diff options
Diffstat (limited to 'src')
124 files changed, 34679 insertions, 18352 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ae647b2d61..fa2dd560a6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ # leave in dependency order, since common must be built first -SUBDIRS = common or tools win32 config -DIST_SUBDIRS = common or tools win32 config +SUBDIRS = common or test tools win32 config +DIST_SUBDIRS = common or test tools win32 config diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 105c413343..b1e03cd710 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -1,5 +1,7 @@ -noinst_LIBRARIES = libor.a libor-crypto.a +noinst_LIBRARIES = libor.a libor-crypto.a libor-event.a + +EXTRA_DIST = common_sha1.i sha256.c #CFLAGS = -Wall -Wpointer-arith -O2 @@ -10,7 +12,21 @@ libor_extra_source= endif libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \ - memarea.c $(libor_extra_source) + memarea.c util_codedigest.c $(libor_extra_source) libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.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 + +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; \ + 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; \ + else \ + rm common_sha1.i; \ + touch common_sha1.i; \ + fi -noinst_HEADERS = address.h log.h crypto.h test.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 +util_codedigest.o: common_sha1.i +crypto.o: sha256.c diff --git a/src/common/address.c b/src/common/address.c index 58ead3075a..c35f04c18b 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -12,7 +12,7 @@ #include "compat.h" #include "util.h" #include "address.h" -#include "log.h" +#include "torlog.h" #ifdef MS_WINDOWS #include <process.h> @@ -726,7 +726,7 @@ tor_addr_is_loopback(const tor_addr_t *addr) } /** Set <b>dest</b> to equal the IPv4 address in <b>v4addr</b> (given in - * network order. */ + * network order). */ void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr) { @@ -760,6 +760,8 @@ tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6) void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src) { + if (src == dest) + return; tor_assert(src); tor_assert(dest); memcpy(dest, src, sizeof(tor_addr_t)); @@ -912,13 +914,6 @@ tor_dup_addr(const tor_addr_t *addr) return tor_strdup(buf); } -/** Copy the address in <b>src</b> to <b>dest</b> */ -void -tor_addr_assign(tor_addr_t *dest, const tor_addr_t *src) -{ - memcpy(dest, src, sizeof(tor_addr_t)); -} - /** Return a string representing the address <b>addr</b>. This string is * statically allocated, and must not be freed. Each call to * <b>fmt_addr</b> invalidates the last result of the function. This diff --git a/src/common/address.h b/src/common/address.h index 352e0d7237..6116bb4b1c 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -107,7 +107,6 @@ 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; -void tor_addr_assign(tor_addr_t *dest, const tor_addr_t *src); const char *fmt_addr(const tor_addr_t *addr); int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr); diff --git a/src/common/aes.c b/src/common/aes.c index 5a6bab242d..a17328317e 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -21,7 +21,7 @@ #include "compat.h" #include "aes.h" #include "util.h" -#include "log.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 @@ -263,7 +263,8 @@ aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) void aes_free_cipher(aes_cnt_cipher_t *cipher) { - tor_assert(cipher); + if (!cipher) + return; #ifdef USE_OPENSSL_EVP EVP_CIPHER_CTX_cleanup(&cipher->key); #endif diff --git a/src/common/compat.c b/src/common/compat.c index 4cc8d99794..8ec4221b22 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -88,7 +88,7 @@ #include <sys/prctl.h> #endif -#include "log.h" +#include "torlog.h" #include "util.h" #include "container.h" #include "address.h" @@ -170,12 +170,17 @@ tor_munmap_file(tor_mmap_t *handle) tor_mmap_t * tor_mmap_file(const char *filename) { + TCHAR tfilename[MAX_PATH]= {0}; tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t)); int empty = 0; res->file_handle = INVALID_HANDLE_VALUE; res->mmap_handle = NULL; - - res->file_handle = CreateFile(filename, +#ifdef UNICODE + mbstowcs(tfilename,filename,MAX_PATH); +#else + strlcpy(tfilename,filename,MAX_PATH); +#endif + res->file_handle = CreateFile(tfilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, @@ -308,6 +313,100 @@ tor_vsnprintf(char *str, size_t size, const char *format, va_list args) return r; } +/** + * Portable asprintf implementation. Does a printf() into a newly malloc'd + * string. Sets *<b>strp</b> to this string, and returns its length (not + * including the terminating NUL character). + * + * You can treat this function as if its implementation were something like + <pre> + char buf[_INFINITY_]; + tor_snprintf(buf, sizeof(buf), fmt, args); + *strp = tor_strdup(buf); + return strlen(*strp): + </pre> + * Where _INFINITY_ is an imaginary constant so big that any string can fit + * into it. + */ +int +tor_asprintf(char **strp, const char *fmt, ...) +{ + int r; + va_list args; + va_start(args, fmt); + r = tor_vasprintf(strp, fmt, args); + va_end(args); + if (!*strp || r < 0) { + log_err(LD_BUG, "Internal error in asprintf"); + tor_assert(0); + } + return r; +} + +/** + * Portable vasprintf implementation. Does a printf() into a newly malloc'd + * string. Differs from regular vasprintf in the same ways that + * tor_asprintf() differs from regular asprintf. + */ +int +tor_vasprintf(char **strp, const char *fmt, va_list args) +{ + /* use a temporary variable in case *strp is in args. */ + char *strp_tmp=NULL; +#ifdef HAVE_VASPRINTF + /* If the platform gives us one, use it. */ + int r = vasprintf(&strp_tmp, fmt, args); + if (r < 0) + *strp = NULL; + else + *strp = strp_tmp; + return r; +#elif defined(_MSC_VER) + /* On Windows, _vsnprintf won't tell us the length of the string if it + * overflows, so we need to use _vcsprintf to tell how much to allocate */ + int len, r; + char *res; + len = _vscprintf(fmt, args); + if (len < 0) { + *strp = NULL; + return -1; + } + strp_tmp = tor_malloc(len + 1); + r = _vsnprintf(strp_tmp, len+1, fmt, args); + if (r != len) { + tor_free(strp_tmp); + *strp = NULL; + return -1; + } + *strp = strp_tmp; + return len; +#else + /* Everywhere else, we have a decent vsnprintf that tells us how many + * characters we need. We give it a try on a short buffer first, since + * it might be nice to avoid the second vsnprintf call. + */ + char buf[128]; + int len, r; + va_list tmp_args; + va_copy(tmp_args, args); + len = vsnprintf(buf, sizeof(buf), fmt, tmp_args); + va_end(tmp_args); + if (len < (int)sizeof(buf)) { + *strp = tor_strdup(buf); + return len; + } + strp_tmp = tor_malloc(len+1); + r = vsnprintf(strp_tmp, len+1, fmt, args); + if (r != len) { + tor_free(strp_tmp); + *strp = NULL; + return -1; + } + *strp = strp_tmp; + return len; +#endif +} + /** Given <b>hlen</b> bytes at <b>haystack</b> and <b>nlen</b> bytes at * <b>needle</b>, return a pointer to the first occurrence of the needle * within the haystack, or NULL if there is no such occurrence. @@ -399,6 +498,37 @@ const char TOR_TOLOWER_TABLE[256] = { 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, }; +/** Implementation of strtok_r for platforms whose coders haven't figured out + * how to write one. Hey guys! You can use this code here for free! */ +char * +tor_strtok_r_impl(char *str, const char *sep, char **lasts) +{ + char *cp, *start; + if (str) + start = cp = *lasts = str; + else if (!*lasts) + return NULL; + else + start = cp = *lasts; + + tor_assert(*sep); + if (sep[1]) { + while (*cp && !strchr(sep, *cp)) + ++cp; + } else { + tor_assert(strlen(sep) == 1); + cp = strchr(cp, *sep); + } + + if (!cp || !*cp) { + *lasts = NULL; + } else { + *cp++ = '\0'; + *lasts = cp; + } + return start; +} + #ifdef MS_WINDOWS /** Take a filename and return a pointer to its final element. This * function is called on __FILE__ to fix a MSVC nit where __FILE__ @@ -450,8 +580,8 @@ get_uint32(const void *cp) return v; } /** - * Read a 32-bit value beginning at <b>cp</b>. Equivalent to - * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid + * Read a 64-bit value beginning at <b>cp</b>. Equivalent to + * *(uint64_t*)(cp), but will not cause segfaults on platforms that forbid * unaligned memory access. */ uint64_t @@ -979,9 +1109,6 @@ set_max_file_descriptors(rlim_t limit, int *max_out) #if defined(CYGWIN) || defined(__CYGWIN__) const char *platform = "Cygwin"; const unsigned long MAX_CONNECTIONS = 3200; -#elif defined(IPHONE) - const char *platform = "iPhone"; - const unsigned long MAX_CONNECTIONS = 9999; #elif defined(MS_WINDOWS) const char *platform = "Windows"; const unsigned long MAX_CONNECTIONS = 15000; @@ -1553,6 +1680,30 @@ tor_lookup_hostname(const char *name, uint32_t *addr) return -1; } +/** Initialize the insecure libc RNG. */ +void +tor_init_weak_random(unsigned seed) +{ +#ifdef MS_WINDOWS + srand(seed); +#else + srandom(seed); +#endif +} + +/** Return a randomly chosen value in the range 0..TOR_RAND_MAX. This + * entropy will not be cryptographically strong; do not rely on it + * for anything an adversary should not be able to predict. */ +long +tor_weak_random(void) +{ +#ifdef MS_WINDOWS + return rand(); +#else + return random(); +#endif +} + /** Hold the result of our call to <b>uname</b>. */ static char uname_result[256]; /** True iff uname_result is set. */ @@ -1578,13 +1729,14 @@ get_uname(void) #ifdef MS_WINDOWS OSVERSIONINFOEX info; int i; - unsigned int leftover_mask; const char *plat = NULL; const char *extra = NULL; + char acsd[MAX_PATH] = {0}; static struct { unsigned major; unsigned minor; const char *version; } win_version_table[] = { - { 6, 0, "Windows \"Longhorn\"" }, + { 6, 1, "Windows 7" }, + { 6, 0, "Windows Vista" }, { 5, 2, "Windows Server 2003" }, { 5, 1, "Windows XP" }, { 5, 0, "Windows 2000" }, @@ -1595,25 +1747,6 @@ get_uname(void) { 3, 51, "Windows NT 3.51" }, { 0, 0, NULL } }; -#ifdef VER_SUITE_BACKOFFICE - static struct { - unsigned int mask; const char *str; - } win_mask_table[] = { - { VER_SUITE_BACKOFFICE, " {backoffice}" }, - { VER_SUITE_BLADE, " {\"blade\" (2003, web edition)}" }, - { VER_SUITE_DATACENTER, " {datacenter}" }, - { VER_SUITE_ENTERPRISE, " {enterprise}" }, - { VER_SUITE_EMBEDDEDNT, " {embedded}" }, - { VER_SUITE_PERSONAL, " {personal}" }, - { VER_SUITE_SINGLEUSERTS, - " {terminal services, single user}" }, - { VER_SUITE_SMALLBUSINESS, " {small business}" }, - { VER_SUITE_SMALLBUSINESS_RESTRICTED, - " {small business, restricted}" }, - { VER_SUITE_TERMINAL, " {terminal services}" }, - { 0, NULL }, - }; -#endif memset(&info, 0, sizeof(info)); info.dwOSVersionInfoSize = sizeof(info); if (! GetVersionEx((LPOSVERSIONINFO)&info)) { @@ -1622,14 +1755,19 @@ get_uname(void) uname_result_is_set = 1; return uname_result; } +#ifdef UNICODE + wcstombs(acsd, info.szCSDVersion, MAX_PATH); +#else + strlcpy(acsd, info.szCSDVersion, sizeof(acsd)); +#endif if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) { if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) plat = "Windows NT 4.0"; else plat = "Windows 95"; - if (info.szCSDVersion[1] == 'B') + if (acsd[1] == 'B') extra = "OSR2 (B)"; - else if (info.szCSDVersion[1] == 'C') + else if (acsd[1] == 'C') extra = "OSR2 (C)"; } else { for (i=0; win_version_table[i].major>0; ++i) { @@ -1641,29 +1779,30 @@ get_uname(void) } } if (plat && !strcmp(plat, "Windows 98")) { - if (info.szCSDVersion[1] == 'A') + if (acsd[1] == 'A') extra = "SE (A)"; - else if (info.szCSDVersion[1] == 'B') + else if (acsd[1] == 'B') extra = "SE (B)"; } if (plat) { if (!extra) - extra = info.szCSDVersion; + extra = acsd; tor_snprintf(uname_result, sizeof(uname_result), "%s %s", plat, extra); } else { if (info.dwMajorVersion > 6 || - (info.dwMajorVersion==6 && info.dwMinorVersion>0)) + (info.dwMajorVersion==6 && info.dwMinorVersion>1)) tor_snprintf(uname_result, sizeof(uname_result), "Very recent version of Windows [major=%d,minor=%d] %s", (int)info.dwMajorVersion,(int)info.dwMinorVersion, - info.szCSDVersion); + acsd); else tor_snprintf(uname_result, sizeof(uname_result), "Unrecognized version of Windows [major=%d,minor=%d] %s", (int)info.dwMajorVersion,(int)info.dwMinorVersion, - info.szCSDVersion); + acsd); } +#if !defined (WINCE) #ifdef VER_SUITE_BACKOFFICE if (info.wProductType == VER_NT_DOMAIN_CONTROLLER) { strlcat(uname_result, " [domain controller]", sizeof(uname_result)); @@ -1672,18 +1811,7 @@ get_uname(void) } else if (info.wProductType == VER_NT_WORKSTATION) { strlcat(uname_result, " [workstation]", sizeof(uname_result)); } - leftover_mask = info.wSuiteMask; - for (i = 0; win_mask_table[i].mask; ++i) { - if (info.wSuiteMask & win_mask_table[i].mask) { - strlcat(uname_result, win_mask_table[i].str, sizeof(uname_result)); - leftover_mask &= ~win_mask_table[i].mask; - } - } - if (leftover_mask) { - size_t len = strlen(uname_result); - tor_snprintf(uname_result+len, sizeof(uname_result)-len, - " {0x%x}", info.wSuiteMask); - } +#endif #endif #else strlcpy(uname_result, "Unknown platform", sizeof(uname_result)); @@ -1793,7 +1921,6 @@ spawn_exit(void) * call _exit, not exit, from child processes. */ _exit(0); #endif - } /** Set *timeval to the current time of day. On error, log and terminate. @@ -1813,8 +1940,15 @@ tor_gettimeofday(struct timeval *timeval) uint64_t ft_64; FILETIME ft_ft; } ft; +#if defined (WINCE) + /* wince do not have GetSystemTimeAsFileTime */ + SYSTEMTIME stime; + GetSystemTime(&stime); + SystemTimeToFileTime(&stime,&ft.ft_ft); +#else /* number of 100-nsec units since Jan 1, 1601 */ GetSystemTimeAsFileTime(&ft.ft_ft); +#endif if (ft.ft_64 < EPOCH_BIAS) { log_err(LD_GENERAL,"System time is before 1970; failing."); exit(1); @@ -2014,6 +2148,8 @@ tor_mutex_new(void) void tor_mutex_free(tor_mutex_t *m) { + if (!m) + return; tor_mutex_uninit(m); tor_free(m); } @@ -2041,7 +2177,8 @@ tor_cond_new(void) void tor_cond_free(tor_cond_t *cond) { - tor_assert(cond); + if (!cond) + return; if (pthread_cond_destroy(&cond->cond)) { log_warn(LD_GENERAL,"Error freeing condition: %s", strerror(errno)); return; @@ -2098,7 +2235,8 @@ tor_cond_new(void) void tor_cond_free(tor_cond_t *cond) { - tor_assert(cond); + if (!cond) + return; DeleteCriticalSection(&cond->mutex); /* XXXX notify? */ smartlist_free(cond->events); @@ -2174,6 +2312,89 @@ tor_threads_init(void) } #endif +#if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK) +/** Attempt to raise the current and max rlimit to infinity for our process. + * This only needs to be done once and can probably only be done when we have + * not already dropped privileges. + */ +static int +tor_set_max_memlock(void) +{ + /* Future consideration for Windows is probably SetProcessWorkingSetSize + * This is similar to setting the memory rlimit of RLIMIT_MEMLOCK + * http://msdn.microsoft.com/en-us/library/ms686234(VS.85).aspx + */ + + struct rlimit limit; + + /* RLIM_INFINITY is -1 on some platforms. */ + limit.rlim_cur = RLIM_INFINITY; + limit.rlim_max = RLIM_INFINITY; + + if (setrlimit(RLIMIT_MEMLOCK, &limit) == -1) { + if (errno == EPERM) { + log_warn(LD_GENERAL, "You appear to lack permissions to change memory " + "limits. Are you root?"); + } + log_warn(LD_GENERAL, "Unable to raise RLIMIT_MEMLOCK: %s", + strerror(errno)); + return -1; + } + + return 0; +} +#endif + +/** Attempt to lock all current and all future memory pages. + * This should only be called once and while we're privileged. + * Like mlockall() we return 0 when we're successful and -1 when we're not. + * Unlike mlockall() we return 1 if we've already attempted to lock memory. + */ +int +tor_mlockall(void) +{ + static int memory_lock_attempted = 0; + + if (memory_lock_attempted) { + return 1; + } + + memory_lock_attempted = 1; + + /* + * Future consideration for Windows may be VirtualLock + * VirtualLock appears to implement mlock() but not mlockall() + * + * http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx + */ + +#if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK) + if (tor_set_max_memlock() == 0) { + log_debug(LD_GENERAL, "RLIMIT_MEMLOCK is now set to RLIM_INFINITY."); + } + + if (mlockall(MCL_CURRENT|MCL_FUTURE) == 0) { + log_info(LD_GENERAL, "Insecure OS paging is effectively disabled."); + return 0; + } else { + if (errno == ENOSYS) { + /* Apple - it's 2009! I'm looking at you. Grrr. */ + log_notice(LD_GENERAL, "It appears that mlockall() is not available on " + "your platform."); + } else if (errno == EPERM) { + log_notice(LD_GENERAL, "It appears that you lack the permissions to " + "lock memory. Are you root?"); + } + log_notice(LD_GENERAL, "Unable to lock all current and future memory " + "pages: %s", strerror(errno)); + return -1; + } +#else + log_warn(LD_GENERAL, "Unable to lock memory pages. mlockall() unsupported?"); + return -1; +#endif +} + /** Identity of the "main" thread */ static unsigned long main_thread_id = -1; @@ -2325,20 +2546,26 @@ network_init(void) char * format_win32_error(DWORD err) { - LPVOID str = NULL; + TCHAR *str = NULL; char *result; /* Somebody once decided that this interface was better than strerror(). */ - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &str, + (LPVOID)&str, 0, NULL); if (str) { - result = tor_strdup((char*)str); +#ifdef UNICODE + char abuf[1024] = {0}; + wcstombs(abuf,str,1024); + result = tor_strdup(abuf); +#else + result = tor_strdup(str); +#endif LocalFree(str); /* LocalFree != free() */ } else { result = tor_strdup("<unformattable error>"); diff --git a/src/common/compat.h b/src/common/compat.h index 209d9fc38b..03e0686e8d 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -51,6 +51,22 @@ #include <netinet6/in6.h> #endif +#if defined (WINCE) +#include <fcntl.h> +#include <io.h> +#include <math.h> +#include <projects.h> +#define snprintf _snprintf +/* this is not exported as W .... */ +#define SHGetPathFromIDListW SHGetPathFromIDList +/* wcecompat has vasprintf */ +#define HAVE_VASPRINTF +/* no service here */ +#ifdef NT_SERVICE +#undef NT_SERVICE +#endif +#endif // WINCE + #ifndef NULL_REP_IS_ZERO_BYTES #error "It seems your platform does not represent NULL as zero. We can't cope." #endif @@ -177,8 +193,8 @@ extern INLINE double U64_TO_DBL(uint64_t x) { /* ===== String compatibility */ #ifdef MS_WINDOWS /* Windows names string functions differently from most other platforms. */ -#define strncasecmp strnicmp -#define strcasecmp stricmp +#define strncasecmp _strnicmp +#define strcasecmp _stricmp #endif #ifndef HAVE_STRLCAT size_t strlcat(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2)); @@ -196,18 +212,26 @@ size_t strlcpy(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2)); #define U64_SCANF_ARG(a) (a) /** Expands to a literal uint64_t-typed constant for the value <b>n</b>. */ #define U64_LITERAL(n) (n ## ui64) +#define I64_PRINTF_ARG(a) (a) +#define I64_SCANF_ARG(a) (a) +#define I64_LITERAL(n) (n ## i64) #else #define U64_PRINTF_ARG(a) ((long long unsigned int)(a)) #define U64_SCANF_ARG(a) ((long long unsigned int*)(a)) #define U64_LITERAL(n) (n ## llu) +#define I64_PRINTF_ARG(a) ((long long signed int)(a)) +#define I64_SCANF_ARG(a) ((long long signed int*)(a)) +#define I64_LITERAL(n) (n ## ll) #endif #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) /** The formatting string used to put a uint64_t value in a printf() or * scanf() function. See also U64_PRINTF_ARG and U64_SCANF_ARG. */ #define U64_FORMAT "%I64u" +#define I64_FORMAT "%I64d" #else #define U64_FORMAT "%llu" +#define I64_FORMAT "%lld" #endif /** Represents an mmaped file. Allocated via tor_mmap_file; freed with @@ -235,6 +259,10 @@ int tor_snprintf(char *str, size_t size, const char *format, ...) int tor_vsnprintf(char *str, size_t size, const char *format, va_list args) ATTR_NONNULL((1,3)); +int tor_asprintf(char **strp, const char *fmt, ...) + CHECK_PRINTF(2,3); +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)); static const void *tor_memstr(const void *haystack, size_t hlen, @@ -267,6 +295,13 @@ extern const char TOR_TOLOWER_TABLE[]; #define TOR_TOLOWER(c) (TOR_TOLOWER_TABLE[(uint8_t)c]) #define TOR_TOUPPER(c) (TOR_TOUPPER_TABLE[(uint8_t)c]) +char *tor_strtok_r_impl(char *str, const char *sep, char **lasts); +#ifdef HAVE_STRTOK_R +#define tor_strtok_r(str, sep, lasts) strtok_r(str, sep, lasts) +#else +#define tor_strtok_r(str, sep, lasts) tor_strtok_r_impl(str, sep, lasts) +#endif + #ifdef MS_WINDOWS #define _SHORT_FILE_ (tor_fix_source_file(__FILE__)) const char *tor_fix_source_file(const char *fname); @@ -445,6 +480,11 @@ typedef enum { SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08, } socks5_reply_status_t; +/* ===== Insecure rng */ +void tor_init_weak_random(unsigned seed); +long tor_weak_random(void); +#define TOR_RAND_MAX (RAND_MAX) + /* ===== OS compatibility */ const char *get_uname(void); @@ -502,6 +542,8 @@ typedef struct tor_mutex_t { #endif } tor_mutex_t; +int tor_mlockall(void); + #ifdef TOR_IS_MULTITHREADED tor_mutex_t *tor_mutex_new(void); void tor_mutex_init(tor_mutex_t *m); @@ -536,6 +578,19 @@ void tor_cond_signal_all(tor_cond_t *cond); #endif #endif +/** Macros for MIN/MAX. Never use these when the arguments could have + * side-effects. + * {With GCC extensions we could probably define a safer MIN/MAX. But + * depending on that safety would be dangerous, since not every platform + * has it.} + **/ +#ifndef MAX +#define MAX(a,b) ( ((a)<(b)) ? (b) : (a) ) +#endif +#ifndef MIN +#define MIN(a,b) ( ((a)>(b)) ? (b) : (a) ) +#endif + /* Platform-specific helpers. */ #ifdef MS_WINDOWS char *format_win32_error(DWORD err); diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c new file mode 100644 index 0000000000..250fa2bdb7 --- /dev/null +++ b/src/common/compat_libevent.c @@ -0,0 +1,553 @@ +/* Copyright (c) 2009-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file compat_libevent.c + * \brief Wrappers to handle porting between different versions of libevent. + * + * In an ideal world, we'd just use Libevent 2.0 from now on. But as of June + * 2009, Libevent 2.0 is still in alpha, and we will have old versions of + * Libevent for the forseeable future. + **/ + +#include "orconfig.h" +#include "compat.h" +#include "compat_libevent.h" + +#include "util.h" +#include "torlog.h" + +#ifdef HAVE_EVENT2_EVENT_H +#include <event2/event.h> +#else +#include <event.h> +#endif + +/** A number representing a version of Libevent. + + This is a 4-byte number, with the first three bytes representing the + major, minor, and patchlevel respectively of the library. The fourth + byte is unused. + + This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent + 2.0.1 or later. For versions of Libevent before 1.4.0, which followed the + format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a + to be equivalent to 1.0.1, and so on. +*/ +typedef uint32_t le_version_t; + +/* Macros: returns the number of a libevent version. */ +#define V(major, minor, patch) \ + (((major) << 24) | ((minor) << 16) | ((patch) << 8)) +#define V_OLD(major, minor, patch) \ + V((major), (minor), (patch)-'a'+1) + +#define LE_OLD V(0,0,0) +#define LE_OTHER V(0,0,99) + +static le_version_t tor_get_libevent_version(const char **v_out); + +#ifdef HAVE_EVENT_SET_LOG_CALLBACK +/** A string which, if it appears in a libevent log, should be ignored. */ +static const char *suppress_msg = NULL; +/** Callback function passed to event_set_log() so we can intercept + * log messages from libevent. */ +static void +libevent_logging_callback(int severity, const char *msg) +{ + char buf[1024]; + size_t n; + if (suppress_msg && strstr(msg, suppress_msg)) + return; + n = strlcpy(buf, msg, sizeof(buf)); + if (n && n < sizeof(buf) && buf[n-1] == '\n') { + buf[n-1] = '\0'; + } + switch (severity) { + case _EVENT_LOG_DEBUG: + log(LOG_DEBUG, LD_NET, "Message from libevent: %s", buf); + break; + case _EVENT_LOG_MSG: + log(LOG_INFO, LD_NET, "Message from libevent: %s", buf); + break; + case _EVENT_LOG_WARN: + log(LOG_WARN, LD_GENERAL, "Warning from libevent: %s", buf); + break; + case _EVENT_LOG_ERR: + log(LOG_ERR, LD_GENERAL, "Error from libevent: %s", buf); + break; + default: + log(LOG_WARN, LD_GENERAL, "Message [%d] from libevent: %s", + severity, buf); + break; + } +} +/** Set hook to intercept log messages from libevent. */ +void +configure_libevent_logging(void) +{ + event_set_log_callback(libevent_logging_callback); +} +/** Ignore any libevent log message that contains <b>msg</b>. */ +void +suppress_libevent_log_msg(const char *msg) +{ + suppress_msg = msg; +} +#else +void +configure_libevent_logging(void) +{ +} +void +suppress_libevent_log_msg(const char *msg) +{ + (void)msg; +} +#endif + +#ifndef HAVE_EVENT2_EVENT_H +/** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */ +struct event * +tor_event_new(struct event_base *base, int sock, short what, + void (*cb)(int, short, void *), void *arg) +{ + struct event *e = tor_malloc_zero(sizeof(struct event)); + event_set(e, sock, what, cb, arg); + if (! base) + base = tor_libevent_get_base(); + event_base_set(base, e); + return e; +} +/** Work-alike replacement for evtimer_new() on pre-Libevent-2.0 systems. */ +struct event * +tor_evtimer_new(struct event_base *base, + void (*cb)(int, short, void *), void *arg) +{ + return tor_event_new(base, -1, 0, cb, arg); +} +/** Work-alike replacement for evsignal_new() on pre-Libevent-2.0 systems. */ +struct event * +tor_evsignal_new(struct event_base * base, int sig, + void (*cb)(int, short, void *), void *arg) +{ + return tor_event_new(base, sig, EV_SIGNAL|EV_PERSIST, cb, arg); +} +/** Work-alike replacement for event_free() on pre-Libevent-2.0 systems. */ +void +tor_event_free(struct event *ev) +{ + event_del(ev); + tor_free(ev); +} +#endif + +/** Global event base for use by the main thread. */ +struct event_base *the_event_base = NULL; + +/* This is what passes for version detection on OSX. We set + * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before + * 10.4.0 (aka 1040). */ +#ifdef __APPLE__ +#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +#define MACOSX_KQUEUE_IS_BROKEN \ + (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040) +#else +#define MACOSX_KQUEUE_IS_BROKEN 0 +#endif +#endif + +/** Initialize the Libevent library and set up the event base. */ +void +tor_libevent_initialize(void) +{ + tor_assert(the_event_base == NULL); + +#ifdef __APPLE__ + if (MACOSX_KQUEUE_IS_BROKEN || + tor_get_libevent_version(NULL) < V_OLD(1,1,'b')) { + setenv("EVENT_NOKQUEUE","1",1); + } +#endif + +#ifdef HAVE_EVENT2_EVENT_H + the_event_base = event_base_new(); +#else + the_event_base = event_init(); +#endif + +#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. */ + log(LOG_NOTICE, LD_GENERAL, + "Initialized libevent version %s using method %s. Good.", + event_get_version(), tor_libevent_get_method()); +#else + log(LOG_NOTICE, LD_GENERAL, + "Initialized old libevent (version 1.0b or earlier)."); + log(LOG_WARN, LD_GENERAL, + "You have a *VERY* old version of libevent. It is likely to be buggy; " + "please build Tor with a more recent version."); +#endif +} + +/** Return the current Libevent event base that we're set up to use. */ +struct event_base * +tor_libevent_get_base(void) +{ + return the_event_base; +} + +#ifndef HAVE_EVENT_BASE_LOOPEXIT +/* Replacement for event_base_loopexit on some very old versions of Libevent + that we are not yet brave enough to deprecate. */ +int +tor_event_base_loopexit(struct event_base *base, struct timeval *tv) +{ + tor_assert(base == the_event_base); + return event_loopexit(tv); +} +#endif + +/** Return the name of the Libevent backend we're using. */ +const char * +tor_libevent_get_method(void) +{ +#ifdef HAVE_EVENT2_EVENT_H + return event_base_get_method(the_event_base); +#elif defined(HAVE_EVENT_GET_METHOD) + return event_get_method(); +#else + return "<unknown>"; +#endif +} + +/** Return the le_version_t for the current version of libevent. If the + * version is very new, return LE_OTHER. If the version is so old that it + * doesn't support event_get_version(), return LE_OLD. DOCDOC */ +static le_version_t +tor_decode_libevent_version(const char *v) +{ + unsigned major, minor, patchlevel; + char c, e, extra; + int fields; + + /* 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); + if (fields == 3 || + ((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) || + (fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) { + return V(major,minor,patchlevel); + } + + /* Try the old "1.3e" format. */ + fields = 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) { + return V(major, minor, 0); + } + + return LE_OTHER; +} + +/** Return an integer representing the binary interface of a Libevent library. + * Two different versions with different numbers are sure not to be binary + * compatible. Two different versions with the same numbers have a decent + * chance of binary compatibility.*/ +static int +le_versions_compatibility(le_version_t v) +{ + if (v == LE_OTHER) + return 0; + if (v < V_OLD(1,0,'c')) + return 1; + else if (v < V(1,4,0)) + return 2; + else if (v < V(1,4,99)) + return 3; + else if (v < V(2,0,1)) + return 4; + else /* Everything 2.0 and later should be compatible. */ + return 5; +} + +/** Return the version number of the currently running version of Libevent. + See le_version_t for info on the format. + */ +static le_version_t +tor_get_libevent_version(const char **v_out) +{ + const char *v; + le_version_t r; +#if defined(HAVE_EVENT_GET_VERSION_NUMBER) + v = event_get_version(); + r = event_get_version_number(); +#elif defined (HAVE_EVENT_GET_VERSION) + v = event_get_version(); + r = tor_decode_libevent_version(v); +#else + v = "pre-1.0c"; + r = LE_OLD; +#endif + if (v_out) + *v_out = v; + return r; +} + +/** Return a string representation of the version of the currently running + * version of Libevent. */ +const char * +tor_libevent_get_version_str(void) +{ +#ifdef HAVE_EVENT_GET_VERSION + return event_get_version(); +#else + return "pre-1.0c"; +#endif +} + +/** + * Compare the current Libevent method and version to a list of versions + * which are known not to work. Warn the user as appropriate. + */ +void +tor_check_libevent_version(const char *m, int server, + const char **badness_out) +{ + int buggy = 0, iffy = 0, slow = 0, thread_unsafe = 0; + le_version_t version; + const char *v = NULL; + const char *badness = NULL; + const char *sad_os = ""; + + version = tor_get_libevent_version(&v); + + /* XXX Would it be worthwhile disabling the methods that we know + * are buggy, rather than just warning about them and then proceeding + * to use them? If so, we should probably not wrap this whole thing + * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */ + /* XXXX The problem is that it's not trivial to get libevent to change it's + * method once it's initialized, and it's not trivial to tell what method it + * will use without initializing it. I guess we could preemptively disable + * buggy libevent modes based on the version _before_ initializing it, + * though, but then there's no good way (afaict) to warn "I would have used + * kqueue, but instead I'm using select." -NM */ + /* XXXX022 revist the above; it is fixable now. */ + if (!strcmp(m, "kqueue")) { + if (version < V_OLD(1,1,'b')) + buggy = 1; + } else if (!strcmp(m, "epoll")) { + if (version < V(1,1,0)) + iffy = 1; + } else if (!strcmp(m, "poll")) { + if (version < V_OLD(1,0,'e')) + buggy = 1; + if (version < V(1,1,0)) + slow = 1; + } else if (!strcmp(m, "select")) { + if (version < V(1,1,0)) + slow = 1; + } else if (!strcmp(m, "win32")) { + if (version < V_OLD(1,1,'b')) + buggy = 1; + } + + /* Libevent versions before 1.3b do very badly on operating systems with + * user-space threading implementations. */ +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) + if (server && version < V_OLD(1,3,'b')) { + thread_unsafe = 1; + sad_os = "BSD variants"; + } +#elif defined(__APPLE__) || defined(__darwin__) + if (server && version < V_OLD(1,3,'b')) { + thread_unsafe = 1; + sad_os = "Mac OS X"; + } +#endif + + if (thread_unsafe) { + log(LOG_WARN, LD_GENERAL, + "Libevent version %s often crashes when running a Tor server with %s. " + "Please use the latest version of libevent (1.3b or later)",v,sad_os); + badness = "BROKEN"; + } else if (buggy) { + log(LOG_WARN, LD_GENERAL, + "There are serious bugs in using %s with libevent %s. " + "Please use the latest version of libevent.", m, v); + badness = "BROKEN"; + } else if (iffy) { + log(LOG_WARN, LD_GENERAL, + "There are minor bugs in using %s with libevent %s. " + "You may want to use the latest version of libevent.", m, v); + badness = "BUGGY"; + } else if (slow && server) { + log(LOG_WARN, LD_GENERAL, + "libevent %s can be very slow with %s. " + "When running a server, please use the latest version of libevent.", + v,m); + badness = "SLOW"; + } + + *badness_out = badness; +} + +#if defined(LIBEVENT_VERSION) +#define HEADER_VERSION LIBEVENT_VERSION +#elif defined(_EVENT_VERSION) +#define HEADER_VERSION _EVENT_VERSION +#endif + +/** See whether the headers we were built against differ from the library we + * linked against so much that we're likely to crash. If so, warn the + * user. */ +void +tor_check_libevent_header_compatibility(void) +{ + (void) le_versions_compatibility; + (void) tor_decode_libevent_version; + + /* In libevent versions before 2.0, it's hard to keep binary compatibility + * between upgrades, and unpleasant to detect when the version we compiled + * against is unlike the version we have linked against. Here's how. */ +#if defined(HEADER_VERSION) && defined(HAVE_EVENT_GET_VERSION) + /* We have a header-file version and a function-call version. Easy. */ + if (strcmp(HEADER_VERSION, event_get_version())) { + le_version_t v1, v2; + int compat1 = -1, compat2 = -1; + int verybad; + v1 = tor_decode_libevent_version(HEADER_VERSION); + v2 = tor_decode_libevent_version(event_get_version()); + compat1 = le_versions_compatibility(v1); + compat2 = le_versions_compatibility(v2); + + verybad = compat1 != compat2; + + log(verybad ? LOG_WARN : LOG_NOTICE, + LD_GENERAL, "We were compiled with headers from version %s " + "of Libevent, but we're using a Libevent library that says it's " + "version %s.", HEADER_VERSION, event_get_version()); + if (verybad) + log_warn(LD_GENERAL, "This will almost certainly make Tor crash."); + else + log_info(LD_GENERAL, "I think these versions are binary-compatible."); + } +#elif defined(HAVE_EVENT_GET_VERSION) + /* event_get_version but no _EVENT_VERSION. We might be in 1.4.0-beta or + earlier, where that's normal. To see whether we were compiled with an + earlier version, let's see whether the struct event defines MIN_HEAP_IDX. + */ +#ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX + /* The header files are 1.4.0-beta or later. If the version is not + * 1.4.0-beta, we are incompatible. */ + { + if (strcmp(event_get_version(), "1.4.0-beta")) { + log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have " + "Libevent 1.4.0-beta header files, whereas you have linked " + "against Libevent %s. This will probably make Tor crash.", + event_get_version()); + } + } +#else + /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or + later, we're probably fine. */ + { + const char *v = event_get_version(); + if ((v[0] == '1' && v[2] == '.' && v[3] > '3') || v[0] > '1') { + log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have " + "Libevent header file from 1.3e or earlier, whereas you have " + "linked against Libevent %s. This will probably make Tor " + "crash.", event_get_version()); + } + } +#endif + +#elif defined(HEADER_VERSION) +#warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd." +#else + /* Your libevent is ancient. */ +#endif +} + +/* + 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 + called exactly M seconds apart, rather than starting each one exactly M + seconds after the time that the last one was run. + */ +#ifdef HAVE_EVENT2_EVENT_H +#define HAVE_PERIODIC +#define PERIODIC_FLAGS EV_PERSIST +#else +#define PERIODIC_FLAGS 0 +#endif + +/** Represents a timer that's run every N microseconds by Libevent. */ +struct periodic_timer_t { + /** Underlying event used to implement this periodic event. */ + struct event *ev; + /** The callback we'll be invoking whenever the event triggers */ + void (*cb)(struct periodic_timer_t *, void *); + /** User-supplied data for the callback */ + void *data; +#ifndef HAVE_PERIODIC + /** If Libevent doesn't know how to invoke events every N microseconds, + * we'll need to remember the timeout interval here. */ + struct timeval tv; +#endif +}; + +/** Libevent callback to implement a periodic event. */ +static void +periodic_timer_cb(evutil_socket_t fd, short what, void *arg) +{ + periodic_timer_t *timer = arg; + (void) what; + (void) fd; +#ifndef HAVE_PERIODIC + /** reschedule the event as needed. */ + event_add(timer->ev, &timer->tv); +#endif + timer->cb(timer, timer->data); +} + +/** Create and schedule a new timer that will run every <b>tv</b> in + * the event loop of <b>base</b>. When the timer fires, it will + * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */ +periodic_timer_t * +periodic_timer_new(struct event_base *base, + const struct timeval *tv, + void (*cb)(periodic_timer_t *timer, void *data), + void *data) +{ + periodic_timer_t *timer; + tor_assert(base); + tor_assert(tv); + tor_assert(cb); + timer = tor_malloc_zero(sizeof(periodic_timer_t)); + if (!(timer->ev = tor_event_new(base, -1, PERIODIC_FLAGS, + periodic_timer_cb, timer))) { + tor_free(timer); + return NULL; + } + timer->cb = cb; + timer->data = data; +#ifndef HAVE_PERIODIC + memcpy(&timer->tv, tv, sizeof(struct timeval)); +#endif + event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/ + return timer; +} + +/** Stop and free a periodic timer */ +void +periodic_timer_free(periodic_timer_t *timer) +{ + if (!timer) + return; + tor_event_free(timer->ev); + tor_free(timer); +} + diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h new file mode 100644 index 0000000000..fdf5e0a18f --- /dev/null +++ b/src/common/compat_libevent.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2009, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef _TOR_COMPAT_LIBEVENT_H +#define _TOR_COMPAT_LIBEVENT_H + +#include "orconfig.h" + +struct event; +struct event_base; + +#ifdef HAVE_EVENT2_EVENT_H +#include <event2/util.h> +#else +#define evutil_socket_t int +#endif + +void configure_libevent_logging(void); +void suppress_libevent_log_msg(const char *msg); + +#ifdef HAVE_EVENT2_EVENT_H +#define tor_event_new event_new +#define tor_evtimer_new evtimer_new +#define tor_evsignal_new evsignal_new +#define tor_event_free event_free +#define tor_evdns_add_server_port(sock, tcp, cb, data) \ + evdns_add_server_port_with_base(tor_libevent_get_base(), \ + (sock),(tcp),(cb),(data)); + +#else +struct event *tor_event_new(struct event_base * base, evutil_socket_t sock, + short what, void (*cb)(evutil_socket_t, short, void *), void *arg); +struct event *tor_evtimer_new(struct event_base * base, + void (*cb)(evutil_socket_t, short, void *), void *arg); +struct event *tor_evsignal_new(struct event_base * base, int sig, + void (*cb)(evutil_socket_t, short, void *), void *arg); +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; + +periodic_timer_t *periodic_timer_new(struct event_base *base, + const struct timeval *tv, + void (*cb)(periodic_timer_t *timer, void *data), + void *data); +void periodic_timer_free(periodic_timer_t *); + +#ifdef HAVE_EVENT_BASE_LOOPEXIT +#define tor_event_base_loopexit event_base_loopexit +#else +struct timeval; +int tor_event_base_loopexit(struct event_base *base, struct timeval *tv); +#endif + +void tor_libevent_initialize(void); +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, + const char **badness_out); +void tor_check_libevent_header_compatibility(void); +const char *tor_libevent_get_version_str(void); + +#endif + diff --git a/src/common/container.c b/src/common/container.c index 08fab5ced1..72f3470344 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -13,7 +13,7 @@ #include "compat.h" #include "util.h" -#include "log.h" +#include "torlog.h" #include "container.h" #include "crypto.h" @@ -44,7 +44,8 @@ smartlist_create(void) void smartlist_free(smartlist_t *sl) { - tor_assert(sl != NULL); + if (!sl) + return; tor_free(sl->list); tor_free(sl); } @@ -459,6 +460,42 @@ smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b)) (int (*)(const void *,const void*))compare); } +/** Given a smartlist <b>sl</b> sorted with the function <b>compare</b>, + * return the most frequent member in the list. Break ties in favor of + * later elements. If the list is empty, return NULL. + */ +void * +smartlist_get_most_frequent(const smartlist_t *sl, + int (*compare)(const void **a, const void **b)) +{ + const void *most_frequent = NULL; + int most_frequent_count = 0; + + const void *cur = NULL; + int i, count=0; + + if (!sl->num_used) + return NULL; + for (i = 0; i < sl->num_used; ++i) { + const void *item = sl->list[i]; + if (cur && 0 == compare(&cur, &item)) { + ++count; + } else { + if (cur && count >= most_frequent_count) { + most_frequent = cur; + most_frequent_count = count; + } + cur = item; + count = 1; + } + } + if (cur && count >= most_frequent_count) { + most_frequent = cur; + most_frequent_count = count; + } + return (void*)most_frequent; +} + /** Given a sorted smartlist <b>sl</b> and the comparison function used to * sort it, remove all duplicate members. If free_fn is provided, calls * free_fn on each duplicate. Otherwise, just removes them. Preserves order. @@ -550,6 +587,13 @@ smartlist_sort_strings(smartlist_t *sl) smartlist_sort(sl, _compare_string_ptrs); } +/** Return the most frequent string in the sorted list <b>sl</b> */ +char * +smartlist_get_most_frequent_string(smartlist_t *sl) +{ + return smartlist_get_most_frequent(sl, _compare_string_ptrs); +} + /** Remove duplicate strings from a sorted list, and free them with tor_free(). */ void @@ -561,6 +605,38 @@ smartlist_uniq_strings(smartlist_t *sl) /* Heap-based priority queue implementation for O(lg N) insert and remove. * Recall that the heap property is that, for every index I, h[I] < * H[LEFT_CHILD[I]] and h[I] < H[RIGHT_CHILD[I]]. + * + * For us to remove items other than the topmost item, each item must store + * its own index within the heap. When calling the pqueue functions, tell + * them about the offset of the field that stores the index within the item. + * + * Example: + * + * typedef struct timer_t { + * struct timeval tv; + * int heap_index; + * } timer_t; + * + * static int compare(const void *p1, const void *p2) { + * const timer_t *t1 = p1, *t2 = p2; + * if (t1->tv.tv_sec < t2->tv.tv_sec) { + * return -1; + * } else if (t1->tv.tv_sec > t2->tv.tv_sec) { + * return 1; + * } else { + * return t1->tv.tv_usec - t2->tv_usec; + * } + * } + * + * void timer_heap_insert(smartlist_t *heap, timer_t *timer) { + * smartlist_pqueue_add(heap, compare, STRUCT_OFFSET(timer_t, heap_index), + * timer); + * } + * + * void timer_heap_pop(smartlist_t *heap) { + * return smartlist_pqueue_pop(heap, compare, + * STRUCT_OFFSET(timer_t, heap_index)); + * } */ /* For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x] @@ -572,12 +648,22 @@ smartlist_uniq_strings(smartlist_t *sl) #define RIGHT_CHILD(i) ( 2*(i) + 2 ) #define PARENT(i) ( ((i)-1) / 2 ) +#define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset)) + +#define UPDATE_IDX(i) do { \ + void *updated = sl->list[i]; \ + *IDXP(updated) = i; \ + } while (0) + +#define IDX_OF_ITEM(p) (*IDXP(p)) + /** Helper. <b>sl</b> may have at most one violation of the heap property: * the item at <b>idx</b> may be greater than one or both of its children. * Restore the heap property. */ static INLINE void smartlist_heapify(smartlist_t *sl, int (*compare)(const void *a, const void *b), + int idx_field_offset, int idx) { while (1) { @@ -600,21 +686,28 @@ smartlist_heapify(smartlist_t *sl, void *tmp = sl->list[idx]; sl->list[idx] = sl->list[best_idx]; sl->list[best_idx] = tmp; + UPDATE_IDX(idx); + UPDATE_IDX(best_idx); idx = best_idx; } } } -/** Insert <b>item</b> into the heap stored in <b>sl</b>, where order - * is determined by <b>compare</b>. */ +/** Insert <b>item</b> into the heap stored in <b>sl</b>, where order is + * determined by <b>compare</b> and the offset of the item in the heap is + * stored in an int-typed field at position <b>idx_field_offset</b> within + * item. + */ void smartlist_pqueue_add(smartlist_t *sl, int (*compare)(const void *a, const void *b), + int idx_field_offset, void *item) { int idx; smartlist_add(sl,item); + UPDATE_IDX(sl->num_used-1); for (idx = sl->num_used - 1; idx; ) { int parent = PARENT(idx); @@ -622,6 +715,8 @@ smartlist_pqueue_add(smartlist_t *sl, void *tmp = sl->list[parent]; sl->list[parent] = sl->list[idx]; sl->list[idx] = tmp; + UPDATE_IDX(parent); + UPDATE_IDX(idx); idx = parent; } else { return; @@ -630,32 +725,63 @@ smartlist_pqueue_add(smartlist_t *sl, } /** Remove and return the top-priority item from the heap stored in <b>sl</b>, - * where order is determined by <b>compare</b>. <b>sl</b> must not be - * empty. */ + * where order is determined by <b>compare</b> and the item's position is + * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must + * not be empty. */ void * smartlist_pqueue_pop(smartlist_t *sl, - int (*compare)(const void *a, const void *b)) + int (*compare)(const void *a, const void *b), + int idx_field_offset) { void *top; tor_assert(sl->num_used); top = sl->list[0]; + *IDXP(top)=-1; if (--sl->num_used) { sl->list[0] = sl->list[sl->num_used]; - smartlist_heapify(sl, compare, 0); + UPDATE_IDX(0); + smartlist_heapify(sl, compare, idx_field_offset, 0); } return top; } +/** Remove the item <b>item</b> from the heap stored in <b>sl</b>, + * where order is determined by <b>compare</b> and the item's position is + * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must + * not be empty. */ +void +smartlist_pqueue_remove(smartlist_t *sl, + int (*compare)(const void *a, const void *b), + int idx_field_offset, + void *item) +{ + int idx = IDX_OF_ITEM(item); + tor_assert(idx >= 0); + tor_assert(sl->list[idx] == item); + --sl->num_used; + *IDXP(item) = -1; + if (idx == sl->num_used) { + return; + } else { + sl->list[idx] = sl->list[sl->num_used]; + UPDATE_IDX(idx); + smartlist_heapify(sl, compare, idx_field_offset, idx); + } +} + /** Assert that the heap property is correctly maintained by the heap stored * in <b>sl</b>, where order is determined by <b>compare</b>. */ void smartlist_pqueue_assert_ok(smartlist_t *sl, - int (*compare)(const void *a, const void *b)) + int (*compare)(const void *a, const void *b), + int idx_field_offset) { int i; - for (i = sl->num_used - 1; i > 0; --i) { - tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0); + for (i = sl->num_used - 1; i >= 0; --i) { + if (i>0) + tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0); + tor_assert(IDX_OF_ITEM(sl->list[i]) == i); } } @@ -681,6 +807,37 @@ smartlist_uniq_digests(smartlist_t *sl) smartlist_uniq(sl, _compare_digests, _tor_free); } +/** Helper: compare two DIGEST256_LEN digests. */ +static int +_compare_digests256(const void **_a, const void **_b) +{ + return memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN); +} + +/** Sort the list of DIGEST256_LEN-byte digests into ascending order. */ +void +smartlist_sort_digests256(smartlist_t *sl) +{ + smartlist_sort(sl, _compare_digests256); +} + +/** Return the most frequent member of the sorted list of DIGEST256_LEN + * digests in <b>sl</b> */ +char * +smartlist_get_most_frequent_digest256(smartlist_t *sl) +{ + return smartlist_get_most_frequent(sl, _compare_digests256); +} + +/** Remove duplicate 256-bit digests from a sorted list, and free them with + * tor_free(). + */ +void +smartlist_uniq_digests256(smartlist_t *sl) +{ + smartlist_uniq(sl, _compare_digests256, _tor_free); +} + /** Helper: Declare an entry type and a map type to implement a mapping using * ht.h. The map type will be called <b>maptype</b>. The key part of each * entry is declared using the C declaration <b>keydecl</b>. All functions @@ -1113,6 +1270,9 @@ void strmap_free(strmap_t *map, void (*free_val)(void*)) { strmap_entry_t **ent, **next, *this; + if (!map) + return; + for (ent = HT_START(strmap_impl, &map->head); ent != NULL; ent = next) { this = *ent; next = HT_NEXT_RMV(strmap_impl, &map->head, ent); @@ -1134,6 +1294,8 @@ void digestmap_free(digestmap_t *map, void (*free_val)(void*)) { digestmap_entry_t **ent, **next, *this; + if (!map) + return; for (ent = HT_START(digestmap_impl, &map->head); ent != NULL; ent = next) { this = *ent; next = HT_NEXT_RMV(digestmap_impl, &map->head, ent); @@ -1220,6 +1382,7 @@ IMPLEMENT_ORDER_FUNC(find_nth_int, int) IMPLEMENT_ORDER_FUNC(find_nth_time, time_t) IMPLEMENT_ORDER_FUNC(find_nth_double, double) IMPLEMENT_ORDER_FUNC(find_nth_uint32, uint32_t) +IMPLEMENT_ORDER_FUNC(find_nth_int32, int32_t) IMPLEMENT_ORDER_FUNC(find_nth_long, long) /** Return a newly allocated digestset_t, optimized to hold a total of @@ -1248,6 +1411,8 @@ digestset_new(int max_elements) void digestset_free(digestset_t *set) { + if (!set) + return; bitarray_free(set->ba); tor_free(set); } diff --git a/src/common/container.h b/src/common/container.h index c42b86977d..3568de0159 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -93,13 +93,22 @@ void smartlist_del_keeporder(smartlist_t *sl, int idx); void smartlist_insert(smartlist_t *sl, int idx, void *val); void smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b)); +void *smartlist_get_most_frequent(const smartlist_t *sl, + int (*compare)(const void **a, const void **b)); void smartlist_uniq(smartlist_t *sl, int (*compare)(const void **a, const void **b), void (*free_fn)(void *elt)); + void smartlist_sort_strings(smartlist_t *sl); void smartlist_sort_digests(smartlist_t *sl); +void smartlist_sort_digests256(smartlist_t *sl); + +char *smartlist_get_most_frequent_string(smartlist_t *sl); +char *smartlist_get_most_frequent_digest256(smartlist_t *sl); + 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; @@ -109,11 +118,18 @@ int smartlist_bsearch_idx(const smartlist_t *sl, const void *key, void smartlist_pqueue_add(smartlist_t *sl, int (*compare)(const void *a, const void *b), + int idx_field_offset, void *item); void *smartlist_pqueue_pop(smartlist_t *sl, - int (*compare)(const void *a, const void *b)); + int (*compare)(const void *a, const void *b), + int idx_field_offset); +void smartlist_pqueue_remove(smartlist_t *sl, + int (*compare)(const void *a, const void *b), + int idx_field_offset, + void *item); void smartlist_pqueue_assert_ok(smartlist_t *sl, - int (*compare)(const void *a, const void *b)); + int (*compare)(const void *a, const void *b), + int idx_field_offset); #define SPLIT_SKIP_SPACE 0x01 #define SPLIT_IGNORE_BLANK 0x02 @@ -627,6 +643,7 @@ void digestset_free(digestset_t* set); int find_nth_int(int *array, int n_elements, int nth); time_t find_nth_time(time_t *array, int n_elements, int nth); double find_nth_double(double *array, int n_elements, int nth); +int32_t find_nth_int32(int32_t *array, int n_elements, int nth); uint32_t find_nth_uint32(uint32_t *array, int n_elements, int nth); long find_nth_long(long *array, int n_elements, int nth); static INLINE int @@ -649,6 +666,11 @@ median_uint32(uint32_t *array, int n_elements) { return find_nth_uint32(array, n_elements, (n_elements-1)/2); } +static INLINE int32_t +median_int32(int32_t *array, int n_elements) +{ + return find_nth_int32(array, n_elements, (n_elements-1)/2); +} static INLINE long median_long(long *array, int n_elements) { diff --git a/src/common/crypto.c b/src/common/crypto.c index 751a5b0c61..e030c56064 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -27,6 +27,7 @@ #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/evp.h> +#include <openssl/engine.h> #include <openssl/rand.h> #include <openssl/opensslv.h> #include <openssl/bn.h> @@ -49,9 +50,9 @@ #define CRYPTO_PRIVATE #include "crypto.h" -#include "log.h" +#include "../common/torlog.h" #include "aes.h" -#include "util.h" +#include "../common/util.h" #include "container.h" #include "compat.h" @@ -61,6 +62,33 @@ #include <openssl/engine.h> +#ifdef ANDROID +/* Android's OpenSSL seems to have removed all of its Engine support. */ +#define DISABLE_ENGINES +#endif + +#if OPENSSL_VERSION_NUMBER < 0x00908000l +/* On OpenSSL versions before 0.9.8, there is no working SHA256 + * implementation, so we use Tom St Denis's nice speedy one, slightly adapted + * to our needs */ +#define SHA256_CTX sha256_state +#define SHA256_Init sha256_init +#define SHA256_Update sha256_process +#define LTC_ARGCHK(x) tor_assert(x) +#include "sha256.c" +#define SHA256_Final(a,b) sha256_done(b,a) + +static unsigned char * +SHA256(const unsigned char *m, size_t len, unsigned char *d) +{ + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, m, len); + SHA256_Final(d, &ctx); + return d; +} +#endif + /** Macro: is k a valid RSA public or private key? */ #define PUBLIC_KEY_OK(k) ((k) && (k)->key && (k)->key->n) /** Macro: is k a valid RSA private key? */ @@ -94,7 +122,7 @@ struct crypto_dh_env_t { }; static int setup_openssl_threading(void); -static int tor_check_dh_key(BIGNUM *bn); +static int tor_check_dh_key(int severity, BIGNUM *bn); /** Return the number of bytes added by padding method <b>padding</b>. */ @@ -151,6 +179,7 @@ crypto_log_errors(int severity, const char *doing) } } +#ifndef DISABLE_ENGINES /** Log any OpenSSL engines we're using at NOTICE. */ static void log_engine(const char *fn, ENGINE *e) @@ -165,37 +194,82 @@ log_engine(const char *fn, ENGINE *e) log(LOG_INFO, LD_CRYPTO, "Using default implementation for %s", fn); } } +#endif + +#ifndef DISABLE_ENGINES +/** Try to load an engine in a shared library via fully qualified path. + */ +static ENGINE * +try_load_engine(const char *path, const char *engine) +{ + ENGINE *e = ENGINE_by_id("dynamic"); + if (e) { + if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) || + !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) || + !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) || + !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { + ENGINE_free(e); + e = NULL; + } + } + return e; +} +#endif /** Initialize the crypto library. Return 0 on success, -1 on failure. */ int -crypto_global_init(int useAccel) +crypto_global_init(int useAccel, const char *accelName, const char *accelDir) { if (!_crypto_global_initialized) { ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); _crypto_global_initialized = 1; setup_openssl_threading(); - /* XXX the below is a bug, since we can't know if we're supposed - * to be using hardware acceleration or not. we should arrange - * for this function to be called before init_keys. But make it - * not complain loudly, at least until we make acceleration work. */ - if (useAccel < 0) { - log_info(LD_CRYPTO, "Initializing OpenSSL via tor_tls_init()."); - } if (useAccel > 0) { +#ifdef DISABLE_ENGINES + (void)accelName; + (void)accelDir; + log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled."); +#else + ENGINE *e = NULL; + log_info(LD_CRYPTO, "Initializing OpenSSL engine support."); ENGINE_load_builtin_engines(); - if (!ENGINE_register_all_complete()) - return -1; - - /* XXXX make sure this isn't leaking. */ + ENGINE_register_all_complete(); + + if (accelName) { + if (accelDir) { + log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\"" + " via path \"%s\".", accelName, accelDir); + e = try_load_engine(accelName, accelDir); + } else { + log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\"" + " acceleration support.", accelName); + e = ENGINE_by_id(accelName); + } + if (!e) { + log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".", + accelName); + } else { + log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".", + accelName); + } + } + if (e) { + log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine," + " setting default ciphers."); + ENGINE_set_default(e, ENGINE_METHOD_ALL); + } log_engine("RSA", ENGINE_get_default_RSA()); log_engine("DH", ENGINE_get_default_DH()); log_engine("RAND", ENGINE_get_default_RAND()); log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1)); log_engine("3DES", ENGINE_get_cipher_engine(NID_des_ede3_ecb)); log_engine("AES", ENGINE_get_cipher_engine(NID_aes_128_ecb)); +#endif + } else { + log_info(LD_CRYPTO, "NOT using OpenSSL engine support."); } return crypto_seed_rng(1); } @@ -217,7 +291,11 @@ crypto_global_cleanup(void) EVP_cleanup(); ERR_remove_state(0); ERR_free_strings(); + +#ifndef DISABLE_ENGINES ENGINE_cleanup(); +#endif + CONF_modules_unload(1); CRYPTO_cleanup_all_ex_data(); #ifdef TOR_IS_MULTITHREADED @@ -259,7 +337,8 @@ _crypto_new_pk_env_evp_pkey(EVP_PKEY *pkey) return _crypto_new_pk_env_rsa(rsa); } -/** Helper, used by tor-checkkey.c. Return the RSA from a crypto_pk_env_t. */ +/** Helper, used by tor-checkkey.c and tor-gencert.c. Return the RSA from a + * crypto_pk_env_t. */ RSA * _crypto_pk_env_get_rsa(crypto_pk_env_t *env) { @@ -321,10 +400,12 @@ crypto_new_pk_env(void) void crypto_free_pk_env(crypto_pk_env_t *env) { - tor_assert(env); + if (!env) + return; if (--env->refs > 0) return; + tor_assert(env->refs == 0); if (env->key) RSA_free(env->key); @@ -347,10 +428,7 @@ crypto_create_init_cipher(const char *key, int encrypt_mode) return NULL; } - if (crypto_cipher_set_key(crypto, key)) { - crypto_log_errors(LOG_WARN, "setting symmetric key"); - goto error; - } + crypto_cipher_set_key(crypto, key); if (encrypt_mode) r = crypto_cipher_encrypt_init_cipher(crypto); @@ -384,7 +462,8 @@ crypto_new_cipher_env(void) void crypto_free_cipher_env(crypto_cipher_env_t *env) { - tor_assert(env); + if (!env) + return; tor_assert(env->cipher); aes_free_cipher(env->cipher); @@ -394,11 +473,11 @@ crypto_free_cipher_env(crypto_cipher_env_t *env) /* public key crypto */ -/** Generate a new public/private keypair in <b>env</b>. Return 0 on - * success, -1 on failure. +/** Generate a <b>bits</b>-bit new public/private keypair in <b>env</b>. + * Return 0 on success, -1 on failure. */ int -crypto_pk_generate_key(crypto_pk_env_t *env) +crypto_pk_generate_key_with_bits(crypto_pk_env_t *env, int bits) { tor_assert(env); @@ -406,7 +485,7 @@ crypto_pk_generate_key(crypto_pk_env_t *env) RSA_free(env->key); #if OPENSSL_VERSION_NUMBER < 0x00908000l /* In OpenSSL 0.9.7, RSA_generate_key is all we have. */ - env->key = RSA_generate_key(PK_BYTES*8,65537, NULL, NULL); + env->key = RSA_generate_key(bits, 65537, NULL, NULL); #else /* In OpenSSL 0.9.8, RSA_generate_key is deprecated. */ { @@ -419,7 +498,7 @@ crypto_pk_generate_key(crypto_pk_env_t *env) r = RSA_new(); if (!r) goto done; - if (RSA_generate_key_ex(r, PK_BYTES*8, e, NULL) == -1) + if (RSA_generate_key_ex(r, bits, e, NULL) == -1) goto done; env->key = r; @@ -701,14 +780,25 @@ crypto_pk_env_t * crypto_pk_copy_full(crypto_pk_env_t *env) { RSA *new_key; + int privatekey = 0; tor_assert(env); tor_assert(env->key); if (PRIVATE_KEY_OK(env)) { new_key = RSAPrivateKey_dup(env->key); + privatekey = 1; } else { new_key = RSAPublicKey_dup(env->key); } + if (!new_key) { + log_err(LD_CRYPTO, "Unable to duplicate a %s key: openssl failed.", + privatekey?"private":"public"); + crypto_log_errors(LOG_ERR, + privatekey ? "Duplicating a private key" : + "Duplicating a public key"); + tor_fragile_assert(); + return NULL; + } return _crypto_new_pk_env_rsa(new_key); } @@ -1178,19 +1268,14 @@ crypto_cipher_generate_key(crypto_cipher_env_t *env) /** Set the symmetric key for the cipher in <b>env</b> to the first * CIPHER_KEY_LEN bytes of <b>key</b>. Does not initialize the cipher. - * Return 0 on success, -1 on failure. */ -int +void crypto_cipher_set_key(crypto_cipher_env_t *env, const char *key) { tor_assert(env); tor_assert(key); - if (!env->key) - return -1; - memcpy(env->key, key, CIPHER_KEY_LEN); - return 0; } /** Generate an initialization vector for our AES-CTR cipher; store it @@ -1367,9 +1452,69 @@ crypto_digest(char *digest, const char *m, size_t len) return (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL); } +int +crypto_digest256(char *digest, const char *m, size_t len, + digest_algorithm_t algorithm) +{ + tor_assert(m); + tor_assert(digest); + tor_assert(algorithm == DIGEST_SHA256); + return (SHA256((const unsigned char*)m,len,(unsigned char*)digest) == NULL); +} + +/** Set the digests_t in <b>ds_out</b> to contain every digest on the + * <b>len</b> bytes in <b>m</b> that we know how to compute. Return 0 on + * success, -1 on failure. */ +int +crypto_digest_all(digests_t *ds_out, const char *m, size_t len) +{ + digest_algorithm_t i; + tor_assert(ds_out); + memset(ds_out, 0, sizeof(*ds_out)); + if (crypto_digest(ds_out->d[DIGEST_SHA1], m, len) < 0) + return -1; + for (i = DIGEST_SHA256; i < N_DIGEST_ALGORITHMS; ++i) { + if (crypto_digest256(ds_out->d[i], m, len, i) < 0) + return -1; + } + return 0; +} + +/** Return the name of an algorithm, as used in directory documents. */ +const char * +crypto_digest_algorithm_get_name(digest_algorithm_t alg) +{ + switch (alg) { + case DIGEST_SHA1: + return "sha1"; + case DIGEST_SHA256: + return "sha256"; + default: + tor_fragile_assert(); + return "??unknown_digest??"; + } +} + +/** Given the name of a digest algorithm, return its integer value, or -1 if + * the name is not recognized. */ +int +crypto_digest_algorithm_parse_name(const char *name) +{ + if (!strcmp(name, "sha1")) + return DIGEST_SHA1; + else if (!strcmp(name, "sha256")) + return DIGEST_SHA256; + else + return -1; +} + /** Intermediate information about the digest of a stream of data. */ struct crypto_digest_env_t { - SHA_CTX d; + union { + SHA_CTX sha1; + SHA256_CTX sha2; + } d; + digest_algorithm_t algorithm : 8; }; /** Allocate and return a new digest object. @@ -1379,7 +1524,19 @@ crypto_new_digest_env(void) { crypto_digest_env_t *r; r = tor_malloc(sizeof(crypto_digest_env_t)); - SHA1_Init(&r->d); + SHA1_Init(&r->d.sha1); + r->algorithm = DIGEST_SHA1; + return r; +} + +crypto_digest_env_t * +crypto_new_digest256_env(digest_algorithm_t algorithm) +{ + crypto_digest_env_t *r; + tor_assert(algorithm == DIGEST_SHA256); + r = tor_malloc(sizeof(crypto_digest_env_t)); + SHA256_Init(&r->d.sha2); + r->algorithm = algorithm; return r; } @@ -1388,6 +1545,8 @@ crypto_new_digest_env(void) void crypto_free_digest_env(crypto_digest_env_t *digest) { + if (!digest) + return; memset(digest, 0, sizeof(crypto_digest_env_t)); tor_free(digest); } @@ -1400,30 +1559,51 @@ crypto_digest_add_bytes(crypto_digest_env_t *digest, const char *data, { tor_assert(digest); tor_assert(data); - /* Using the SHA1_*() calls directly means we don't support doing - * SHA1 in hardware. But so far the delay of getting the question + /* Using the SHA*_*() calls directly means we don't support doing + * SHA in hardware. But so far the delay of getting the question * to the hardware, and hearing the answer, is likely higher than * just doing it ourselves. Hashes are fast. */ - SHA1_Update(&digest->d, (void*)data, len); + switch (digest->algorithm) { + case DIGEST_SHA1: + SHA1_Update(&digest->d.sha1, (void*)data, len); + break; + case DIGEST_SHA256: + SHA256_Update(&digest->d.sha2, (void*)data, len); + break; + default: + tor_fragile_assert(); + break; + } } /** Compute the hash of the data that has been passed to the digest * object; write the first out_len bytes of the result to <b>out</b>. - * <b>out_len</b> must be \<= DIGEST_LEN. + * <b>out_len</b> must be \<= DIGEST256_LEN. */ void crypto_digest_get_digest(crypto_digest_env_t *digest, char *out, size_t out_len) { - unsigned char r[DIGEST_LEN]; - SHA_CTX tmpctx; + unsigned char r[DIGEST256_LEN]; + crypto_digest_env_t tmpenv; tor_assert(digest); tor_assert(out); - tor_assert(out_len <= DIGEST_LEN); - /* memcpy into a temporary ctx, since SHA1_Final clears the context */ - memcpy(&tmpctx, &digest->d, sizeof(SHA_CTX)); - SHA1_Final(r, &tmpctx); + /* memcpy into a temporary ctx, since SHA*_Final clears the context */ + memcpy(&tmpenv, digest, sizeof(crypto_digest_env_t)); + switch (digest->algorithm) { + case DIGEST_SHA1: + tor_assert(out_len <= DIGEST_LEN); + SHA1_Final(r, &tmpenv.d.sha1); + break; + case DIGEST_SHA256: + tor_assert(out_len <= DIGEST256_LEN); + SHA256_Final(r, &tmpenv.d.sha2); + break; + default: + tor_fragile_assert(); + break; + } memcpy(out, r, out_len); memset(r, 0, sizeof(r)); } @@ -1559,7 +1739,7 @@ crypto_dh_generate_public(crypto_dh_env_t *dh) crypto_log_errors(LOG_WARN, "generating DH key"); return -1; } - if (tor_check_dh_key(dh->dh->pub_key)<0) { + if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) { log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-" "the-universe chances really do happen. Trying again."); /* Free and clear the keys, so OpenSSL will actually try again. */ @@ -1606,7 +1786,7 @@ crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey, size_t pubkey_len) * See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips. */ static int -tor_check_dh_key(BIGNUM *bn) +tor_check_dh_key(int severity, BIGNUM *bn) { BIGNUM *x; char *s; @@ -1617,13 +1797,13 @@ tor_check_dh_key(BIGNUM *bn) init_dh_param(); BN_set_word(x, 1); if (BN_cmp(bn,x)<=0) { - log_warn(LD_CRYPTO, "DH key must be at least 2."); + log_fn(severity, LD_CRYPTO, "DH key must be at least 2."); goto err; } BN_copy(x,dh_param_p); BN_sub_word(x, 1); if (BN_cmp(bn,x)>=0) { - log_warn(LD_CRYPTO, "DH key must be at most p-2."); + log_fn(severity, LD_CRYPTO, "DH key must be at most p-2."); goto err; } BN_free(x); @@ -1631,7 +1811,7 @@ tor_check_dh_key(BIGNUM *bn) err: BN_free(x); s = BN_bn2hex(bn); - log_warn(LD_CRYPTO, "Rejecting insecure DH key [%s]", s); + log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s); OPENSSL_free(s); return -1; } @@ -1649,7 +1829,7 @@ tor_check_dh_key(BIGNUM *bn) * where || is concatenation.) */ ssize_t -crypto_dh_compute_secret(crypto_dh_env_t *dh, +crypto_dh_compute_secret(int severity, crypto_dh_env_t *dh, const char *pubkey, size_t pubkey_len, char *secret_out, size_t secret_bytes_out) { @@ -1664,9 +1844,9 @@ crypto_dh_compute_secret(crypto_dh_env_t *dh, if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey, (int)pubkey_len, NULL))) goto error; - if (tor_check_dh_key(pubkey_bn)<0) { + if (tor_check_dh_key(severity, pubkey_bn)<0) { /* Check for invalid public keys. */ - log_warn(LD_CRYPTO,"Rejected invalid g^x"); + log_fn(severity, LD_CRYPTO,"Rejected invalid g^x"); goto error; } secret_tmp = tor_malloc(crypto_dh_get_bytes(dh)); @@ -1738,7 +1918,8 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len, void crypto_dh_free(crypto_dh_env_t *dh) { - tor_assert(dh); + if (!dh) + return; tor_assert(dh->dh); DH_free(dh->dh); tor_free(dh); @@ -1763,6 +1944,14 @@ crypto_dh_free(crypto_dh_env_t *dh) OPENSSL_VERSION_NUMBER <= 0x00907fffl) || \ (OPENSSL_VERSION_NUMBER >= 0x0090803fl)) +static void +seed_weak_rng(void) +{ + unsigned seed; + crypto_rand((void*)&seed, sizeof(seed)); + tor_init_weak_random(seed); +} + /** Seed OpenSSL's random number generator with bytes from the operating * system. <b>startup</b> should be true iff we have just started Tor and * have not yet allocated a bunch of fds. Return 0 on success, -1 on failure. @@ -1813,6 +2002,7 @@ crypto_seed_rng(int startup) } RAND_seed(buf, sizeof(buf)); memset(buf, 0, sizeof(buf)); + seed_weak_rng(); return 0; #else for (i = 0; filenames[i]; ++i) { @@ -1829,6 +2019,7 @@ crypto_seed_rng(int startup) } RAND_seed(buf, (int)sizeof(buf)); memset(buf, 0, sizeof(buf)); + seed_weak_rng(); return 0; } @@ -1896,6 +2087,26 @@ crypto_rand_uint64(uint64_t max) } } +/** Return a pseudorandom double d, chosen uniformly from the range + * 0.0 <= d < 1.0. + */ +double +crypto_rand_double(void) +{ + /* We just use an unsigned int here; we don't really care about getting + * more than 32 bits of resolution */ + unsigned int uint; + crypto_rand((char*)&uint, sizeof(uint)); +#if SIZEOF_INT == 4 +#define UINT_MAX_AS_DOUBLE 4294967296.0 +#elif SIZEOF_INT == 8 +#define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19 +#else +#error SIZEOF_INT is neither 4 nor 8 +#endif + return ((double)uint) / UINT_MAX_AS_DOUBLE; +} + /** Generate and return a new random hostname starting with <b>prefix</b>, * ending with <b>suffix</b>, and containing no less than * <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32 @@ -2156,6 +2367,44 @@ digest_from_base64(char *digest, const char *d64) #endif } +/** Base-64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the + * trailing = and newline characters, and store the nul-terminated result in + * the first BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */ +int +digest256_to_base64(char *d64, const char *digest) +{ + char buf[256]; + base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN); + buf[BASE64_DIGEST256_LEN] = '\0'; + memcpy(d64, buf, BASE64_DIGEST256_LEN+1); + return 0; +} + +/** Given a base-64 encoded, nul-terminated digest in <b>d64</b> (without + * trailing newline or = characters), decode it and store the result in the + * first DIGEST256_LEN bytes at <b>digest</b>. */ +int +digest256_from_base64(char *digest, const char *d64) +{ +#ifdef USE_OPENSSL_BASE64 + char buf_in[BASE64_DIGEST256_LEN+3]; + char buf[256]; + if (strlen(d64) != BASE64_DIGEST256_LEN) + return -1; + memcpy(buf_in, d64, BASE64_DIGEST256_LEN); + memcpy(buf_in+BASE64_DIGEST256_LEN, "=\n\0", 3); + if (base64_decode(buf, sizeof(buf), buf_in, strlen(buf_in)) != DIGEST256_LEN) + return -1; + memcpy(digest, buf, DIGEST256_LEN); + return 0; +#else + if (base64_decode(digest, DIGEST256_LEN, d64, strlen(d64)) == DIGEST256_LEN) + return 0; + else + return -1; +#endif +} + /** Implements base32 encoding as in rfc3548. Limitation: Requires * that srclen*8 is a multiple of 5. */ diff --git a/src/common/crypto.h b/src/common/crypto.h index 20fdfa4d2f..a30e5bcbae 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -18,6 +18,9 @@ /** Length of the output of our message digest. */ #define DIGEST_LEN 20 +/** Length of the output of our second (improved) message digests. (For now + * this is just sha256, but any it can be any other 256-byte digest). */ +#define DIGEST256_LEN 32 /** Length of our symmetric cipher's keys. */ #define CIPHER_KEY_LEN 16 /** Length of our symmetric cipher's IV. */ @@ -27,9 +30,12 @@ /** Length of our DH keys. */ #define DH_BYTES (1024/8) -/** Length of a message digest when encoded in base64 with trailing = signs - * removed. */ +/** Length of a sha1 message digest when encoded in base64 with trailing = + * signs removed. */ #define BASE64_DIGEST_LEN 27 +/** Length of a sha256 message digest when encoded in base64 with trailing = + * signs removed. */ +#define BASE64_DIGEST256_LEN 43 /** Constants used to indicate no padding for public-key encryption */ #define PK_NO_PADDING 60000 @@ -48,6 +54,26 @@ #define FINGERPRINT_LEN 49 /** Length of hex encoding of SHA1 digest, not including final NUL. */ #define HEX_DIGEST_LEN 40 +/** Length of hex encoding of SHA256 digest, not including final NUL. */ +#define HEX_DIGEST256_LEN 64 + +typedef enum { + DIGEST_SHA1 = 0, + DIGEST_SHA256 = 1, +} digest_algorithm_t; +#define N_DIGEST_ALGORITHMS (DIGEST_SHA256+1) + +/** A set of all the digests we know how to compute, taken on a single + * string. Any digests that are shorter than 256 bits are right-padded + * with 0 bits. + * + * Note that this representation wastes 12 bytes for the SHA1 case, so + * don't use it for anything where we need to allocate a whole bunch at + * once. + **/ +typedef struct { + char d[N_DIGEST_ALGORITHMS][DIGEST256_LEN]; +} digests_t; typedef struct crypto_pk_env_t crypto_pk_env_t; typedef struct crypto_cipher_env_t crypto_cipher_env_t; @@ -55,7 +81,9 @@ typedef struct crypto_digest_env_t crypto_digest_env_t; typedef struct crypto_dh_env_t crypto_dh_env_t; /* global state */ -int crypto_global_init(int hardwareAccel); +int crypto_global_init(int hardwareAccel, + const char *accelName, + const char *accelPath); void crypto_thread_cleanup(void); int crypto_global_cleanup(void); @@ -71,7 +99,9 @@ crypto_cipher_env_t *crypto_new_cipher_env(void); void crypto_free_cipher_env(crypto_cipher_env_t *env); /* public key crypto */ -int crypto_pk_generate_key(crypto_pk_env_t *env); +int crypto_pk_generate_key_with_bits(crypto_pk_env_t *env, int bits); +#define crypto_pk_generate_key(env) \ + crypto_pk_generate_key_with_bits((env), (PK_BYTES*8)) int crypto_pk_read_private_key_from_filename(crypto_pk_env_t *env, const char *keyfile); @@ -121,7 +151,7 @@ int crypto_pk_check_fingerprint_syntax(const char *s); /* symmetric crypto */ int crypto_cipher_generate_key(crypto_cipher_env_t *env); -int crypto_cipher_set_key(crypto_cipher_env_t *env, const char *key); +void crypto_cipher_set_key(crypto_cipher_env_t *env, const char *key); void crypto_cipher_generate_iv(char *iv_out); int crypto_cipher_set_iv(crypto_cipher_env_t *env, const char *iv); const char *crypto_cipher_get_key(crypto_cipher_env_t *env); @@ -141,9 +171,15 @@ int crypto_cipher_decrypt_with_iv(crypto_cipher_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen); -/* SHA-1 */ +/* SHA-1 and other digests. */ int crypto_digest(char *digest, const char *m, size_t len); +int crypto_digest256(char *digest, const char *m, size_t len, + digest_algorithm_t algorithm); +int crypto_digest_all(digests_t *ds_out, const char *m, size_t len); +const char *crypto_digest_algorithm_get_name(digest_algorithm_t alg); +int crypto_digest_algorithm_parse_name(const char *name); crypto_digest_env_t *crypto_new_digest_env(void); +crypto_digest_env_t *crypto_new_digest256_env(digest_algorithm_t algorithm); void crypto_free_digest_env(crypto_digest_env_t *digest); void crypto_digest_add_bytes(crypto_digest_env_t *digest, const char *data, size_t len); @@ -162,7 +198,7 @@ int crypto_dh_get_bytes(crypto_dh_env_t *dh); int crypto_dh_generate_public(crypto_dh_env_t *dh); int crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey_out, size_t pubkey_out_len); -ssize_t crypto_dh_compute_secret(crypto_dh_env_t *dh, +ssize_t crypto_dh_compute_secret(int severity, crypto_dh_env_t *dh, const char *pubkey, size_t pubkey_len, char *secret_out, size_t secret_out_len); void crypto_dh_free(crypto_dh_env_t *dh); @@ -174,6 +210,7 @@ int crypto_seed_rng(int startup); int crypto_rand(char *to, size_t n); int crypto_rand_int(unsigned int max); uint64_t crypto_rand_uint64(uint64_t max); +double crypto_rand_double(void); char *crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix, const char *suffix); @@ -191,6 +228,8 @@ int base32_decode(char *dest, size_t destlen, const char *src, size_t srclen); int digest_to_base64(char *d64, const char *digest); int digest_from_base64(char *digest, const char *d64); +int digest256_to_base64(char *d64, const char *digest); +int digest256_from_base64(char *digest, const char *d64); /** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the * 9th describes how much iteration to do. */ diff --git a/src/common/ht.h b/src/common/ht.h index e6dd3d2b24..f598856d8a 100644 --- a/src/common/ht.h +++ b/src/common/ht.h @@ -42,6 +42,10 @@ #define HT_SIZE(head) \ ((head)->hth_n_entries) +/* Return memory usage for a hashtable (not counting the entries themselves) */ +#define HT_MEM_USAGE(head) \ + (sizeof(*head) + (head)->hth_table_length * sizeof(void*)) + #define HT_FIND(name, head, elm) name##_HT_FIND((head), (elm)) #define HT_INSERT(name, head, elm) name##_HT_INSERT((head), (elm)) #define HT_REPLACE(name, head, elm) name##_HT_REPLACE((head), (elm)) diff --git a/src/common/log.c b/src/common/log.c index 6baef8e26c..b639e7a781 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -33,11 +33,9 @@ #include "compat.h" #include "util.h" #define LOG_PRIVATE -#include "log.h" +#include "torlog.h" #include "container.h" -#include <event.h> - #define TRUNCATED_STR "[...truncated]" #define TRUNCATED_STR_LEN 14 @@ -83,7 +81,7 @@ should_log_function_name(log_domain_mask_t domain, int severity) /* All debugging messages occur in interesting places. */ return 1; case LOG_NOTICE: - case LOG_WARN: + case LOG_WARN: case LOG_ERR: /* We care about places where bugs occur. */ return (domain == LD_BUG); @@ -330,7 +328,7 @@ logv(int severity, log_domain_mask_t domain, const char *funcname, /** Output a message to the log. */ void -_log(int severity, log_domain_mask_t domain, const char *format, ...) +tor_log(int severity, log_domain_mask_t domain, const char *format, ...) { va_list ap; if (severity > _log_global_min_severity) @@ -428,6 +426,8 @@ _log_err(log_domain_mask_t domain, const char *format, ...) static void log_free(logfile_t *victim) { + if (!victim) + return; tor_free(victim->severities); tor_free(victim->filename); tor_free(victim); @@ -678,13 +678,11 @@ add_file_log(const log_severity_list_t *severity, const char *filename) logfiles->needs_close = 1; lf = logfiles; _log_global_min_severity = get_min_log_level(); - UNLOCK_LOGS(); if (log_tor_version(lf, 0) < 0) { - LOCK_LOGS(); delete_log(lf); - UNLOCK_LOGS(); } + UNLOCK_LOGS(); return 0; } @@ -747,7 +745,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", NULL + "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", NULL }; /** Return a bitmask for the log domain for which <b>domain</b> is the name, @@ -925,65 +923,6 @@ switch_logs_debug(void) UNLOCK_LOGS(); } -#ifdef HAVE_EVENT_SET_LOG_CALLBACK -/** A string which, if it appears in a libevent log, should be ignored. */ -static const char *suppress_msg = NULL; -/** Callback function passed to event_set_log() so we can intercept - * log messages from libevent. */ -static void -libevent_logging_callback(int severity, const char *msg) -{ - char buf[1024]; - size_t n; - if (suppress_msg && strstr(msg, suppress_msg)) - return; - n = strlcpy(buf, msg, sizeof(buf)); - if (n && n < sizeof(buf) && buf[n-1] == '\n') { - buf[n-1] = '\0'; - } - switch (severity) { - case _EVENT_LOG_DEBUG: - log(LOG_DEBUG, LD_NET, "Message from libevent: %s", buf); - break; - case _EVENT_LOG_MSG: - log(LOG_INFO, LD_NET, "Message from libevent: %s", buf); - break; - case _EVENT_LOG_WARN: - log(LOG_WARN, LD_GENERAL, "Warning from libevent: %s", buf); - break; - case _EVENT_LOG_ERR: - log(LOG_ERR, LD_GENERAL, "Error from libevent: %s", buf); - break; - default: - log(LOG_WARN, LD_GENERAL, "Message [%d] from libevent: %s", - severity, buf); - break; - } -} -/** Set hook to intercept log messages from libevent. */ -void -configure_libevent_logging(void) -{ - event_set_log_callback(libevent_logging_callback); -} -/** Ignore any libevent log message that contains <b>msg</b>. */ -void -suppress_libevent_log_msg(const char *msg) -{ - suppress_msg = msg; -} -#else -void -configure_libevent_logging(void) -{ -} -void -suppress_libevent_log_msg(const char *msg) -{ - (void)msg; -} -#endif - #if 0 static void dump_log_info(logfile_t *lf) diff --git a/src/common/memarea.c b/src/common/memarea.c index edd7bbe9ef..dac15434c0 100644 --- a/src/common/memarea.c +++ b/src/common/memarea.c @@ -11,7 +11,11 @@ #include "memarea.h" #include "util.h" #include "compat.h" -#include "log.h" +#include "torlog.h" + +/** If true, we try to detect any attempts to write beyond the length of a + * memarea. */ +#define USE_SENTINELS /** All returned pointers should be aligned to the nearest multiple of this * value. */ @@ -25,6 +29,24 @@ #error "void* is neither 4 nor 8 bytes long. I don't know how to align stuff." #endif +#ifdef USE_SENTINELS +#define SENTINEL_VAL 0x90806622u +#define SENTINEL_LEN sizeof(uint32_t) +#define SET_SENTINEL(chunk) \ + STMT_BEGIN \ + set_uint32( &(chunk)->u.mem[chunk->mem_size], SENTINEL_VAL ); \ + STMT_END +#define CHECK_SENTINEL(chunk) \ + STMT_BEGIN \ + uint32_t sent_val = get_uint32(&(chunk)->u.mem[chunk->mem_size]); \ + tor_assert(sent_val == SENTINEL_VAL); \ + STMT_END +#else +#define SENTINEL_LEN 0 +#define SET_SENTINEL(chunk) STMT_NIL +#define CHECK_SENTINEL(chunk) STMT_NIL +#endif + /** Increment <b>ptr</b> until it is aligned to MEMAREA_ALIGN. */ static INLINE void * realign_pointer(void *ptr) @@ -79,15 +101,20 @@ alloc_chunk(size_t sz, int freelist_ok) freelist = res->next_chunk; res->next_chunk = NULL; --freelist_len; + CHECK_SENTINEL(res); return res; } else { size_t chunk_size = freelist_ok ? CHUNK_SIZE : sz; - memarea_chunk_t *res = tor_malloc_roundup(&chunk_size); + memarea_chunk_t *res; + chunk_size += SENTINEL_LEN; + res = tor_malloc_roundup(&chunk_size); res->next_chunk = NULL; - res->mem_size = chunk_size - CHUNK_HEADER_SIZE; + res->mem_size = chunk_size - CHUNK_HEADER_SIZE - SENTINEL_LEN; res->next_mem = res->u.mem; - tor_assert(res->next_mem+res->mem_size == ((char*)res)+chunk_size); + tor_assert(res->next_mem+res->mem_size+SENTINEL_LEN == + ((char*)res)+chunk_size); tor_assert(realign_pointer(res->next_mem) == res->next_mem); + SET_SENTINEL(res); return res; } } @@ -95,8 +122,9 @@ alloc_chunk(size_t sz, int freelist_ok) /** Release <b>chunk</b> from a memarea, either by adding it to the freelist * or by freeing it if the freelist is already too big. */ static void -chunk_free(memarea_chunk_t *chunk) +chunk_free_unchecked(memarea_chunk_t *chunk) { + CHECK_SENTINEL(chunk); if (freelist_len < MAX_FREELIST_LEN) { ++freelist_len; chunk->next_chunk = freelist; @@ -124,7 +152,7 @@ memarea_drop_all(memarea_t *area) memarea_chunk_t *chunk, *next; for (chunk = area->first; chunk; chunk = next) { next = chunk->next_chunk; - chunk_free(chunk); + chunk_free_unchecked(chunk); } area->first = NULL; /*fail fast on */ tor_free(area); @@ -140,7 +168,7 @@ memarea_clear(memarea_t *area) if (area->first->next_chunk) { for (chunk = area->first->next_chunk; chunk; chunk = next) { next = chunk->next_chunk; - chunk_free(chunk); + chunk_free_unchecked(chunk); } area->first->next_chunk = NULL; } @@ -183,6 +211,7 @@ memarea_alloc(memarea_t *area, size_t sz) memarea_chunk_t *chunk = area->first; char *result; tor_assert(chunk); + CHECK_SENTINEL(chunk); tor_assert(sz < SIZE_T_CEILING); if (sz == 0) sz = 1; @@ -261,6 +290,7 @@ memarea_get_stats(memarea_t *area, size_t *allocated_out, size_t *used_out) size_t a = 0, u = 0; memarea_chunk_t *chunk; for (chunk = area->first; chunk; chunk = chunk->next_chunk) { + CHECK_SENTINEL(chunk); a += CHUNK_HEADER_SIZE + chunk->mem_size; tor_assert(chunk->next_mem >= chunk->u.mem); u += CHUNK_HEADER_SIZE + (chunk->next_mem - chunk->u.mem); @@ -277,6 +307,7 @@ memarea_assert_ok(memarea_t *area) tor_assert(area->first); for (chunk = area->first; chunk; chunk = chunk->next_chunk) { + CHECK_SENTINEL(chunk); tor_assert(chunk->next_mem >= chunk->u.mem); tor_assert(chunk->next_mem <= (char*) realign_pointer(chunk->u.mem+chunk->mem_size)); diff --git a/src/common/mempool.c b/src/common/mempool.c index 1f79221b48..9d019d618e 100644 --- a/src/common/mempool.c +++ b/src/common/mempool.c @@ -65,7 +65,7 @@ #include "orconfig.h" #include "util.h" #include "compat.h" -#include "log.h" +#include "torlog.h" #define ALLOC(x) tor_malloc(x) #define FREE(x) tor_free(x) #define ASSERT(x) tor_assert(x) diff --git a/src/common/sha256.c b/src/common/sha256.c new file mode 100644 index 0000000000..4236d48f5f --- /dev/null +++ b/src/common/sha256.c @@ -0,0 +1,331 @@ +/* Copyright (c) 2009-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ +/* This SHA256 implementation is adapted from the public domain one in + LibTomCrypt, version 1.6. Tor uses it on platforms where OpenSSL doesn't + have a SHA256. */ + + +typedef struct sha256_state { + uint64_t length; + uint32_t state[8], curlen; + unsigned char buf[64]; +} sha256_state; + +#define CRYPT_OK 0 +#define CRYPT_NOP -1 +#define CRYPT_INVALID_ARG -2 + +#define LOAD32H(x,y) STMT_BEGIN x = ntohl(get_uint32((const char*)y)); STMT_END +#define STORE32H(x,y) STMT_BEGIN set_uint32((char*)y, htonl(x)); STMT_END +#define STORE64H(x,y) STMT_BEGIN \ + set_uint32((char*)y, htonl((uint32_t)((x)>>32))); \ + set_uint32(((char*)y)+4, htonl((uint32_t)((x)&0xffffffff))); \ + STMT_END +#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#ifndef MIN + #define MIN(x, y) ( ((x)<(y))?(x):(y) ) +#endif + + +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ + +/** + @file sha256.c + SHA256 by Tom St Denis +*/ + + +#ifdef LTC_SMALL_CODE +/* the K array */ +static const uint32_t K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +#endif + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +#ifdef LTC_CLEAN_STACK +static int _sha256_compress(sha256_state * md, unsigned char *buf) +#else +static int sha256_compress(sha256_state * md, unsigned char *buf) +#endif +{ + uint32_t S[8], W[64], t0, t1; +#ifdef LTC_SMALL_CODE + uint32_t t; +#endif + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 64; ++i) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } +#else +#define RND(a,b,c,d,e,f,g,h,i,ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); + +#undef RND + +#endif + + /* feedback */ + for (i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int sha256_compress(sha256_state * md, unsigned char *buf) +{ + int err; + err = _sha256_compress(md, buf); + burn_stack(sizeof(uint32_t) * 74); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +static int sha256_init(sha256_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->curlen = 0; + md->length = 0; + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +static int sha256_process (sha256_state * md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + int err; + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + if (md->curlen > sizeof(md->buf)) { + return CRYPT_INVALID_ARG; + } + while (inlen > 0) { + if (md->curlen == 0 && inlen >= 64) { + if ((err = sha256_compress (md, (unsigned char *)in)) != CRYPT_OK) { + return err; + } + md->length += 64 * 8; + in += 64; + inlen -= 64; + } else { + n = MIN(inlen, (64 - md->curlen)); + memcpy(md->buf + md->curlen, in, (size_t)n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == 64) { + if ((err = sha256_compress (md, md->buf)) != CRYPT_OK) { + return err; + } + md->length += 8*64; + md->curlen = 0; + } + } + } + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +static int sha256_done(sha256_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->curlen >= sizeof(md->buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + sha256_compress(md, md->buf); + md->curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->length, md->buf+56); + sha256_compress(md, md->buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(md->state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(sha256_state)); +#endif + return CRYPT_OK; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/11/01 09:28:17 $ */ diff --git a/src/common/test.h b/src/common/test.h deleted file mode 100644 index 1e3db58333..0000000000 --- a/src/common/test.h +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (c) 2001-2003, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2010, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -#ifndef _TOR_TEST_H -#define _TOR_TEST_H - -/** - * \file test.h - * \brief Macros used by unit tests. - */ - -#include "compat.h" - -#ifdef __GNUC__ -#define PRETTY_FUNCTION __PRETTY_FUNCTION__ -#else -#define PRETTY_FUNCTION "" -#endif - -#define test_fail_msg(msg) \ - STMT_BEGIN \ - have_failed = 1; \ - printf("\nFile %s: line %d (%s): %s", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - msg); \ - goto done; \ - STMT_END - -#define test_fail() test_fail_msg("Assertion failed.") - -#define test_assert(expr) \ - STMT_BEGIN \ - if (expr) { printf("."); fflush(stdout); } else { \ - have_failed = 1; \ - printf("\nFile %s: line %d (%s): assertion failed: (%s)\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr); \ - goto done; \ - } STMT_END - -#define test_eq_type(tp, fmt, expr1, expr2) \ - STMT_BEGIN \ - tp _test_v1=(tp)(expr1); \ - tp _test_v2=(tp)(expr2); \ - if (_test_v1==_test_v2) { printf("."); fflush(stdout); } else { \ - have_failed = 1; \ - printf("\nFile %s: line %d (%s): Assertion failed: (%s==%s)\n" \ - " "fmt "!="fmt"\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr1, #expr2, \ - _test_v1, _test_v2); \ - goto done; \ - } STMT_END - -#define test_eq(expr1, expr2) \ - test_eq_type(long, "%ld", expr1, expr2) - -#define test_eq_ptr(expr1, expr2) \ - test_eq_type(void*, "%p", expr1, expr2) - -#define test_neq_type(tp, fmt, expr1, expr2) \ - STMT_BEGIN \ - tp _test_v1=(tp)(expr1); \ - tp _test_v2=(tp)(expr2); \ - if (_test_v1!=_test_v2) { printf("."); fflush(stdout); } else { \ - have_failed = 1; \ - printf("\nFile %s: line %d (%s): Assertion failed: (%s!=%s)\n" \ - " ("fmt" == "fmt")\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr1, #expr2, \ - _test_v1, _test_v2); \ - goto done; \ - } STMT_END - -#define test_neq(expr1, expr2) \ - test_neq_type(long, "%ld", expr1, expr2) - -#define test_neq_ptr(expr1, expr2) \ - test_neq_type(void *, "%p", expr1, expr2) - -#define test_streq(expr1, expr2) \ - STMT_BEGIN \ - const char *_test_v1=(expr1), *_test_v2=(expr2); \ - if (!strcmp(_test_v1,_test_v2)) { printf("."); fflush(stdout); } else { \ - have_failed = 1; \ - printf("\nFile %s: line %d (%s): Assertion failed: (%s==%s)\n"\ - " (\"%s\" != \"%s\")\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr1, #expr2, \ - _test_v1, _test_v2); \ - goto done; \ - } STMT_END - -#define test_strneq(expr1, expr2) \ - STMT_BEGIN \ - const char *_test_v1=(expr1), *_test_v2=(expr2); \ - if (strcmp(_test_v1,_test_v2)) { printf("."); fflush(stdout); } else { \ - have_failed = 1; \ - printf("\nFile %s: line %d (%s): Assertion failed: (%s!=%s)\n"\ - " (\"%s\" == \"%s\")\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr1, #expr2, \ - _test_v1, _test_v2); \ - goto done; \ - } STMT_END - -#define test_memeq(expr1, expr2, len) \ - STMT_BEGIN \ - const void *_test_v1=(expr1), *_test_v2=(expr2); \ - char *mem1, *mem2; \ - if (!memcmp(_test_v1,_test_v2,(len))) { \ - printf("."); fflush(stdout); } else { \ - have_failed = 1; \ - mem1 = tor_malloc(len*2+1); \ - mem2 = tor_malloc(len*2+1); \ - base16_encode(mem1, len*2+1, _test_v1, len); \ - base16_encode(mem2, len*2+1, _test_v2, len); \ - printf("\nFile %s: line %d (%s): Assertion failed: (%s==%s)\n" \ - " %s != %s\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr1, #expr2, mem1, mem2); \ - tor_free(mem1); \ - tor_free(mem2); \ - goto done; \ - } STMT_END - -#define test_memeq_hex(expr1, hex) \ - STMT_BEGIN \ - const char *_test_v1 = (char*)(expr1); \ - const char *_test_v2 = (hex); \ - size_t _len_v2 = strlen(_test_v2); \ - char *_mem2 = tor_malloc(_len_v2/2); \ - tor_assert((_len_v2 & 1) == 0); \ - base16_decode(_mem2, _len_v2/2, _test_v2, _len_v2); \ - if (!memcmp(_mem2, _test_v1, _len_v2/2)) { \ - printf("."); fflush(stdout); } else { \ - char *_mem1 = tor_malloc(_len_v2+1); \ - base16_encode(_mem1, _len_v2+1, _test_v1, _len_v2/2); \ - printf("\nFile %s: line %d (%s): Assertion failed: (%s==%s)\n" \ - " %s != %s\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr1, _test_v2, _mem1, _test_v2); \ - tor_free(_mem1); \ - tor_free(_mem2); \ - goto done; \ - } \ - tor_free(_mem2); \ - STMT_END - -#define test_memneq(expr1, expr2, len) \ - STMT_BEGIN \ - void *_test_v1=(expr1), *_test_v2=(expr2); \ - if (memcmp(_test_v1,_test_v2,(len))) { \ - printf("."); fflush(stdout); \ - } else { \ - have_failed = 1; \ - printf("\nFile %s: line %d (%s): Assertion failed: (%s!=%s)\n", \ - _SHORT_FILE_, \ - __LINE__, \ - PRETTY_FUNCTION, \ - #expr1, #expr2); \ - goto done; \ - } STMT_END - -#endif - diff --git a/src/common/torgzip.c b/src/common/torgzip.c index 10bce33283..a247d6c177 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -13,20 +13,42 @@ #include <stdlib.h> #include <stdio.h> #include <assert.h> -#ifdef _MSC_VER -#include "..\..\contrib\zlib\zlib.h" -#else -#include <zlib.h> -#endif #include <string.h> #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif +#include "torint.h" #include "util.h" -#include "log.h" +#include "torlog.h" #include "torgzip.h" +/* zlib 1.2.4 and 1.2.5 do some "clever" things with macros. Instead of + saying "(defined(FOO) ? FOO : 0)" they like to say "FOO-0", on the theory + that nobody will care if the compile outputs a no-such-identifier warning. + + Sorry, but we like -Werror over here, so I guess we need to define these. + I hope that zlib 1.2.6 doesn't break these too. +*/ +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE 0 +#endif +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE 0 +#endif +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif +#ifndef off64_t +#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. */ static int gzip_is_supported = -1; @@ -165,9 +187,7 @@ tor_gzip_compress(char **out, size_t *out_len, deflateEnd(stream); tor_free(stream); } - if (*out) { - tor_free(*out); - } + tor_free(*out); return -1; } @@ -423,7 +443,8 @@ tor_zlib_process(tor_zlib_state_t *state, void tor_zlib_free(tor_zlib_state_t *state) { - tor_assert(state); + if (!state) + return; if (state->compress) deflateEnd(&state->stream); diff --git a/src/common/torint.h b/src/common/torint.h index 665b0b4c71..a57d501002 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -117,11 +117,10 @@ typedef unsigned int uint32_t; #ifndef INT32_MAX #define INT32_MAX 0x7fffffffu #endif -#endif - #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif +#endif #if (SIZEOF_LONG == 4) #ifndef HAVE_INT32_T diff --git a/src/common/log.h b/src/common/torlog.h index 6a45fc3d0b..21219569e3 100644 --- a/src/common/log.h +++ b/src/common/torlog.h @@ -90,9 +90,10 @@ #define LD_ACCT (1u<<17) /** Router history */ #define LD_HIST (1u<<18) - +/** OR handshaking */ +#define LD_HANDSHAKE (1u<<19) /** Number of logging domains in the code. */ -#define N_LOGGING_DOMAINS 19 +#define N_LOGGING_DOMAINS 20 typedef uint32_t log_domain_mask_t; @@ -134,16 +135,14 @@ void add_temp_log(int min_severity); void close_temp_logs(void); void rollback_log_changes(void); void mark_logs_temp(void); -void configure_libevent_logging(void); -void suppress_libevent_log_msg(const char *msg); void change_callback_log_severity(int loglevelMin, int loglevelMax, log_callback cb); void log_set_application_name(const char *name); /* Outputs a message to stdout */ -void _log(int severity, log_domain_mask_t domain, const char *format, ...) +void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) CHECK_PRINTF(3,4); -#define log _log /* hack it so we don't conflict with log() as much */ +#define log tor_log /* hack it so we don't conflict with log() as much */ #ifdef __GNUC__ extern int _log_global_min_severity; diff --git a/src/common/tortls.c b/src/common/tortls.c index 4d11d6d7fe..fa89412f6e 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -16,6 +16,10 @@ #include "orconfig.h" +#if defined (WINCE) +#include <WinSock2.h> +#endif + #include <assert.h> #ifdef MS_WINDOWS /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/ #define WIN32_WINNT 0x400 @@ -45,7 +49,7 @@ #include "crypto.h" #include "tortls.h" #include "util.h" -#include "log.h" +#include "torlog.h" #include "container.h" #include "ht.h" #include <string.h> @@ -82,7 +86,9 @@ static int use_unsafe_renegotiation_op = 0; * SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ static int use_unsafe_renegotiation_flag = 0; -/** Structure holding the TLS state for a single connection. */ +/** Holds a SSL_CTX object and related state used to configure TLS + * connections. + */ typedef struct tor_tls_context_t { int refcnt; SSL_CTX *ctx; @@ -184,10 +190,16 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, const char *cname_sign, unsigned int lifetime); static void tor_tls_unblock_renegotiation(tor_tls_t *tls); - -/** Global tls context. We keep it here because nobody else needs to - * touch it. */ -static tor_tls_context_t *global_tls_context = NULL; +static int tor_tls_context_init_one(tor_tls_context_t **ppcontext, + crypto_pk_env_t *identity, + unsigned int key_lifetime); +static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity, + unsigned int key_lifetime); + +/** 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; @@ -195,30 +207,51 @@ static int tls_library_is_initialized = 0; #define _TOR_TLS_SYSCALL (_MIN_TOR_TLS_ERROR_VAL - 2) #define _TOR_TLS_ZERORETURN (_MIN_TOR_TLS_ERROR_VAL - 1) +#include "tortls_states.h" + +/** Return the symbolic name of an OpenSSL state. */ +static const char * +ssl_state_to_string(int ssl_state) +{ + static char buf[40]; + int i; + for (i = 0; state_map[i].name; ++i) { + if (state_map[i].state == ssl_state) + return state_map[i].name; + } + tor_snprintf(buf, sizeof(buf), "Unknown state %d", ssl_state); + return buf; +} + /** 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, const char *doing) +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, LD_NET, "TLS error while %s%s%s: %s (in %s:%s)", + log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)", doing, addr?" with ":"", addr?addr:"", - msg, lib, func); + msg, lib, func, state); } else { - log(severity, LD_NET, "TLS error%s%s: %s (in %s:%s)", + log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)", addr?" with ":"", addr?addr:"", - msg, lib, func); + msg, lib, func, state); } } } @@ -294,7 +327,7 @@ tor_tls_err_to_string(int err) */ static int tor_tls_get_error(tor_tls_t *tls, int r, int extra, - const char *doing, int severity) + const char *doing, int severity, int domain) { int err = SSL_get_error(tls->ssl, r); int tor_error = TOR_TLS_ERROR_MISC; @@ -309,25 +342,28 @@ tor_tls_get_error(tor_tls_t *tls, int r, int extra, if (extra&CATCH_SYSCALL) return _TOR_TLS_SYSCALL; if (r == 0) { - log(severity, LD_NET, "TLS error: unexpected close while %s", doing); + log(severity, LD_NET, "TLS error: unexpected close while %s (%s)", + doing, ssl_state_to_string(tls->ssl->state)); tor_error = TOR_TLS_ERROR_IO; } else { int e = tor_socket_errno(tls->socket); log(severity, LD_NET, - "TLS error: <syscall error while %s> (errno=%d: %s)", - doing, e, tor_socket_strerror(e)); + "TLS error: <syscall error while %s> (errno=%d: %s; state=%s)", + doing, e, tor_socket_strerror(e), + ssl_state_to_string(tls->ssl->state)); tor_error = tor_errno_to_tls_error(e); } - tls_log_errors(tls, severity, doing); + tls_log_errors(tls, severity, domain, doing); return tor_error; case SSL_ERROR_ZERO_RETURN: if (extra&CATCH_ZERO) return _TOR_TLS_ZERORETURN; - log(severity, LD_NET, "TLS connection closed while %s", doing); - tls_log_errors(tls, severity, doing); + log(severity, LD_NET, "TLS connection closed while %s in state %s", + doing, ssl_state_to_string(tls->ssl->state)); + tls_log_errors(tls, severity, domain, doing); return TOR_TLS_CLOSE; default: - tls_log_errors(tls, severity, doing); + tls_log_errors(tls, severity, domain, doing); return TOR_TLS_ERROR_MISC; } } @@ -341,11 +377,10 @@ tor_tls_init(void) long version; SSL_library_init(); SSL_load_error_strings(); - crypto_global_init(-1); version = SSLeay(); - /* OpenSSL 0.9.8l introdeced SSL3_FLAGS_ALLOW_UNSAGE_LEGACY_RENEGOTIATION + /* OpenSSL 0.9.8l introduced SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION * here, but without thinking too hard about it: it turns out that the * flag in question needed to be set at the last minute, and that it * conflicted with an existing flag number that had already been added @@ -364,8 +399,8 @@ tor_tls_init(void) * leave their headers out of sync with their libraries. * * Yes, it _is_ almost as if the OpenSSL developers decided that no - * program should be allowed to use renegotiation its first passed an - * test of intelligence and determination. + * program should be allowed to use renegotiation unless it first passed + * a test of intelligence and determination. */ if (version >= 0x009080c0L && version < 0x009080d0L) { log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l; " @@ -400,9 +435,15 @@ tor_tls_init(void) void tor_tls_free_all(void) { - if (global_tls_context) { - tor_tls_context_decref(global_tls_context); - global_tls_context = NULL; + if (server_tls_context) { + tor_tls_context_t *ctx = server_tls_context; + server_tls_context = NULL; + tor_tls_context_decref(ctx); + } + if (client_tls_context) { + tor_tls_context_t *ctx = client_tls_context; + 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."); @@ -511,7 +552,7 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, x509 = NULL; } done: - tls_log_errors(NULL, LOG_WARN, "generating certificate"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "generating certificate"); if (sign_pkey) EVP_PKEY_free(sign_pkey); if (pkey) @@ -528,9 +569,9 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, (TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":" \ TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" \ SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) -/* Note: for setting up your own private testing network with link crypto - * disabled, set the cipher lists to your cipher list to - * SSL3_TXT_RSA_NULL_SHA. If you do this, you won't be able to communicate +/* Note: to set up your own private testing network with link crypto + * disabled, set your Tors' cipher list to + * (SSL3_TXT_RSA_NULL_SHA). If you do this, you won't be able to communicate * with any of the "real" Tors, though. */ #ifdef V2_HANDSHAKE_CLIENT @@ -589,15 +630,97 @@ tor_tls_context_incref(tor_tls_context_t *ctx) ++ctx->refcnt; } -/** Create a new TLS context for use with Tor TLS handshakes. - * <b>identity</b> should be set to the identity key used to sign the - * certificate, and <b>nickname</b> set to the nickname to use. +/** Create new global client and server TLS contexts. + * + * If <b>server_identity</b> is NULL, this will not generate a server + * TLS context. If <b>is_public_server</b> is non-zero, this will use + * the same TLS context for incoming and outgoing connections, and + * ignore <b>client_identity</b>. */ +int +tor_tls_context_init(int is_public_server, + crypto_pk_env_t *client_identity, + crypto_pk_env_t *server_identity, + unsigned int key_lifetime) +{ + int rv1 = 0; + int rv2 = 0; + + if (is_public_server) { + tor_tls_context_t *new_ctx; + tor_tls_context_t *old_ctx; + + tor_assert(server_identity != NULL); + + rv1 = tor_tls_context_init_one(&server_tls_context, + server_identity, + key_lifetime); + + if (rv1 >= 0) { + new_ctx = server_tls_context; + tor_tls_context_incref(new_ctx); + old_ctx = client_tls_context; + client_tls_context = new_ctx; + + if (old_ctx != NULL) { + tor_tls_context_decref(old_ctx); + } + } + } else { + if (server_identity != NULL) { + rv1 = tor_tls_context_init_one(&server_tls_context, + server_identity, + key_lifetime); + } else { + tor_tls_context_t *old_ctx = server_tls_context; + server_tls_context = NULL; + + if (old_ctx != NULL) { + tor_tls_context_decref(old_ctx); + } + } + + rv2 = tor_tls_context_init_one(&client_tls_context, + client_identity, + key_lifetime); + } + + return MIN(rv1, rv2); +} + +/** Create a new global TLS context. * * You can call this function multiple times. Each time you call it, * it generates new certificates; all new connections will use * the new SSL context. */ -int +static int +tor_tls_context_init_one(tor_tls_context_t **ppcontext, + crypto_pk_env_t *identity, + unsigned int key_lifetime) +{ + tor_tls_context_t *new_ctx = tor_tls_context_new(identity, + key_lifetime); + tor_tls_context_t *old_ctx = *ppcontext; + + if (new_ctx != NULL) { + *ppcontext = new_ctx; + + /* Free the old context if one existed. */ + if (old_ctx != NULL) { + /* This is safe even if there are open connections: we reference- + * count tor_tls_context_t objects. */ + tor_tls_context_decref(old_ctx); + } + } + + return ((new_ctx != NULL) ? 0 : -1); +} + +/** Create a new TLS context for use with Tor TLS handshakes. + * <b>identity</b> should be set to the identity key used to sign the + * certificate. + */ +static tor_tls_context_t * tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) { crypto_pk_env_t *rsa = NULL; @@ -692,21 +815,15 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) always_accept_verify_cb); /* let us realloc bufs that we're writing from */ SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - /* Free the old context if one exists. */ - if (global_tls_context) { - /* This is safe even if there are open connections: OpenSSL does - * reference counting with SSL and SSL_CTX objects. */ - tor_tls_context_decref(global_tls_context); - } - global_tls_context = result; + if (rsa) crypto_free_pk_env(rsa); tor_free(nickname); tor_free(nn2); - return 0; + return result; error: - tls_log_errors(NULL, LOG_WARN, "creating TLS context"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "creating TLS context"); tor_free(nickname); tor_free(nn2); if (pkey) @@ -719,7 +836,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) X509_free(cert); if (idcert) X509_free(idcert); - return -1; + return NULL; } #ifdef V2_HANDSHAKE_SERVER @@ -734,11 +851,11 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) /* If we reached this point, we just got a client hello. See if there is * a cipher list. */ if (!(session = SSL_get_session((SSL *)ssl))) { - log_warn(LD_NET, "No session on TLS?"); + log_info(LD_NET, "No session on TLS?"); return 0; } if (!session->ciphers) { - log_warn(LD_NET, "No ciphers on session"); + log_info(LD_NET, "No ciphers on session"); return 0; } /* Now we need to see if there are any ciphers whose presence means we're @@ -750,8 +867,7 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) && strcmp(ciphername, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) && strcmp(ciphername, "(NONE)")) { - /* XXXX should be ld_debug */ - log_info(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername); + log_debug(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername); // return 1; goto dump_list; } @@ -767,8 +883,8 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) smartlist_add(elts, (char*)ciphername); } s = smartlist_join_strings(elts, ":", 0, NULL); - log_info(LD_NET, "Got a non-version-1 cipher list from %s. It is: '%s'", - address, s); + log_debug(LD_NET, "Got a non-version-1 cipher list from %s. It is: '%s'", + address, s); tor_free(s); smartlist_free(elts); } @@ -899,10 +1015,12 @@ tor_tls_new(int sock, int isServer) { BIO *bio = NULL; tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t)); + tor_tls_context_t *context = isServer ? server_tls_context : + client_tls_context; - tor_assert(global_tls_context); /* make sure somebody made it first */ - if (!(result->ssl = SSL_new(global_tls_context->ctx))) { - tls_log_errors(NULL, LOG_WARN, "generating TLS context"); + tor_assert(context); /* make sure somebody made it first */ + if (!(result->ssl = SSL_new(context->ctx))) { + tls_log_errors(NULL, LOG_WARN, LD_NET, "creating SSL object"); tor_free(result); return NULL; } @@ -918,7 +1036,7 @@ tor_tls_new(int sock, int isServer) if (!SSL_set_cipher_list(result->ssl, isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) { - tls_log_errors(NULL, LOG_WARN, "setting ciphers"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "setting ciphers"); #ifdef SSL_set_tlsext_host_name SSL_set_tlsext_host_name(result->ssl, NULL); #endif @@ -931,7 +1049,7 @@ tor_tls_new(int sock, int isServer) result->socket = sock; bio = BIO_new_socket(sock, BIO_NOCLOSE); if (! bio) { - tls_log_errors(NULL, LOG_WARN, "opening BIO"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "opening BIO"); #ifdef SSL_set_tlsext_host_name SSL_set_tlsext_host_name(result->ssl, NULL); #endif @@ -941,8 +1059,8 @@ tor_tls_new(int sock, int isServer) } HT_INSERT(tlsmap, &tlsmap_root, result); SSL_set_bio(result->ssl, bio, bio); - tor_tls_context_incref(global_tls_context); - result->context = global_tls_context; + tor_tls_context_incref(context); + result->context = context; result->state = TOR_TLS_ST_HANDSHAKE; result->isServer = isServer; result->wantwrite_n = 0; @@ -959,7 +1077,7 @@ tor_tls_new(int sock, int isServer) #endif /* Not expected to get called. */ - tls_log_errors(NULL, LOG_WARN, "generating TLS context"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object"); return result; } @@ -1038,7 +1156,9 @@ void tor_tls_free(tor_tls_t *tls) { tor_tls_t *removed; - tor_assert(tls && tls->ssl); + 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."); @@ -1081,7 +1201,7 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len) #endif return r; } - err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG); + err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET); 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; @@ -1117,7 +1237,7 @@ tor_tls_write(tor_tls_t *tls, const char *cp, size_t n) tls->wantwrite_n = 0; } r = SSL_write(tls->ssl, cp, (int)n); - err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO); + err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO, LD_NET); if (err == TOR_TLS_DONE) { return r; } @@ -1135,21 +1255,30 @@ int tor_tls_handshake(tor_tls_t *tls) { int r; + int oldstate; tor_assert(tls); tor_assert(tls->ssl); tor_assert(tls->state == TOR_TLS_ST_HANDSHAKE); check_no_tls_errors(); + oldstate = tls->ssl->state; if (tls->isServer) { + log_debug(LD_HANDSHAKE, "About to call SSL_accept on %p (%s)", tls, + ssl_state_to_string(tls->ssl->state)); r = SSL_accept(tls->ssl); } else { + log_debug(LD_HANDSHAKE, "About to call SSL_connect on %p (%s)", tls, + ssl_state_to_string(tls->ssl->state)); r = SSL_connect(tls->ssl); } + if (oldstate != tls->ssl->state) + log_debug(LD_HANDSHAKE, "After call, %p was in state %s", + tls, ssl_state_to_string(tls->ssl->state)); /* We need to call this here and not earlier, since OpenSSL has a penchant * for clearing its flags when you say accept or connect. */ tor_tls_unblock_renegotiation(tls); - r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO); + r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO, LD_HANDSHAKE); if (ERR_peek_error() != 0) { - tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, + tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, LD_HANDSHAKE, "handshaking"); return TOR_TLS_ERROR_MISC; } @@ -1170,7 +1299,8 @@ tor_tls_handshake(tor_tls_t *tls) " get set. Fixing that."); } tls->wasV2Handshake = 1; - log_debug(LD_NET, "Completed V2 TLS handshake with client; waiting " + log_debug(LD_HANDSHAKE, + "Completed V2 TLS handshake with client; waiting " "for renegotiation."); } else { tls->wasV2Handshake = 0; @@ -1182,10 +1312,13 @@ tor_tls_handshake(tor_tls_t *tls) 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))) + 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_NET, "Server sent back a single certificate; looks like " + } else { + log_debug(LD_HANDSHAKE, + "Server sent back a single certificate; looks like " "a v2 handshake on %p.", tls); tls->wasV2Handshake = 1; } @@ -1193,7 +1326,7 @@ tor_tls_handshake(tor_tls_t *tls) X509_free(cert); #endif if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) { - tls_log_errors(NULL, LOG_WARN, "re-setting ciphers"); + tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers"); r = TOR_TLS_ERROR_MISC; } } @@ -1216,7 +1349,8 @@ tor_tls_renegotiate(tor_tls_t *tls) if (tls->state != TOR_TLS_ST_RENEGOTIATE) { int r = SSL_renegotiate(tls->ssl); if (r <= 0) { - return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN); + return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN, + LD_HANDSHAKE); } tls->state = TOR_TLS_ST_RENEGOTIATE; } @@ -1225,7 +1359,8 @@ tor_tls_renegotiate(tor_tls_t *tls) tls->state = TOR_TLS_ST_OPEN; return TOR_TLS_DONE; } else - return tor_tls_get_error(tls, r, 0, "renegotiating handshake", LOG_INFO); + return tor_tls_get_error(tls, r, 0, "renegotiating handshake", LOG_INFO, + LD_HANDSHAKE); } /** Shut down an open tls connection <b>tls</b>. When finished, returns @@ -1249,7 +1384,7 @@ tor_tls_shutdown(tor_tls_t *tls) r = SSL_read(tls->ssl, buf, 128); } while (r>0); err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading to shut down", - LOG_INFO); + LOG_INFO, LD_NET); if (err == _TOR_TLS_ZERORETURN) { tls->state = TOR_TLS_ST_GOTCLOSE; /* fall through... */ @@ -1265,7 +1400,7 @@ tor_tls_shutdown(tor_tls_t *tls) return TOR_TLS_DONE; } err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down", - LOG_INFO); + LOG_INFO, LD_NET); if (err == _TOR_TLS_SYSCALL) { /* The underlying TCP connection closed while we were shutting down. */ tls->state = TOR_TLS_ST_CLOSED; @@ -1297,7 +1432,7 @@ tor_tls_peer_has_cert(tor_tls_t *tls) { X509 *cert; cert = SSL_get_peer_certificate(tls->ssl); - tls_log_errors(tls, LOG_WARN, "getting peer certificate"); + tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate"); if (!cert) return 0; X509_free(cert); @@ -1324,7 +1459,7 @@ log_cert_lifetime(X509 *cert, const char *problem) log_warn(LD_GENERAL, "Couldn't allocate BIO!"); goto end; } if (!(ASN1_TIME_print(bio, X509_get_notBefore(cert)))) { - tls_log_errors(NULL, LOG_WARN, "printing certificate lifetime"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "printing certificate lifetime"); goto end; } BIO_get_mem_ptr(bio, &buf); @@ -1332,7 +1467,7 @@ log_cert_lifetime(X509 *cert, const char *problem) (void)BIO_reset(bio); if (!(ASN1_TIME_print(bio, X509_get_notAfter(cert)))) { - tls_log_errors(NULL, LOG_WARN, "printing certificate lifetime"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "printing certificate lifetime"); goto end; } BIO_get_mem_ptr(bio, &buf); @@ -1346,13 +1481,11 @@ log_cert_lifetime(X509 *cert, const char *problem) end: /* Not expected to get invoked */ - tls_log_errors(NULL, LOG_WARN, "getting certificate lifetime"); + tls_log_errors(NULL, LOG_WARN, LD_NET, "getting certificate lifetime"); if (bio) BIO_free(bio); - if (s1) - tor_free(s1); - if (s2) - tor_free(s2); + tor_free(s1); + tor_free(s2); } /** Helper function: try to extract a link certificate and an identity @@ -1420,7 +1553,7 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key) 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"); - tls_log_errors(tls, severity,"verifying certificate"); + tls_log_errors(tls, severity, LD_HANDSHAKE, "verifying certificate"); goto done; } @@ -1439,7 +1572,7 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key) /* This should never get invoked, but let's make sure in case OpenSSL * acts unexpectedly. */ - tls_log_errors(tls, LOG_WARN, "finishing tor_tls_verify"); + tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "finishing tor_tls_verify"); return r; } @@ -1478,7 +1611,7 @@ tor_tls_check_lifetime(tor_tls_t *tls, int tolerance) if (cert) X509_free(cert); /* Not expected to get invoked */ - tls_log_errors(tls, LOG_WARN, "checking certificate lifetime"); + tls_log_errors(tls, LOG_WARN, LD_NET, "checking certificate lifetime"); return r; } @@ -1546,7 +1679,7 @@ _check_no_tls_errors(const char *fname, int line) return; log(LOG_WARN, LD_CRYPTO, "Unhandled OpenSSL errors found at %s:%d: ", tor_fix_source_file(fname), line); - tls_log_errors(NULL, LOG_WARN, NULL); + tls_log_errors(NULL, LOG_WARN, LD_NET, NULL); } /** Return true iff the initial TLS connection at <b>tls</b> did not use a v2 diff --git a/src/common/tortls.h b/src/common/tortls.h index e4b1ad65f2..955027ba35 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -50,7 +50,10 @@ typedef struct tor_tls_t tor_tls_t; const char *tor_tls_err_to_string(int err); void tor_tls_free_all(void); -int tor_tls_context_new(crypto_pk_env_t *rsa, unsigned int key_lifetime); +int tor_tls_context_init(int is_public_server, + crypto_pk_env_t *client_identity, + crypto_pk_env_t *server_identity, + 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, diff --git a/src/common/tortls_states.h b/src/common/tortls_states.h new file mode 100644 index 0000000000..00f476dd66 --- /dev/null +++ b/src/common/tortls_states.h @@ -0,0 +1,414 @@ +/* Copyright (c) 2003, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* Helper file: included only in tortls.c */ + +#ifndef _TORTLS_STATES_H +#define _TORTLS_STATES_H + +/* The main body of this file was mechanically generated with this + perl script: + + my %keys = (); + for $fn (@ARGV) { + open(F, $fn); + while (<F>) { + next unless /^#define ((?:SSL|DTLS)\w*_ST_\w*)/; + $keys{$1} = 1; + } + close(F); + } + for $k (sort keys %keys) { + print "#ifdef $k\n S($k),\n#endif\n" + } +*/ + +/** Mapping from allowed value of SSL.state to the name of C macro for that + * state. Used for debugging an openssl connection. */ +static const struct { int state; const char *name; } state_map[] = { +#define S(state) { state, #state } +#ifdef DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A + S(DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A), +#endif +#ifdef DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B + S(DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B), +#endif +#ifdef DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A + S(DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A), +#endif +#ifdef DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B + S(DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B), +#endif +#ifdef SSL23_ST_CR_SRVR_HELLO_A + S(SSL23_ST_CR_SRVR_HELLO_A), +#endif +#ifdef SSL23_ST_CR_SRVR_HELLO_B + S(SSL23_ST_CR_SRVR_HELLO_B), +#endif +#ifdef SSL23_ST_CW_CLNT_HELLO_A + S(SSL23_ST_CW_CLNT_HELLO_A), +#endif +#ifdef SSL23_ST_CW_CLNT_HELLO_B + S(SSL23_ST_CW_CLNT_HELLO_B), +#endif +#ifdef SSL23_ST_SR_CLNT_HELLO_A + S(SSL23_ST_SR_CLNT_HELLO_A), +#endif +#ifdef SSL23_ST_SR_CLNT_HELLO_B + S(SSL23_ST_SR_CLNT_HELLO_B), +#endif +#ifdef SSL2_ST_CLIENT_START_ENCRYPTION + S(SSL2_ST_CLIENT_START_ENCRYPTION), +#endif +#ifdef SSL2_ST_GET_CLIENT_FINISHED_A + S(SSL2_ST_GET_CLIENT_FINISHED_A), +#endif +#ifdef SSL2_ST_GET_CLIENT_FINISHED_B + S(SSL2_ST_GET_CLIENT_FINISHED_B), +#endif +#ifdef SSL2_ST_GET_CLIENT_HELLO_A + S(SSL2_ST_GET_CLIENT_HELLO_A), +#endif +#ifdef SSL2_ST_GET_CLIENT_HELLO_B + S(SSL2_ST_GET_CLIENT_HELLO_B), +#endif +#ifdef SSL2_ST_GET_CLIENT_HELLO_C + S(SSL2_ST_GET_CLIENT_HELLO_C), +#endif +#ifdef SSL2_ST_GET_CLIENT_MASTER_KEY_A + S(SSL2_ST_GET_CLIENT_MASTER_KEY_A), +#endif +#ifdef SSL2_ST_GET_CLIENT_MASTER_KEY_B + S(SSL2_ST_GET_CLIENT_MASTER_KEY_B), +#endif +#ifdef SSL2_ST_GET_SERVER_FINISHED_A + S(SSL2_ST_GET_SERVER_FINISHED_A), +#endif +#ifdef SSL2_ST_GET_SERVER_FINISHED_B + S(SSL2_ST_GET_SERVER_FINISHED_B), +#endif +#ifdef SSL2_ST_GET_SERVER_HELLO_A + S(SSL2_ST_GET_SERVER_HELLO_A), +#endif +#ifdef SSL2_ST_GET_SERVER_HELLO_B + S(SSL2_ST_GET_SERVER_HELLO_B), +#endif +#ifdef SSL2_ST_GET_SERVER_VERIFY_A + S(SSL2_ST_GET_SERVER_VERIFY_A), +#endif +#ifdef SSL2_ST_GET_SERVER_VERIFY_B + S(SSL2_ST_GET_SERVER_VERIFY_B), +#endif +#ifdef SSL2_ST_SEND_CLIENT_CERTIFICATE_A + S(SSL2_ST_SEND_CLIENT_CERTIFICATE_A), +#endif +#ifdef SSL2_ST_SEND_CLIENT_CERTIFICATE_B + S(SSL2_ST_SEND_CLIENT_CERTIFICATE_B), +#endif +#ifdef SSL2_ST_SEND_CLIENT_CERTIFICATE_C + S(SSL2_ST_SEND_CLIENT_CERTIFICATE_C), +#endif +#ifdef SSL2_ST_SEND_CLIENT_CERTIFICATE_D + S(SSL2_ST_SEND_CLIENT_CERTIFICATE_D), +#endif +#ifdef SSL2_ST_SEND_CLIENT_FINISHED_A + S(SSL2_ST_SEND_CLIENT_FINISHED_A), +#endif +#ifdef SSL2_ST_SEND_CLIENT_FINISHED_B + S(SSL2_ST_SEND_CLIENT_FINISHED_B), +#endif +#ifdef SSL2_ST_SEND_CLIENT_HELLO_A + S(SSL2_ST_SEND_CLIENT_HELLO_A), +#endif +#ifdef SSL2_ST_SEND_CLIENT_HELLO_B + S(SSL2_ST_SEND_CLIENT_HELLO_B), +#endif +#ifdef SSL2_ST_SEND_CLIENT_MASTER_KEY_A + S(SSL2_ST_SEND_CLIENT_MASTER_KEY_A), +#endif +#ifdef SSL2_ST_SEND_CLIENT_MASTER_KEY_B + S(SSL2_ST_SEND_CLIENT_MASTER_KEY_B), +#endif +#ifdef SSL2_ST_SEND_REQUEST_CERTIFICATE_A + S(SSL2_ST_SEND_REQUEST_CERTIFICATE_A), +#endif +#ifdef SSL2_ST_SEND_REQUEST_CERTIFICATE_B + S(SSL2_ST_SEND_REQUEST_CERTIFICATE_B), +#endif +#ifdef SSL2_ST_SEND_REQUEST_CERTIFICATE_C + S(SSL2_ST_SEND_REQUEST_CERTIFICATE_C), +#endif +#ifdef SSL2_ST_SEND_REQUEST_CERTIFICATE_D + S(SSL2_ST_SEND_REQUEST_CERTIFICATE_D), +#endif +#ifdef SSL2_ST_SEND_SERVER_FINISHED_A + S(SSL2_ST_SEND_SERVER_FINISHED_A), +#endif +#ifdef SSL2_ST_SEND_SERVER_FINISHED_B + S(SSL2_ST_SEND_SERVER_FINISHED_B), +#endif +#ifdef SSL2_ST_SEND_SERVER_HELLO_A + S(SSL2_ST_SEND_SERVER_HELLO_A), +#endif +#ifdef SSL2_ST_SEND_SERVER_HELLO_B + S(SSL2_ST_SEND_SERVER_HELLO_B), +#endif +#ifdef SSL2_ST_SEND_SERVER_VERIFY_A + S(SSL2_ST_SEND_SERVER_VERIFY_A), +#endif +#ifdef SSL2_ST_SEND_SERVER_VERIFY_B + S(SSL2_ST_SEND_SERVER_VERIFY_B), +#endif +#ifdef SSL2_ST_SEND_SERVER_VERIFY_C + S(SSL2_ST_SEND_SERVER_VERIFY_C), +#endif +#ifdef SSL2_ST_SERVER_START_ENCRYPTION + S(SSL2_ST_SERVER_START_ENCRYPTION), +#endif +#ifdef SSL2_ST_X509_GET_CLIENT_CERTIFICATE + S(SSL2_ST_X509_GET_CLIENT_CERTIFICATE), +#endif +#ifdef SSL2_ST_X509_GET_SERVER_CERTIFICATE + S(SSL2_ST_X509_GET_SERVER_CERTIFICATE), +#endif +#ifdef SSL3_ST_CR_CERT_A + S(SSL3_ST_CR_CERT_A), +#endif +#ifdef SSL3_ST_CR_CERT_B + S(SSL3_ST_CR_CERT_B), +#endif +#ifdef SSL3_ST_CR_CERT_REQ_A + S(SSL3_ST_CR_CERT_REQ_A), +#endif +#ifdef SSL3_ST_CR_CERT_REQ_B + S(SSL3_ST_CR_CERT_REQ_B), +#endif +#ifdef SSL3_ST_CR_CERT_STATUS_A + S(SSL3_ST_CR_CERT_STATUS_A), +#endif +#ifdef SSL3_ST_CR_CERT_STATUS_B + S(SSL3_ST_CR_CERT_STATUS_B), +#endif +#ifdef SSL3_ST_CR_CHANGE_A + S(SSL3_ST_CR_CHANGE_A), +#endif +#ifdef SSL3_ST_CR_CHANGE_B + S(SSL3_ST_CR_CHANGE_B), +#endif +#ifdef SSL3_ST_CR_FINISHED_A + S(SSL3_ST_CR_FINISHED_A), +#endif +#ifdef SSL3_ST_CR_FINISHED_B + S(SSL3_ST_CR_FINISHED_B), +#endif +#ifdef SSL3_ST_CR_KEY_EXCH_A + S(SSL3_ST_CR_KEY_EXCH_A), +#endif +#ifdef SSL3_ST_CR_KEY_EXCH_B + S(SSL3_ST_CR_KEY_EXCH_B), +#endif +#ifdef SSL3_ST_CR_SESSION_TICKET_A + S(SSL3_ST_CR_SESSION_TICKET_A), +#endif +#ifdef SSL3_ST_CR_SESSION_TICKET_B + S(SSL3_ST_CR_SESSION_TICKET_B), +#endif +#ifdef SSL3_ST_CR_SRVR_DONE_A + S(SSL3_ST_CR_SRVR_DONE_A), +#endif +#ifdef SSL3_ST_CR_SRVR_DONE_B + S(SSL3_ST_CR_SRVR_DONE_B), +#endif +#ifdef SSL3_ST_CR_SRVR_HELLO_A + S(SSL3_ST_CR_SRVR_HELLO_A), +#endif +#ifdef SSL3_ST_CR_SRVR_HELLO_B + S(SSL3_ST_CR_SRVR_HELLO_B), +#endif +#ifdef SSL3_ST_CW_CERT_A + S(SSL3_ST_CW_CERT_A), +#endif +#ifdef SSL3_ST_CW_CERT_B + S(SSL3_ST_CW_CERT_B), +#endif +#ifdef SSL3_ST_CW_CERT_C + S(SSL3_ST_CW_CERT_C), +#endif +#ifdef SSL3_ST_CW_CERT_D + S(SSL3_ST_CW_CERT_D), +#endif +#ifdef SSL3_ST_CW_CERT_VRFY_A + S(SSL3_ST_CW_CERT_VRFY_A), +#endif +#ifdef SSL3_ST_CW_CERT_VRFY_B + S(SSL3_ST_CW_CERT_VRFY_B), +#endif +#ifdef SSL3_ST_CW_CHANGE_A + S(SSL3_ST_CW_CHANGE_A), +#endif +#ifdef SSL3_ST_CW_CHANGE_B + S(SSL3_ST_CW_CHANGE_B), +#endif +#ifdef SSL3_ST_CW_CLNT_HELLO_A + S(SSL3_ST_CW_CLNT_HELLO_A), +#endif +#ifdef SSL3_ST_CW_CLNT_HELLO_B + S(SSL3_ST_CW_CLNT_HELLO_B), +#endif +#ifdef SSL3_ST_CW_FINISHED_A + S(SSL3_ST_CW_FINISHED_A), +#endif +#ifdef SSL3_ST_CW_FINISHED_B + S(SSL3_ST_CW_FINISHED_B), +#endif +#ifdef SSL3_ST_CW_FLUSH + S(SSL3_ST_CW_FLUSH), +#endif +#ifdef SSL3_ST_CW_KEY_EXCH_A + S(SSL3_ST_CW_KEY_EXCH_A), +#endif +#ifdef SSL3_ST_CW_KEY_EXCH_B + S(SSL3_ST_CW_KEY_EXCH_B), +#endif +#ifdef SSL3_ST_SR_CERT_A + S(SSL3_ST_SR_CERT_A), +#endif +#ifdef SSL3_ST_SR_CERT_B + S(SSL3_ST_SR_CERT_B), +#endif +#ifdef SSL3_ST_SR_CERT_VRFY_A + S(SSL3_ST_SR_CERT_VRFY_A), +#endif +#ifdef SSL3_ST_SR_CERT_VRFY_B + S(SSL3_ST_SR_CERT_VRFY_B), +#endif +#ifdef SSL3_ST_SR_CHANGE_A + S(SSL3_ST_SR_CHANGE_A), +#endif +#ifdef SSL3_ST_SR_CHANGE_B + S(SSL3_ST_SR_CHANGE_B), +#endif +#ifdef SSL3_ST_SR_CLNT_HELLO_A + S(SSL3_ST_SR_CLNT_HELLO_A), +#endif +#ifdef SSL3_ST_SR_CLNT_HELLO_B + S(SSL3_ST_SR_CLNT_HELLO_B), +#endif +#ifdef SSL3_ST_SR_CLNT_HELLO_C + S(SSL3_ST_SR_CLNT_HELLO_C), +#endif +#ifdef SSL3_ST_SR_FINISHED_A + S(SSL3_ST_SR_FINISHED_A), +#endif +#ifdef SSL3_ST_SR_FINISHED_B + S(SSL3_ST_SR_FINISHED_B), +#endif +#ifdef SSL3_ST_SR_KEY_EXCH_A + S(SSL3_ST_SR_KEY_EXCH_A), +#endif +#ifdef SSL3_ST_SR_KEY_EXCH_B + S(SSL3_ST_SR_KEY_EXCH_B), +#endif +#ifdef SSL3_ST_SW_CERT_A + S(SSL3_ST_SW_CERT_A), +#endif +#ifdef SSL3_ST_SW_CERT_B + S(SSL3_ST_SW_CERT_B), +#endif +#ifdef SSL3_ST_SW_CERT_REQ_A + S(SSL3_ST_SW_CERT_REQ_A), +#endif +#ifdef SSL3_ST_SW_CERT_REQ_B + S(SSL3_ST_SW_CERT_REQ_B), +#endif +#ifdef SSL3_ST_SW_CERT_STATUS_A + S(SSL3_ST_SW_CERT_STATUS_A), +#endif +#ifdef SSL3_ST_SW_CERT_STATUS_B + S(SSL3_ST_SW_CERT_STATUS_B), +#endif +#ifdef SSL3_ST_SW_CHANGE_A + S(SSL3_ST_SW_CHANGE_A), +#endif +#ifdef SSL3_ST_SW_CHANGE_B + S(SSL3_ST_SW_CHANGE_B), +#endif +#ifdef SSL3_ST_SW_FINISHED_A + S(SSL3_ST_SW_FINISHED_A), +#endif +#ifdef SSL3_ST_SW_FINISHED_B + S(SSL3_ST_SW_FINISHED_B), +#endif +#ifdef SSL3_ST_SW_FLUSH + S(SSL3_ST_SW_FLUSH), +#endif +#ifdef SSL3_ST_SW_HELLO_REQ_A + S(SSL3_ST_SW_HELLO_REQ_A), +#endif +#ifdef SSL3_ST_SW_HELLO_REQ_B + S(SSL3_ST_SW_HELLO_REQ_B), +#endif +#ifdef SSL3_ST_SW_HELLO_REQ_C + S(SSL3_ST_SW_HELLO_REQ_C), +#endif +#ifdef SSL3_ST_SW_KEY_EXCH_A + S(SSL3_ST_SW_KEY_EXCH_A), +#endif +#ifdef SSL3_ST_SW_KEY_EXCH_B + S(SSL3_ST_SW_KEY_EXCH_B), +#endif +#ifdef SSL3_ST_SW_SESSION_TICKET_A + S(SSL3_ST_SW_SESSION_TICKET_A), +#endif +#ifdef SSL3_ST_SW_SESSION_TICKET_B + S(SSL3_ST_SW_SESSION_TICKET_B), +#endif +#ifdef SSL3_ST_SW_SRVR_DONE_A + S(SSL3_ST_SW_SRVR_DONE_A), +#endif +#ifdef SSL3_ST_SW_SRVR_DONE_B + S(SSL3_ST_SW_SRVR_DONE_B), +#endif +#ifdef SSL3_ST_SW_SRVR_HELLO_A + S(SSL3_ST_SW_SRVR_HELLO_A), +#endif +#ifdef SSL3_ST_SW_SRVR_HELLO_B + S(SSL3_ST_SW_SRVR_HELLO_B), +#endif +#ifdef SSL_ST_ACCEPT + S(SSL_ST_ACCEPT), +#endif +#ifdef SSL_ST_BEFORE + S(SSL_ST_BEFORE), +#endif +#ifdef SSL_ST_CONNECT + S(SSL_ST_CONNECT), +#endif +#ifdef SSL_ST_INIT + S(SSL_ST_INIT), +#endif +#ifdef SSL_ST_MASK + S(SSL_ST_MASK), +#endif +#ifdef SSL_ST_OK + S(SSL_ST_OK), +#endif +#ifdef SSL_ST_READ_BODY + S(SSL_ST_READ_BODY), +#endif +#ifdef SSL_ST_READ_DONE + S(SSL_ST_READ_DONE), +#endif +#ifdef SSL_ST_READ_HEADER + S(SSL_ST_READ_HEADER), +#endif +#ifdef SSL_ST_RENEGOTIATE + S(SSL_ST_RENEGOTIATE), +#endif + { 0, NULL } +}; + +#endif + diff --git a/src/common/util.c b/src/common/util.c index 0571a532cd..d511872964 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -15,7 +15,8 @@ #include "orconfig.h" #include "util.h" -#include "log.h" +#include "torlog.h" +#undef log #include "crypto.h" #include "torint.h" #include "container.h" @@ -25,11 +26,17 @@ #include <io.h> #include <direct.h> #include <process.h> +#include <tchar.h> #else #include <dirent.h> #include <pwd.h> #endif +/* math.h needs this on Linux */ +#ifndef __USE_ISOC99 +#define __USE_ISOC99 1 +#endif +#include <math.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -285,7 +292,7 @@ tor_log_mallinfo(int severity) struct mallinfo mi; memset(&mi, 0, sizeof(mi)); mi = mallinfo(); - log(severity, LD_MM, + tor_log(severity, LD_MM, "mallinfo() said: arena=%d, ordblks=%d, smblks=%d, hblks=%d, " "hblkhd=%d, usmblks=%d, fsmblks=%d, uordblks=%d, fordblks=%d, " "keepcost=%d", @@ -308,6 +315,25 @@ tor_log_mallinfo(int severity) * Math * ===== */ +/** + * Returns the natural logarithm of d base 2. We define this wrapper here so + * as to make it easier not to conflict with Tor's log() macro. + */ +double +tor_mathlog(double d) +{ + return log(d); +} + +/** Return the long integer closest to d. We define this wrapper here so + * that not all users of math.h need to use the right incancations to get + * the c99 functions. */ +long +tor_lround(double d) +{ + return lround(d); +} + /** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */ int tor_log2(uint64_t u64) @@ -352,6 +378,36 @@ round_to_power_of_2(uint64_t u64) return low; } +/** Return the lowest x such that x is at least <b>number</b>, and x modulo + * <b>divisor</b> == 0. */ +unsigned +round_to_next_multiple_of(unsigned number, unsigned divisor) +{ + number += divisor - 1; + number -= number % divisor; + return number; +} + +/** Return the lowest x such that x is at least <b>number</b>, and x modulo + * <b>divisor</b> == 0. */ +uint32_t +round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor) +{ + number += divisor - 1; + number -= number % divisor; + return number; +} + +/** Return the lowest x such that x is at least <b>number</b>, and x modulo + * <b>divisor</b> == 0. */ +uint64_t +round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor) +{ + number += divisor - 1; + number -= number % divisor; + return number; +} + /* ===== * String manipulation * ===== */ @@ -634,6 +690,29 @@ find_whitespace_eos(const char *s, const char *eos) return s; } +/** Return the first occurrence of <b>needle</b> in <b>haystack</b> that + * occurs at the start of a line (that is, at the beginning of <b>haystack</b> + * or immediately after a newline). Return NULL if no such string is found. + */ +const char * +find_str_at_start_of_line(const char *haystack, const char *needle) +{ + size_t needle_len = strlen(needle); + + do { + if (!strncmp(haystack, needle, needle_len)) + return haystack; + + haystack = strchr(haystack, '\n'); + if (!haystack) + return NULL; + else + ++haystack; + } while (*haystack); + + return NULL; +} + /** Return true iff the 'len' bytes at 'mem' are all zero. */ int tor_mem_is_zero(const char *mem, size_t len) @@ -661,6 +740,13 @@ tor_digest_is_zero(const char *digest) return tor_mem_is_zero(digest, DIGEST_LEN); } +/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */ +int +tor_digest256_is_zero(const char *digest) +{ + return tor_mem_is_zero(digest, DIGEST256_LEN); +} + /* Helper: common code to check whether the result of a strtol or strtoul or * strtoll is correct. */ #define CHECK_STRTOX_RESULT() \ @@ -712,7 +798,18 @@ tor_parse_ulong(const char *s, int base, unsigned long min, CHECK_STRTOX_RESULT(); } -/** As tor_parse_log, but return a unit64_t. Only base 10 is guaranteed to +/** As tor_parse_long(), but return a double. */ +double +tor_parse_double(const char *s, double min, double max, int *ok, char **next) +{ + char *endptr; + double r; + + r = strtod(s, &endptr); + CHECK_STRTOX_RESULT(); +} + +/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to * work for now. */ uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, @@ -851,6 +948,9 @@ esc_for_log(const char *s) case '\\': case '\"': case '\'': + case '\r': + case '\n': + case '\t': len += 2; break; default: @@ -912,8 +1012,7 @@ const char * escaped(const char *s) { static char *_escaped_val = NULL; - if (_escaped_val) - tor_free(_escaped_val); + tor_free(_escaped_val); if (s) _escaped_val = esc_for_log(s); @@ -1000,6 +1099,42 @@ wrap_string(smartlist_t *out, const char *string, size_t width, * Time * ===== */ +/** + * Converts struct timeval to a double value. + * Preserves microsecond precision, but just barely. + * Error is approx +/- 0.1 usec when dealing with epoch values. + */ +double +tv_to_double(const struct timeval *tv) +{ + double conv = tv->tv_sec; + conv += tv->tv_usec/1000000.0; + return conv; +} + +/** + * Converts timeval to milliseconds. + */ +int64_t +tv_to_msec(const struct timeval *tv) +{ + int64_t conv = ((int64_t)tv->tv_sec)*1000L; + /* Round ghetto-style */ + conv += ((int64_t)tv->tv_usec+500)/1000L; + return conv; +} + +/** + * Converts timeval to microseconds. + */ +int64_t +tv_to_usec(const struct timeval *tv) +{ + int64_t conv = ((int64_t)tv->tv_sec)*1000000L; + conv += tv->tv_usec; + return conv; +} + /** Return the number of microseconds elapsed between *start and *end. */ long @@ -1009,7 +1144,8 @@ tv_udiff(const struct timeval *start, const struct timeval *end) long secdiff = end->tv_sec - start->tv_sec; if (labs(secdiff+1) > LONG_MAX/1000000) { - log_warn(LD_GENERAL, "comparing times too far apart."); + log_warn(LD_GENERAL, "comparing times on microsecond detail too far " + "apart: %ld seconds", secdiff); return LONG_MAX; } @@ -1017,6 +1153,26 @@ tv_udiff(const struct timeval *start, const struct timeval *end) return udiff; } +/** Return the number of milliseconds elapsed between *start and *end. + */ +long +tv_mdiff(const struct timeval *start, const struct timeval *end) +{ + long mdiff; + long secdiff = end->tv_sec - start->tv_sec; + + if (labs(secdiff+1) > LONG_MAX/1000) { + log_warn(LD_GENERAL, "comparing times on millisecond detail too far " + "apart: %ld seconds", secdiff); + return LONG_MAX; + } + + /* Subtract and round */ + mdiff = secdiff*1000L + + ((long)end->tv_usec - (long)start->tv_usec + 500L) / 1000L; + return mdiff; +} + /** Yield true iff <b>y</b> is a leap-year. */ #define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400))) /** Helper: Return the number of leap-days between Jan 1, y1 and Jan 1, y2. */ @@ -1092,7 +1248,7 @@ format_rfc1123_time(char *buf, time_t t) memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3); } -/** Parse the the RFC1123 encoding of some time (in GMT) from <b>buf</b>, +/** Parse the RFC1123 encoding of some time (in GMT) from <b>buf</b>, * and store the result in *<b>t</b>. * * Return 0 on success, -1 on failure. @@ -1430,6 +1586,49 @@ ftime_definitely_before(time_t now, time_t when) } /* ===== + * Rate limiting + * ===== */ + +/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number + * of calls to rate_limit_is_ready (including this one!) since the last time + * rate_limit_is_ready returned nonzero. Otherwise return 0. */ +static int +rate_limit_is_ready(ratelim_t *lim, time_t now) +{ + if (lim->rate + lim->last_allowed <= now) { + int res = lim->n_calls_since_last_time + 1; + lim->last_allowed = now; + lim->n_calls_since_last_time = 0; + return res; + } else { + ++lim->n_calls_since_last_time; + return 0; + } +} + +/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly + * allocated string indicating how many messages were suppressed, suitable to + * append to a log message. Otherwise return NULL. */ +char * +rate_limit_log(ratelim_t *lim, time_t now) +{ + int n; + if ((n = rate_limit_is_ready(lim, now))) { + if (n == 1) { + return tor_strdup(""); + } else { + char *cp=NULL; + tor_asprintf(&cp, + " [%d similar message(s) suppressed in last %d seconds]", + n-1, lim->rate); + return cp; + } + } else { + return NULL; + } +} + +/* ===== * File helpers * ===== */ @@ -1553,22 +1752,22 @@ check_private_dir(const char *dirname, cpd_check_t check) tor_free(f); if (r) { if (errno != ENOENT) { - log(LOG_WARN, LD_FS, "Directory %s cannot be read: %s", dirname, - strerror(errno)); + log_warn(LD_FS, "Directory %s cannot be read: %s", dirname, + strerror(errno)); return -1; } if (check == CPD_NONE) { - log(LOG_WARN, LD_FS, "Directory %s does not exist.", dirname); + log_warn(LD_FS, "Directory %s does not exist.", dirname); return -1; } else if (check == CPD_CREATE) { log_info(LD_GENERAL, "Creating directory %s", dirname); -#ifdef MS_WINDOWS +#if defined (MS_WINDOWS) && !defined (WINCE) r = mkdir(dirname); #else r = mkdir(dirname, 0700); #endif if (r) { - log(LOG_WARN, LD_FS, "Error creating directory %s: %s", dirname, + log_warn(LD_FS, "Error creating directory %s: %s", dirname, strerror(errno)); return -1; } @@ -1578,7 +1777,7 @@ check_private_dir(const char *dirname, cpd_check_t check) return 0; } if (!(st.st_mode & S_IFDIR)) { - log(LOG_WARN, LD_FS, "%s is not a directory", dirname); + log_warn(LD_FS, "%s is not a directory", dirname); return -1; } #ifndef MS_WINDOWS @@ -1591,7 +1790,7 @@ check_private_dir(const char *dirname, cpd_check_t check) pw = getpwuid(st.st_uid); - log(LOG_WARN, LD_FS, "%s is not owned by this user (%s, %d) but by " + log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by " "%s (%d). Perhaps you are running Tor as the wrong user?", dirname, process_ownername, (int)getuid(), pw ? pw->pw_name : "<unknown>", (int)st.st_uid); @@ -1600,9 +1799,9 @@ check_private_dir(const char *dirname, cpd_check_t check) return -1; } if (st.st_mode & 0077) { - log(LOG_WARN, LD_FS, "Fixing permissions on directory %s", dirname); + log_warn(LD_FS, "Fixing permissions on directory %s", dirname); if (chmod(dirname, 0700)) { - log(LOG_WARN, LD_FS, "Could not chmod directory %s: %s", dirname, + log_warn(LD_FS, "Could not chmod directory %s: %s", dirname, strerror(errno)); return -1; } else { @@ -1633,12 +1832,13 @@ write_str_to_file(const char *fname, const char *str, int bin) } /** Represents a file that we're writing to, with support for atomic commit: - * we can write into a a temporary file, and either remove the file on + * we can write into a temporary file, and either remove the file on * failure, or replace the original file on success. */ struct open_file_t { char *tempname; /**< Name of the temporary file. */ char *filename; /**< Name of the original file. */ - int rename_on_close; /**< Are we using the temporary file or not? */ + unsigned rename_on_close:1; /**< Are we using the temporary file or not? */ + unsigned binary:1; /**< Did we open in binary mode? */ int fd; /**< fd for the open file. */ FILE *stdio_file; /**< stdio wrapper for <b>fd</b>. */ }; @@ -1686,7 +1886,7 @@ start_writing_to_file(const char *fname, int open_flags, int mode, } else { open_name = new_file->tempname = tor_malloc(tempname_len); if (tor_snprintf(new_file->tempname, tempname_len, "%s.tmp", fname)<0) { - log(LOG_WARN, LD_GENERAL, "Failed to generate filename"); + log_warn(LD_GENERAL, "Failed to generate filename"); goto err; } /* We always replace an existing temporary file if there is one. */ @@ -1694,9 +1894,12 @@ start_writing_to_file(const char *fname, int open_flags, int mode, open_flags &= ~O_EXCL; new_file->rename_on_close = 1; } + if (open_flags & O_BINARY) + new_file->binary = 1; - if ((new_file->fd = open(open_name, open_flags, mode)) < 0) { - log(LOG_WARN, LD_FS, "Couldn't open \"%s\" (%s) for writing: %s", + new_file->fd = open(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)); goto err; } @@ -1732,7 +1935,8 @@ fdopen_file(open_file_t *file_data) if (file_data->stdio_file) return file_data->stdio_file; tor_assert(file_data->fd >= 0); - if (!(file_data->stdio_file = fdopen(file_data->fd, "a"))) { + if (!(file_data->stdio_file = fdopen(file_data->fd, + file_data->binary?"ab":"a"))) { log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename, file_data->fd, strerror(errno)); } @@ -1832,7 +2036,7 @@ write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks, { result = write_all(fd, chunk->bytes, chunk->len, 0); if (result < 0) { - log(LOG_WARN, LD_FS, "Error writing to \"%s\": %s", fname, + log_warn(LD_FS, "Error writing to \"%s\": %s", fname, strerror(errno)); goto err; } @@ -2088,7 +2292,40 @@ unescape_string(const char *s, char **result, size_t *size_out) const char * parse_config_line_from_str(const char *line, char **key_out, char **value_out) { + /* I believe the file format here is supposed to be: + FILE = (EMPTYLINE | LINE)* (EMPTYLASTLINE | LASTLINE)? + + EMPTYLASTLINE = SPACE* | COMMENT + EMPTYLINE = EMPTYLASTLINE NL + SPACE = ' ' | '\r' | '\t' + COMMENT = '#' NOT-NL* + NOT-NL = Any character except '\n' + NL = '\n' + + LASTLINE = SPACE* KEY SPACE* VALUES + LINE = LASTLINE NL + KEY = KEYCHAR+ + KEYCHAR = Any character except ' ', '\r', '\n', '\t', '#', "\" + + VALUES = QUOTEDVALUE | NORMALVALUE + QUOTEDVALUE = QUOTE QVITEM* QUOTE EOLSPACE? + QUOTE = '"' + QVCHAR = KEYCHAR | ESC ('n' | 't' | 'r' | '"' | ESC |'\'' | OCTAL | HEX) + ESC = "\\" + OCTAL = ODIGIT (ODIGIT ODIGIT?)? + HEX = ('x' | 'X') HEXDIGIT HEXDIGIT + ODIGIT = '0' .. '7' + HEXDIGIT = '0'..'9' | 'a' .. 'f' | 'A' .. 'F' + EOLSPACE = SPACE* COMMENT? + + NORMALVALUE = (VALCHAR | ESC ESC_IGNORE | CONTINUATION)* EOLSPACE? + VALCHAR = Any character except ESC, '#', and '\n' + ESC_IGNORE = Any character except '#' or '\n' + CONTINUATION = ESC NL ( COMMENT NL )* + */ + const char *key, *val, *cp; + int continuation = 0; tor_assert(key_out); tor_assert(value_out); @@ -2112,9 +2349,10 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out) return line; } - /* Skip until the next space. */ + /* Skip until the next space or \ followed by newline. */ key = line; - while (*line && !TOR_ISSPACE(*line) && *line != '#') + while (*line && !TOR_ISSPACE(*line) && *line != '#' && + ! (line[0] == '\\' && line[1] == '\n')) ++line; *key_out = tor_strndup(key, line-key); @@ -2125,7 +2363,7 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out) val = line; /* Find the end of the line. */ - if (*line == '\"') { + if (*line == '\"') { // XXX No continuation handling is done here if (!(line = unescape_string(line, value_out, NULL))) return NULL; while (*line == ' ' || *line == '\t') @@ -2133,18 +2371,53 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out) if (*line && *line != '#' && *line != '\n') return NULL; } else { - while (*line && *line != '\n' && *line != '#') - ++line; + /* Look for the end of the line. */ + while (*line && *line != '\n' && (*line != '#' || continuation)) { + if (*line == '\\' && line[1] == '\n') { + continuation = 1; + line += 2; + } else if (*line == '#') { + do { + ++line; + } while (*line && *line != '\n'); + if (*line == '\n') + ++line; + } else { + ++line; + } + } + if (*line == '\n') { cp = line++; } else { cp = line; } + /* Now back cp up to be the last nonspace character */ while (cp>val && TOR_ISSPACE(*(cp-1))) --cp; tor_assert(cp >= val); + + /* Now copy out and decode the value. */ *value_out = tor_strndup(val, cp-val); + if (continuation) { + char *v_out, *v_in; + v_out = v_in = *value_out; + while (*v_in) { + if (*v_in == '#') { + do { + ++v_in; + } while (*v_in && *v_in != '\n'); + if (*v_in == '\n') + ++v_in; + } else if (v_in[0] == '\\' && v_in[1] == '\n') { + v_in += 2; + } else { + *v_out++ = *v_in++; + } + } + *v_out = '\0'; + } } if (*line == '#') { @@ -2163,19 +2436,22 @@ char * expand_filename(const char *filename) { tor_assert(filename); +#ifdef MS_WINDOWS + return tor_strdup(filename); +#else if (*filename == '~') { - size_t len; - char *home, *result; + char *home, *result=NULL; const char *rest; if (filename[1] == '/' || filename[1] == '\0') { home = getenv("HOME"); if (!home) { log_warn(LD_CONFIG, "Couldn't find $HOME environment variable while " - "expanding \"%s\"", filename); - return NULL; + "expanding \"%s\"; defaulting to \"\".", filename); + home = tor_strdup(""); + } else { + home = tor_strdup(home); } - home = tor_strdup(home); rest = strlen(filename)>=2?(filename+2):""; } else { #ifdef HAVE_PWD_H @@ -2202,21 +2478,19 @@ expand_filename(const char *filename) if (strlen(home)>1 && !strcmpend(home,PATH_SEPARATOR)) { home[strlen(home)-1] = '\0'; } - /* Plus one for /, plus one for NUL. - * Round up to 16 in case we can't do math. */ - len = strlen(home)+strlen(rest)+16; - result = tor_malloc(len); - tor_snprintf(result,len,"%s"PATH_SEPARATOR"%s",home,rest); + tor_asprintf(&result,"%s"PATH_SEPARATOR"%s",home,rest); tor_free(home); return result; } else { return tor_strdup(filename); } +#endif } #define MAX_SCANF_WIDTH 9999 -/** DOCDOC */ +/** Helper: given an ASCII-encoded decimal digit, return its numeric value. + * NOTE: requires that its input be in-bounds. */ static int digit_to_num(char d) { @@ -2225,7 +2499,10 @@ digit_to_num(char d) return num; } -/** DOCDOC */ +/** Helper: Read an unsigned int from *<b>bufp</b> of up to <b>width</b> + * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On + * 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) { @@ -2252,7 +2529,9 @@ scan_unsigned(const char **bufp, unsigned *out, int width) return 0; } -/** DOCDOC */ +/** Helper: copy up to <b>width</b> non-space characters from <b>bufp</b> to + * <b>out</b>. Make sure <b>out</b> is nul-terminated. Advance <b>bufp</b> + * to the next non-space character or the EOS. */ static int scan_string(const char **bufp, char *out, int width) { @@ -2341,7 +2620,12 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) * 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. */ + * 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 + * miscellaneous characters look like numbers, spaces, and so on.) + */ int tor_sscanf(const char *buf, const char *pattern, ...) { @@ -2362,20 +2646,32 @@ tor_listdir(const char *dirname) smartlist_t *result; #ifdef MS_WINDOWS char *pattern; + TCHAR tpattern[MAX_PATH] = {0}; + char name[MAX_PATH] = {0}; HANDLE handle; WIN32_FIND_DATA findData; size_t pattern_len = strlen(dirname)+16; pattern = tor_malloc(pattern_len); tor_snprintf(pattern, pattern_len, "%s\\*", dirname); - if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(pattern, &findData))) { +#ifdef UNICODE + mbstowcs(tpattern,pattern,MAX_PATH); +#else + strlcpy(tpattern, pattern, MAX_PATH); +#endif + if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &findData))) { tor_free(pattern); return NULL; } result = smartlist_create(); while (1) { - if (strcmp(findData.cFileName, ".") && - strcmp(findData.cFileName, "..")) { - smartlist_add(result, tor_strdup(findData.cFileName)); +#ifdef UNICODE + wcstombs(name,findData.cFileName,MAX_PATH); +#else + strlcpy(name,findData.cFileName,sizeof(name)); +#endif + if (strcmp(name, ".") && + strcmp(name, "..")) { + smartlist_add(result, tor_strdup(name)); } if (!FindNextFile(handle, &findData)) { DWORD err; @@ -2574,3 +2870,18 @@ write_pidfile(char *filename) } } +#ifdef MS_WINDOWS +HANDLE +load_windows_system_library(const TCHAR *library_name) +{ + TCHAR path[MAX_PATH]; + unsigned n; + n = GetSystemDirectory(path, MAX_PATH); + if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH) + return 0; + _tcscat(path, TEXT("\\")); + _tcscat(path, library_name); + return LoadLibrary(path); +} +#endif + diff --git a/src/common/util.h b/src/common/util.h index fa66d7cf40..833fd904c7 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -43,7 +43,7 @@ * stderr. */ #define tor_assert(expr) STMT_BEGIN \ if (PREDICT_UNLIKELY(!(expr))) { \ - log(LOG_ERR, LD_BUG, "%s:%d: %s: Assertion %s failed; aborting.", \ + log_err(LD_BUG, "%s:%d: %s: Assertion %s failed; aborting.", \ _SHORT_FILE_, __LINE__, __func__, #expr); \ fprintf(stderr,"%s:%d %s: Assertion %s failed; aborting.\n", \ _SHORT_FILE_, __LINE__, __func__, #expr); \ @@ -152,8 +152,18 @@ void tor_log_mallinfo(int severity); #define bool_neq(a,b) (!(a)!=!(b)) /* Math functions */ +double tor_mathlog(double d) ATTR_CONST; +long tor_lround(double d) ATTR_CONST; int tor_log2(uint64_t u64) ATTR_CONST; 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); + +/* 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 + * overflow. */ +#define CEIL_DIV(a,b) (((a)+(b)-1)/(b)) /* String manipulation */ @@ -179,6 +189,8 @@ long tor_parse_long(const char *s, int base, long min, long max, int *ok, char **next); unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, unsigned long max, int *ok, char **next); +double tor_parse_double(const char *s, double min, double max, int *ok, + char **next); 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)); @@ -188,8 +200,11 @@ 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; char *esc_for_log(const char *string) ATTR_MALLOC; const char *escaped(const char *string); struct smartlist_t; @@ -207,7 +222,11 @@ 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); /* Time helpers */ +double tv_to_double(const struct timeval *tv); +int64_t tv_to_msec(const struct timeval *tv); +int64_t tv_to_usec(const struct timeval *tv); long tv_udiff(const struct timeval *start, const struct timeval *end); +long tv_mdiff(const struct timeval *start, const struct timeval *end); time_t tor_timegm(struct tm *tm); #define RFC1123_TIME_LEN 29 void format_rfc1123_time(char *buf, time_t t); @@ -238,6 +257,33 @@ int ftime_maybe_before(time_t now, time_t when); int ftime_definitely_after(time_t now, time_t when); int ftime_definitely_before(time_t now, time_t when); +/* Rate-limiter */ + +/** A ratelim_t remembers how often an event is occurring, and how often + * it's allowed to occur. Typical usage is something like: + * + <pre> + if (possibly_very_frequent_event()) { + const int INTERVAL = 300; + static ratelim_t warning_limit = RATELIM_INIT(INTERVAL); + char *m; + if ((m = rate_limit_log(&warning_limit, approx_time()))) { + log_warn(LD_GENERAL, "The event occurred!%s", m); + tor_free(m); + } + } + </pre> + */ +typedef struct ratelim_t { + int rate; + time_t last_allowed; + int n_calls_since_last_time; +} ratelim_t; + +#define RATELIM_INIT(r) { (r), 0, 0 } + +char *rate_limit_log(ratelim_t *lim, time_t now); + /* File helpers */ ssize_t write_all(int fd, const char *buf, size_t count, int isSocket); ssize_t read_all(int fd, char *buf, size_t count, int isSocket); @@ -294,5 +340,11 @@ void start_daemon(void); void finish_daemon(const char *desired_cwd); void write_pidfile(char *filename); +#ifdef MS_WINDOWS +HANDLE load_windows_system_library(const TCHAR *library_name); +#endif + +const char *libor_get_digests(void); + #endif diff --git a/src/common/util_codedigest.c b/src/common/util_codedigest.c new file mode 100644 index 0000000000..88fe508b92 --- /dev/null +++ b/src/common/util_codedigest.c @@ -0,0 +1,11 @@ + +#include "util.h" + +const char * +libor_get_digests(void) +{ + return "" +#include "common_sha1.i" + ; +} + diff --git a/src/config/geoip b/src/config/geoip index 6e2cbbdf49..e28e7b0a53 100644 --- a/src/config/geoip +++ b/src/config/geoip @@ -1,4 +1,4 @@ -# Last updated based on October 1 2010 Maxmind GeoLite Country +# Last updated based on December 1 2010 Maxmind GeoLite Country # wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip # cut -d, -f3-5 < GeoIPCountryWhois.csv|sed 's/"//g' > geoip 16777216,17301503,AU @@ -45,7 +45,14 @@ 35651584,36700159,IT 36700160,36962303,AE 36962304,37224447,IL -37224448,37486591,UA +37224448,37265407,UA +37265408,37268479,CZ +37268480,37289983,UA +37289984,37298175,RU +37298176,37355519,UA +37355520,37421055,RU +37421056,37486591,UA +37486592,37748735,RU 37748736,38273023,SE 38273024,38797311,KZ 38797312,39059455,PT @@ -56,7 +63,15 @@ 40370176,40894463,DK 40894464,41418751,IT 41418752,41943039,GB +42467328,42991615,ES +42991616,43253759,IR +43253760,43515903,NO +43515904,43778047,ES +43778048,44040191,IT 44040192,45088767,DE +45088768,46137343,IR +46137344,46661631,IT +46661632,47710207,DE 50331648,68257567,US 68257568,68257599,CA 68257600,68259583,US @@ -261,9 +276,7 @@ 209831680,209831711,DE 209831712,209845143,US 209845144,209845151,DE -209845152,209854735,US -209854736,209854743,SE -209854744,209867103,US +209845152,209867103,US 209867104,209867111,CA 209867112,209868799,US 209868800,209869055,IR @@ -293,9 +306,7 @@ 211363752,211363759,PR 211363760,211368655,US 211368656,211368663,PR -211368664,211403527,US -211403528,211403535,MS -211403536,211410031,US +211368664,211410031,US 211410032,211410039,PR 211410040,211410119,US 211410120,211410135,PR @@ -533,7 +544,8 @@ 214698336,214698343,US 214698344,214698351,VI 214698352,214698359,US -214698360,214698375,VI +214698360,214698367,PR +214698368,214698375,VI 214698376,214698383,US 214698384,214698639,PR 214698640,214698655,VI @@ -572,7 +584,6 @@ 217028008,217046775,US 217046776,217046783,PR 217046784,234881023,US -234882304,234882559,AP 234883072,234884095,JP 234885120,234889215,VN 234889216,234913791,KR @@ -670,8 +681,7 @@ 405979136,405995519,PR 406003712,406011903,US 406011904,406028287,BS -406044672,406052863,US -406061056,406126591,US +406028288,406126591,US 406142976,406147071,US 406147072,406151167,CA 406159360,406175743,US @@ -698,15 +708,27 @@ 409862144,410124287,US 410124288,410177751,CA 410177752,410177755,US -410177756,410185355,CA +410177756,410180643,CA +410180644,410180647,US +410180648,410185355,CA 410185356,410185359,US 410185360,410185407,CA 410185408,410185411,US -410185412,410187047,CA +410185412,410185555,CA +410185556,410185559,US +410185560,410186719,CA +410186720,410186723,US +410186724,410186971,CA +410186972,410186979,US +410186980,410186983,CA +410186984,410186999,US +410187000,410187047,CA 410187048,410187055,US 410187056,410187175,CA 410187176,410187183,US -410187184,410187703,CA +410187184,410187231,CA +410187232,410187239,US +410187240,410187703,CA 410187704,410187707,US 410187708,410189823,CA 410189824,410648575,US @@ -788,7 +810,9 @@ 418693120,418709503,CA 418709504,418766847,US 418766848,418770943,CA -418770944,419430399,US +418770944,418775039,US +418775040,418807807,CA +418807808,419430399,US 419430400,436207615,GB 436207616,452984831,US 452984832,452985855,JP @@ -879,7 +903,6 @@ 460155904,460156927,AU 460156928,460158975,KH 460158976,460159999,JP -460160000,460161023,ID 460161024,460193791,MO 460193792,460210175,JP 460210176,460214271,HK @@ -893,7 +916,6 @@ 460263424,460267519,NP 460267520,460275711,ID 460275712,460277759,AU -460277760,460278783,PG 460278784,460279807,JP 460279808,460283903,AU 460283904,460292095,KR @@ -929,7 +951,7 @@ 460596224,460597247,AU 460597248,460598271,JP 460598272,460599295,CN -460599296,460600319,IN +460599296,460601343,IN 460601344,460602367,AF 460602368,460603391,KH 460603392,460718079,KR @@ -946,6 +968,51 @@ 460943360,460945407,AU 460947456,460980223,JP 460980224,460981247,NC +460982272,460983295,JP +460983296,460984319,HK +460984320,460988415,PG +460988416,460994559,JP +460994560,460995583,MY +460995584,460996607,SG +460996608,461008895,JP +461008896,461012991,AU +461012992,461045759,KR +461045760,461047807,ID +461047808,461049855,JP +461049856,461050879,TH +461050880,461051903,NZ +461051904,461053951,AU +461053952,461062143,AP +461062144,461078527,IN +461078528,461094911,FJ +461094912,461099007,AP +461099008,461100031,JP +461100032,461101055,MN +461101056,461102079,IN +461102080,461103103,ID +461103104,461111295,PH +461111296,461127679,IN +461127680,461131775,PH +461131776,461135871,ID +461135872,461139967,AU +461144064,461209599,KR +461209600,461225983,SG +461225984,461227007,WF +461227008,461228031,SG +461228032,461229055,IN +461229056,461230079,JP +461230080,461234175,AU +461234176,461242367,MY +461242368,461258751,KR +461258752,461279231,JP +461279232,461281279,AU +461281280,461282303,PH +461282304,461283327,MY +461283328,461287423,JP +461287424,461307903,HK +461307904,461357055,JP +461357056,461369343,AU +461369344,461373439,JP 461373440,461504511,CN 461504512,461570047,TH 461570048,461572095,ID @@ -980,7 +1047,9 @@ 469696512,469712895,PK 469712896,469729279,KR 469729280,469762047,IN -469762048,539624567,US +469762048,520093695,US +524288000,528482303,GB +536870912,539624567,US 539624568,539624575,IE 539624576,539624703,US 539624704,539624735,GB @@ -1001,7 +1070,10 @@ 539626496,539626543,GB 539626544,539627127,US 539627128,539627135,SE -539627136,539627391,US +539627136,539627231,US +539627232,539627247,JP +539627248,539627263,AN +539627264,539627391,US 539627392,539627399,JP 539627400,539627407,IE 539627408,539627423,JP @@ -1077,7 +1149,11 @@ 540814016,540814079,US 540814080,540814271,TW 540814272,540814279,DE -540814280,540819455,US +540814280,540814511,US +540814512,540814519,SG +540814520,540814719,US +540814720,540814735,SG +540814736,540819455,US 540819456,540823551,CA 540823552,540826671,US 540826672,540826719,CA @@ -1112,6 +1188,7 @@ 543691008,543844351,US 543844352,543844607,CH 543844608,603979775,US +603979776,620756991,AU 637534208,644067391,US 644067392,644067455,CA 644067456,644835071,US @@ -1131,6 +1208,8 @@ 691863552,691929087,ZA 691929088,691994623,SN 691994624,692011007,ZM +692011008,692027391,ZA +692027392,692035583,MG 692043776,692060159,NA 692060160,692191231,EG 692191232,692207615,CI @@ -1172,6 +1251,13 @@ 692760576,692768767,ZA 692768768,692772863,MG 692772864,692776959,ZA +692776960,692781055,AO +692781056,692785151,BW +692785152,692789247,NG +692789248,692793343,KE +692793344,692797439,GH +692797440,692801535,CG +692801536,692805631,NG 692830208,692834303,NG 692834304,692838399,TZ 692838400,692842495,ZA @@ -1186,6 +1272,7 @@ 692860928,692862975,ZA 692862976,692869119,NG 692869120,692871167,TZ +692871168,692873215,ZA 692875264,692877311,ZA 692877312,692879359,GA 692879360,692881407,ZA @@ -1198,6 +1285,7 @@ 692893696,692895743,KE 692895744,692897791,NG 692897792,692905983,ZA +692905984,692908031,ZW 692969472,692971519,TZ 692973568,692975615,MZ 692975616,692977663,EG @@ -1209,6 +1297,7 @@ 692983808,692984831,KE 692984832,692987903,ZA 692987904,692988927,GH +692988928,692989951,ZW 692989952,692990975,BF 692992000,692993023,MW 692993024,692994047,EG @@ -1239,6 +1328,12 @@ 693018624,693019647,UG 693019648,693020671,ZA 693020672,693021695,TZ +693021696,693022719,NG +693022720,693023743,KE +693023744,693026815,ZA +693026816,693027839,MU +693027840,693028863,CD +693028864,693029887,ZA 693101568,693102591,KE 693102592,693103615,CD 693103616,693104639,GN @@ -1248,6 +1343,10 @@ 693107712,693239807,KE 693239808,693370879,SN 693370880,693403647,ZA +693403648,693411839,KE +693411840,693420031,NG +693420032,693428223,UG +693428224,693436415,SZ 693501952,693510143,LR 693510144,693518335,SC 693518336,693534719,ZA @@ -1642,12 +1741,15 @@ 703594496,704118783,ZA 704118784,704380927,MA 704380928,704643071,LY +704643072,721420287,AU 721420288,738197503,JP 738197504,771751935,US 771751936,771817471,RU 771817472,771948543,TR 771948544,772014079,RU -772014080,772145151,DE +772014080,772057727,DE +772057728,772057735,IT +772057736,772145151,DE 772145152,772210687,ES 772210688,772276223,IE 772276224,772341759,RU @@ -1657,22 +1759,187 @@ 772538368,772603903,GR 772603904,772669439,CZ 772669440,772734975,CH +772734976,772800511,NO 772800512,772802559,GB 772802560,772804607,RU 772804608,772806655,BZ 772806656,772808703,RU +772808704,772810751,GB +772810752,772812799,FR +772812800,772814847,NO +772814848,772816895,ES +772816896,772818943,RU +772818944,772820991,DE +772820992,772823039,GB +772823040,772825087,IT +772825088,772827135,RU +772827136,772829183,RS +772829184,772831231,EE +772831232,772833279,CZ +772833280,772835327,RU +772835328,772837375,CY +772837376,772839423,KZ +772839424,772841471,CH +772841472,772843519,GB +772843520,772845567,IT +772845568,772847615,RU +772847616,772849663,GB +772849664,772851711,BG +772851712,772853759,CH +772853760,772855807,GB +772855808,772857855,DE +772857856,772859903,RU +772859904,772861951,SE +772861952,772863999,UA +772864000,772870143,NL +772870144,772872191,NO +772872192,772874239,NL +772874240,772876287,IE +772876288,772880383,RU +772880384,772882431,GB +772882432,772884479,FR +772884480,772884543,GB +772884544,772884735,LB +772884736,772884799,GB +772884800,772885503,LB +772885504,772885567,GB +772885568,772885759,LB +772885760,772885823,GB +772885824,772886527,LB +772886528,772888575,FR +772888576,772890623,GB +772890624,772892671,RU +772892672,772894719,DE +772894720,772896767,PL +772896768,772898815,RS +772898816,772900863,TR +772900864,772902911,ES +772902912,772904959,RS +772904960,772907007,IT +772907008,772909055,GB +772909056,772911103,LU +772911104,772913151,GB +772913152,772915199,SE +772915200,772917247,FI +772917248,772919295,RU +772919296,772923391,GB +772923392,772925439,AT +772925440,772927487,GB +772927488,772929535,UA +772929536,772931583,RU +772931584,772933631,UA +772933632,772935679,GB +772935680,772937727,PS +772937728,772939775,IT +772939776,772941823,BE +772941824,772943871,ES +772943872,772945919,GB +772945920,772947967,DE +772947968,772950015,AZ +772950016,772952063,ES +772952064,772954111,GB +772954112,772958207,FR +772958208,772960255,PL +772960256,772962303,GB +772962304,772966399,FR +772966400,772968447,IT +772968448,772970495,SK +772970496,772972543,GB +772972544,772974591,SA +772974592,772978687,GB +772978688,772980735,DE +772980736,772982783,FR +772982784,772984831,RU +772984832,772986879,FR +772986880,772988927,GB +772988928,772990975,FR +772990976,772993023,IT +772993024,772995071,DE +772995072,772997119,IR +772997120,772999167,BE +772999168,773001215,SI 773001216,773003263,NO +773003264,773005311,FR +773005312,773007359,NL +773007360,773009407,KZ +773009408,773011455,IT +773011456,773013503,DE +773013504,773015551,RU +773015552,773017599,AE +773017600,773019647,IL +773019648,773021695,DE +773021696,773023743,AM +773023744,773025791,RO +773025792,773027839,RU +773027840,773031935,FR +773031936,773033983,CH +773033984,773036031,LV +773036032,773038079,DE +773038080,773040127,GB +773040128,773042175,NL +773042176,773044223,FR +773044224,773046271,RU +773046272,773048319,LB +773048320,773050367,LV +773050368,773052415,IE +773052416,773054463,NL +773054464,773056511,AL +773056512,773058559,IT +773058560,773060607,BE +773060608,773062655,DK 773062656,773062911,TR 773062912,773063167,US -773063168,773063935,TR -773063936,773064703,US -773064704,773066751,TR +773063168,773063424,TR +773063425,773063436,US +773063437,773063935,TR +773063936,773065215,US +773065216,773066751,TR 773066752,773070847,AT 773070848,773074943,DE 773074944,773079039,PL 773079040,773083135,RU 773083136,773087231,IT 773087232,773091327,LB +773091328,773095423,GB +773095424,773099519,RO +773099520,773103615,TR +773103616,773107711,FR +773107712,773111807,RU +773111808,773115903,TJ +773115904,773119999,PS +773120000,773124095,GB +773124096,773128191,CH +773128192,773132287,DE +773132288,773134335,IT +773134336,773134847,CH +773134848,773135359,IT +773135360,773135871,CH +773135872,773136383,IT +773136384,773140479,DK +773140480,773144575,CY +773144576,773148671,RU +773148672,773152767,IR +773152768,773156863,SE +773156864,773165055,FR +773165056,773168127,NL +773168128,773168383,US +773168384,773173247,NL +773173248,773177343,IT +773177344,773181439,FR +773181440,773185535,PL +773185536,773189631,NL +773189632,773197823,RU +773197824,773201919,CH +773201920,773206015,DE +773206016,773210111,RU +773210112,773214207,US +773214208,773218303,FR +773218304,773222399,IS +773222400,773226495,SE +773226496,773230591,IE +773230592,773234687,RS +773234688,773238783,PL +773238784,773242879,NL 773324800,773586943,ES 773586944,773588991,IT 773588992,773591039,PL @@ -1722,9 +1989,12 @@ 773675008,773677055,GB 773677056,773679103,DE 773679104,773679135,IT -773679136,773679359,A2 +773679136,773679327,A2 +773679328,773679359,IT 773679360,773679423,GB -773679424,773681151,A2 +773679424,773679615,A2 +773679616,773680191,IT +773680192,773681151,A2 773681152,773683199,RU 773683200,773685247,FR 773685248,773687295,UA @@ -1795,7 +2065,6 @@ 773820416,773822463,TR 773822464,773824511,RU 773824512,773826559,FR -773826560,773828607,NL 773828608,773830655,HU 773830656,773832703,NO 773832704,773834751,FR @@ -1820,11 +2089,184 @@ 773963776,773971967,ME 773971968,773980159,UA 773980160,773988351,GB -773988352,774004735,ES +773988352,774003199,ES +774003200,774003263,TR +774003264,774003711,ES +774003712,774004223,BE +774004224,774004479,ES +774004480,774004511,BE +774004512,774004735,ES 774004736,774012927,IR 774012928,774021119,RU 774021120,774029311,IR 774029312,774037503,RO +774037504,774045695,SK +774045696,774053887,FR +774053888,774061567,DE +774061568,774061695,BZ +774061696,774061823,DE +774061824,774061951,BZ +774061952,774062079,DE +774062080,774070271,YE +774070272,774078463,ES +774078464,774086655,BA +774086656,774094847,BG +774094848,774103039,HU +774103040,774111231,UA +774111232,774119423,RU +774119424,774127615,CZ +774127616,774135807,LT +774135808,774143999,IR +774144000,774152191,KZ +774152192,774160383,BA +774160384,774160415,VA +774160416,774160448,LI +774160449,774160480,IM +774160481,774160514,IS +774160515,774160547,RU +774160548,774160580,AE +774160581,774160612,DK +774160613,774160639,AT +774160640,774160671,GI +774160672,774160702,CY +774160703,774160735,CH +774160736,774160768,GR +774160769,774160801,IL +774160802,774160832,BG +774160833,774160864,NO +774160865,774160869,BR +774160870,774160873,CA +774160874,774160895,CR +774160896,774160927,PA +774160928,774160935,CU +774160936,774160946,BS +774160947,774160956,KY +774160957,774160966,JM +774160967,774160976,PR +774160977,774160986,VG +774160987,774160996,CO +774160997,774161006,GT +774161007,774161016,CN +774161017,774161026,EG +774161027,774161036,FJ +774161037,774161046,IN +774161047,774161056,MH +774161057,774161066,JP +774161067,774161076,MX +774161077,774161086,NZ +774161087,774161096,MY +774161097,774161106,PE +774161107,774161116,PH +774161117,774161126,SA +774161127,774161136,SC +774161137,774161146,SG +774161147,774161151,VA +774161152,774161162,AQ +774161163,774161172,KR +774161173,774161182,TH +774161183,774161192,QA +774161193,774161202,VI +774161203,774161212,BM +774161213,774161222,BB +774161223,774161232,AW +774161233,774161242,BZ +774161243,774161252,MC +774161253,774161262,GB +774161263,774161272,TR +774161273,774161282,MT +774161283,774161292,SE +774161293,774161302,US +774161303,774161312,HK +774161313,774161322,IE +774161323,774161332,PK +774161333,774161337,KW +774161338,774161342,JO +774161343,774161347,OM +774161348,774161352,ID +774161353,774161357,TW +774161358,774161362,AI +774161363,774161367,KN +774161368,774161372,GD +774161373,774161377,DO +774161378,774161382,PY +774161383,774161387,EE +774161388,774161392,LU +774161393,774161397,SK +774161398,774161402,SI +774161403,774161405,LC +774161406,774161408,VA +774161409,774161418,AU +774161419,774161428,GL +774161429,774161438,HU +774161439,774161448,MK +774161449,774161458,PS +774161459,774161468,UZ +774161469,774161478,BD +774161479,774161488,KP +774161489,774161498,MN +774161499,774161518,VA +774161519,774161528,TW +774161529,774161538,DO +774161539,774161548,PY +774161549,774161558,EE +774161559,774161568,SK +774161569,774161578,LC +774161579,774161588,VE +774161589,774161598,TC +774161599,774161608,US +774161609,774161618,LI +774161619,774161628,AE +774161629,774161638,PA +774161639,774161648,RU +774161649,774161658,HK +774161659,774161664,VA +774161665,774161674,CY +774161675,774161684,CL +774161685,774161694,NI +774161695,774161704,AG +774161705,774161714,AM +774161715,774161724,IR +774161725,774161734,RO +774161735,774161744,UA +774161745,774161754,NP +774161755,774161764,PG +774161765,774168575,VA +774168576,774176767,PL +774176768,774184959,IT +774184960,774193151,GB +774193152,774209535,ES +774209536,774217727,RU +774217728,774224127,GB +774224128,774224159,CN +774224160,774225279,GB +774225280,774225343,CN +774225344,774225359,GB +774225360,774225375,UA +774225376,774225391,GB +774225392,774225407,UA +774225408,774225599,GB +774225600,774225615,PK +774225616,774225631,GB +774225632,774225647,CN +774225648,774225663,UA +774225664,774225671,LK +774225672,774225679,US +774225680,774225687,CN +774225688,774225695,CA +774225696,774225703,RU +774225704,774225711,LK +774225712,774225719,PK +774225720,774225791,GB +774225792,774225807,UA +774225808,774225823,GB +774225824,774225919,US +774225920,774234111,UA +774234112,774242303,IT +774242304,774258687,RU +774258688,774266879,SA +774266880,774275071,RU +774275072,774283263,IR +774283264,774291455,GB 774373376,774389759,RS 774389760,774406143,BG 774406144,774422527,IT @@ -1850,7 +2292,11 @@ 774750208,774782975,RU 774782976,774799359,UA 774799360,774815743,RU -774897664,774963199,RU +774815744,774832127,SE +774832128,774848511,RU +774848512,774864895,BG +774864896,774881279,CZ +774881280,774963199,RU 774963200,774995967,GE 774995968,775028735,RO 775028736,775061503,PT @@ -1864,6 +2310,20 @@ 775290880,775323647,MT 775323648,775356415,SI 775356416,775389183,MD +775389184,775421951,BG +775421952,775487487,BY +775487488,775520255,AT +775520256,775553023,SY +775553024,775585791,EU +775585792,775618559,SY +775618560,775651327,SE +775651328,775684095,DE +775684096,775716863,PS +775716864,775749631,GB +775749632,775847935,RU +775847936,775880703,RO +775880704,775913471,UA +775913472,775946239,RU 775946240,776077311,GB 776077312,776208383,NO 776208384,776339455,GB @@ -1882,6 +2342,7 @@ 778502144,778534911,GR 778534912,778567679,CY 778567680,778633215,TR +778633216,778698751,FR 778698752,778764287,TR 778764288,778829823,HU 778829824,778895359,RO @@ -1896,27 +2357,221 @@ 779747328,779878399,SI 779878400,780009471,AT 780009472,780140543,CH +780140544,780206079,DE +780206080,780271615,NL +780271616,780337151,AM +780337152,780402687,EE +780402688,780468223,FI +780468224,780533759,UA +780533760,780599295,PL +780599296,780664831,CZ +780664832,780664960,NL +780664961,780730367,FR +780730368,780795903,IE +780795904,780861439,RU +780861440,780926975,HU +780926976,780992511,CH +780992512,781058047,IT +781058048,781123583,DE +781123584,781189119,IR +781189120,781320191,NL +781320192,781451263,RU +781451264,781455359,PL +781455360,781459455,UA +781459456,781463551,IR +781463552,781467647,RU +781467648,781475839,PL +781475840,781479935,RU +781479936,781484031,UA +781484032,781488127,RU +781488128,781496319,PL +781496320,781504511,RU +781582336,781590527,UA +781590528,781598719,SI +781598720,781615103,UA +781615104,781631487,RU +781631488,781639679,SK +781639680,781651967,RU +781651968,781654015,PL +781654016,781656063,RU +781656064,781658111,RO +781658112,781662207,UA +781662208,781664255,SK +781664256,781666303,UA +781666304,781668351,PL +781668352,781670399,UA +781670400,781672447,RU +781672448,781674495,BE +781674496,781676543,RU +781676544,781678591,PL +781678592,781682687,RS +781713408,781844479,SA +781844480,781975551,TR +781975552,782106623,GB +782106624,782254079,RU +782254080,782270463,UA +782270464,782305791,RU +782305792,782306303,RO +782306304,782319615,RU +782319616,782335999,ME +782336000,782352383,RU +782352384,782368767,SY +782368768,782385151,UA +782385152,782401535,SE +782401536,782417919,FR +782417920,782434303,AM +782761984,782893055,PL +783679488,783681535,FR +783681536,783683583,IE +783683584,783685631,DE +783685632,783687679,RU +783687680,783689727,PT +783689728,783691775,FR +783691776,783693823,BY +783693824,783695871,GB +783695872,783697919,TR +783697920,783699967,FR +783699968,783702015,UA +783702016,783704063,IT +783704064,783706111,PL +783706112,783708159,NL +783708160,783710207,FI +783710208,783712255,NL +783712256,783714303,RU +783714304,783718399,DE +783718400,783720447,IT +783720448,783722495,FI +783722496,783724543,AM +783724544,783726591,NL +783726592,783728639,IS +783728640,783730687,BE +783730688,783732735,SE +783732736,783734783,FR +783734784,783736831,NL +783736832,783738879,SI +783810560,783843327,SA +783843328,783876095,BH +783876096,783908863,UA +783908864,783941631,JO +783941632,783974399,PL +783974400,784007167,KW +784007168,784039935,RU +784039936,784072703,PL +784072704,784105471,RU +784105472,784138239,HR 788529152,805306367,CA 805306368,822083583,US 822083584,822083839,AP 822083840,822084095,AU +822084608,822085631,ID +822085632,822087679,AU +822087680,822089727,JP +822089728,822090751,ID +822090752,822091775,NZ +822091776,822099967,BD +822099968,822116351,TH +822116352,822149119,MN +822149120,822214655,KR 822214656,822345727,AU 822345728,822607871,CN +822607872,822870015,KR +822870016,823132159,IN +823132160,824180735,KR +824180736,825229311,IN 825229312,825360383,TH 825360384,825361407,AP +825361408,825363455,ID +825363456,825364479,MY +825364480,825376767,KR +825376768,825393151,IN +825393152,825409535,KR +825409536,825419775,NZ +825419776,825420799,TH +825420800,825421823,MY +825421824,825425919,NZ 825425920,825491455,AU -830406656,830472703,AU +825491456,825753599,CN +825753600,826277887,KR +826277888,828375039,CN +828375040,829423615,JP +829423616,830210047,CN +830210048,830341119,MY +830341120,830406655,NP +830406656,830474239,AU +830474240,830475263,SG +830475264,830476287,AU +830476288,830480383,JP +830480384,830488575,SG +830488576,830496767,TW +830496768,830498815,JP +830498816,830499839,GU +830499840,830500863,IN +830500864,830504959,TW +830504960,830513151,JP +830513152,830517247,IN +830517248,830521343,ID +830521344,830529535,KR +830529536,830537727,AU +830537728,830603263,JP +830603264,830734335,HK +830734336,830996479,JP +830996480,831258623,IN +831258624,831389695,CN +831389696,831512575,KR +831512576,831513599,AU +831513600,831514623,NZ +831514624,831515647,HK +831515648,831516671,AU +831516672,831518719,JP +831518720,831519743,AU +831519744,831520767,IN +831520768,832045055,PH +832045056,832307199,CN +832307200,832308223,MN +832308224,832311295,JP +832311296,832312319,AU +832312320,832313343,ID +832313344,832315391,AU +832315392,832319487,KH +832319488,832320511,NU +832320512,832321535,VN +832321536,832323583,ID +832323584,832348159,IN +832348160,832372735,JP +832372736,832438271,PH +832438272,832569343,TW +832569344,833617919,KR +836763648,837025791,NZ +837025792,837287935,TH +837287936,837550079,CN +837550080,837566463,IN +837566464,837599231,KR +837599232,837603327,MY +837603328,837604351,VN +837812224,838074367,JP +838074368,838139903,NP +838139904,838205439,SG +838205440,838238207,KR +838238208,838262783,VN +838262784,838270975,CN +838270976,838336511,KR +838336512,838467583,IN +838467584,838729727,JP +838729728,838795263,KR 838795264,838860799,AP 838860800,838926335,US 838991872,838999039,US 838999040,838999295,CA 838999296,839010559,US 839010560,839010815,CA -839010816,839022079,US -839022080,839023103,CA -839023104,839254015,US -839385088,839909375,US -840957952,843055103,US +839010816,839017983,US +839017984,839018239,CA +839018240,839023359,US +839023360,839023615,CA +839023616,843055103,US +843055104,844103679,CA +844103680,844627967,US +847249408,855638015,US 855638016,872415231,GB 872415232,889192447,US 889192448,905969663,DE @@ -2443,13 +3098,9 @@ 1040470272,1040470335,DE 1040470336,1040470399,EU 1040470400,1040470431,DE -1040470432,1040470783,EU -1040470784,1040471295,NL -1040471296,1040471487,EU -1040471488,1040471711,NL -1040471712,1040471743,EU -1040471744,1040471775,NL -1040471776,1040472991,EU +1040470432,1040471487,EU +1040471488,1040471551,NL +1040471552,1040472991,EU 1040472992,1040473087,NL 1040473088,1040473855,EU 1040473856,1040474111,NL @@ -2469,10 +3120,14 @@ 1040982016,1040982279,A2 1040982280,1040982287,NG 1040982288,1040982583,A2 -1040982584,1040982607,DK +1040982584,1040982591,DK +1040982592,1040982599,A2 +1040982600,1040982607,DK 1040982608,1040982631,A2 1040982632,1040982639,DE -1040982640,1040983807,A2 +1040982640,1040982943,A2 +1040982944,1040982951,DK +1040982952,1040983807,A2 1040983808,1040983815,NG 1040983816,1040984143,A2 1040984144,1040984151,NG @@ -2521,13 +3176,9 @@ 1041696872,1041696879,GB 1041696880,1041697699,FR 1041697700,1041697703,GB -1041697704,1041697919,FR -1041697920,1041697983,GB -1041697984,1041698047,FR +1041697704,1041698047,FR 1041698048,1041698077,GB -1041698078,1041698135,FR -1041698136,1041698143,GB -1041698144,1041698207,FR +1041698078,1041698207,FR 1041698208,1041698223,GB 1041698224,1041698247,FR 1041698248,1041698255,GB @@ -2565,23 +3216,19 @@ 1041701648,1041701663,GB 1041701664,1041702167,FR 1041702168,1041702175,GB -1041702176,1041702303,FR -1041702304,1041702311,GB +1041702176,1041702306,FR +1041702307,1041702311,GB 1041702312,1041702327,FR 1041702328,1041702335,GB 1041702336,1041702351,FR 1041702352,1041702399,GB -1041702400,1041702855,FR -1041702856,1041702863,GB -1041702864,1041703575,FR +1041702400,1041703575,FR 1041703576,1041703583,GB 1041703584,1041704119,FR 1041704120,1041704127,GB 1041704128,1041704159,FR 1041704160,1041704175,GB -1041704176,1041704319,FR -1041704320,1041704383,GB -1041704384,1041704407,FR +1041704176,1041704407,FR 1041704408,1041704431,GB 1041704432,1041704439,FR 1041704440,1041704455,GB @@ -2601,7 +3248,9 @@ 1041704848,1041704863,GB 1041704864,1041704879,FR 1041704880,1041704887,GB -1041704888,1041705231,FR +1041704888,1041704943,FR +1041704944,1041704959,GB +1041704960,1041705231,FR 1041705232,1041705239,GB 1041705240,1041705255,FR 1041705256,1041705279,GB @@ -2671,7 +3320,9 @@ 1041707632,1041707639,GB 1041707640,1041707679,FR 1041707680,1041707687,GB -1041707688,1041707895,FR +1041707688,1041707807,FR +1041707808,1041707815,GB +1041707816,1041707895,FR 1041707896,1041707903,GB 1041707904,1041707999,FR 1041708000,1041708007,GB @@ -2755,8 +3406,8 @@ 1041711584,1041711599,GB 1041711600,1041711943,FR 1041711944,1041711951,GB -1041711952,1041712399,FR -1041712400,1041712415,GB +1041711952,1041712407,FR +1041712408,1041712415,GB 1041712416,1041712423,FR 1041712424,1041712431,GB 1041712432,1041713095,FR @@ -2773,9 +3424,7 @@ 1041714072,1041714079,GB 1041714080,1041714095,FR 1041714096,1041714103,GB -1041714104,1041714111,FR -1041714112,1041714175,GB -1041714176,1041714523,FR +1041714104,1041714523,FR 1041714524,1041714527,GB 1041714528,1041714775,FR 1041714776,1041714783,GB @@ -2818,10 +3467,12 @@ 1041715952,1041715999,FR 1041716000,1041716015,GB 1041716016,1041716047,FR -1041716048,1041716063,GB -1041716064,1041716111,FR +1041716048,1041716095,GB +1041716096,1041716111,FR 1041716112,1041716223,GB -1041716224,1041716311,FR +1041716224,1041716231,FR +1041716232,1041716239,GB +1041716240,1041716311,FR 1041716312,1041716319,GB 1041716320,1041716439,FR 1041716440,1041716447,GB @@ -2843,7 +3494,9 @@ 1041717168,1041717183,GB 1041717184,1041717199,FR 1041717200,1041717247,GB -1041717248,1041717687,FR +1041717248,1041717503,FR +1041717504,1041717511,IT +1041717512,1041717687,FR 1041717688,1041717695,GB 1041717696,1041718112,FR 1041718113,1041718119,GB @@ -2887,7 +3540,9 @@ 1041719229,1041719231,GB 1041719232,1041719247,FR 1041719248,1041719263,GB -1041719264,1041719683,FR +1041719264,1041719383,FR +1041719384,1041719391,GB +1041719392,1041719683,FR 1041719684,1041719687,GB 1041719688,1041719703,FR 1041719704,1041719711,GB @@ -2935,7 +3590,9 @@ 1041722568,1041722623,GB 1041722624,1041722703,FR 1041722704,1041722711,GB -1041722712,1041722983,FR +1041722712,1041722743,FR +1041722744,1041722751,GB +1041722752,1041722983,FR 1041722984,1041723007,GB 1041723008,1041723047,FR 1041723048,1041723135,GB @@ -2960,16 +3617,15 @@ 1041725168,1041725175,FR 1041725176,1041725183,GB 1041725184,1041725191,FR -1041725192,1041725231,GB +1041725192,1041725199,IT +1041725200,1041725231,GB 1041725232,1041725255,FR 1041725256,1041725279,GB 1041725280,1041725375,FR 1041725376,1041725407,GB 1041725408,1041725749,FR 1041725750,1041725751,GB -1041725752,1041725815,FR -1041725816,1041725823,GB -1041725824,1041725863,FR +1041725752,1041725863,FR 1041725864,1041725871,GB 1041725872,1041726063,FR 1041726064,1041726079,GB @@ -3044,30 +3700,32 @@ 1041729568,1041729615,FR 1041729616,1041729623,GB 1041729624,1041729663,FR -1041729664,1041729791,GB -1041729792,1041730239,FR +1041729664,1041729935,GB +1041729936,1041729951,FR +1041729952,1041730047,GB +1041730048,1041730239,FR 1041730240,1041730247,GB 1041730248,1041730639,FR 1041730640,1041730655,GB -1041730656,1041731919,FR -1041731920,1041731935,GB +1041730656,1041731927,FR +1041731928,1041731935,GB 1041731936,1041731975,FR 1041731976,1041732031,GB 1041732032,1041732055,FR 1041732056,1041732063,GB -1041732064,1041732095,FR -1041732096,1041732111,GB +1041732064,1041732103,FR +1041732104,1041732111,GB 1041732112,1041732127,FR 1041732128,1041732191,GB 1041732192,1041732255,FR 1041732256,1041732295,GB 1041732296,1041732303,FR 1041732304,1041732311,GB -1041732312,1041732447,FR -1041732448,1041732455,GB -1041732456,1041732463,FR -1041732464,1041732479,GB -1041732480,1041732863,FR +1041732312,1041732471,FR +1041732472,1041732479,GB +1041732480,1041732519,FR +1041732520,1041732527,GB +1041732528,1041732863,FR 1041732864,1041732871,GB 1041732872,1041732879,FR 1041732880,1041732927,GB @@ -3075,8 +3733,8 @@ 1041732960,1041732967,GB 1041732968,1041732991,FR 1041732992,1041733103,GB -1041733104,1041733511,FR -1041733512,1041733535,GB +1041733104,1041733519,FR +1041733520,1041733535,GB 1041733536,1041733567,FR 1041733568,1041733631,GB 1041733632,1041734927,FR @@ -3100,9 +3758,7 @@ 1041735664,1041736375,FR 1041736376,1041736383,GB 1041736384,1041736423,FR -1041736424,1041736447,GB -1041736448,1041736455,FR -1041736456,1041736463,GB +1041736424,1041736463,GB 1041736464,1041736527,FR 1041736528,1041736535,GB 1041736536,1041736543,FR @@ -3131,8 +3787,8 @@ 1041737400,1041737423,GB 1041737424,1041737455,FR 1041737456,1041737463,GB -1041737464,1041737479,FR -1041737480,1041737503,GB +1041737464,1041737487,FR +1041737488,1041737503,GB 1041737504,1041737583,FR 1041737584,1041737599,GB 1041737600,1041737607,FR @@ -3172,8 +3828,8 @@ 1041738608,1041738703,FR 1041738704,1041738711,GB 1041738712,1041738735,FR -1041738736,1041738743,GB -1041738744,1041739079,FR +1041738736,1041738751,GB +1041738752,1041739079,FR 1041739080,1041739087,GB 1041739088,1041739167,FR 1041739168,1041739175,GB @@ -3226,7 +3882,7 @@ 1041741608,1041741615,GB 1041741616,1041741631,FR 1041741632,1041741647,GB -1041741648,1041741663,FR +1041741648,1041741663,DE 1041741664,1041741679,GB 1041741680,1041741687,FR 1041741688,1041741823,GB @@ -3432,7 +4088,9 @@ 1041757504,1041757519,GB 1041757520,1041757583,FR 1041757584,1041757591,GB -1041757592,1041757631,FR +1041757592,1041757607,FR +1041757608,1041757615,GB +1041757616,1041757631,FR 1041757632,1041757647,GB 1041757648,1041757663,FR 1041757664,1041757671,GB @@ -3487,9 +4145,12 @@ 1042288416,1042292735,CH 1042292736,1042293247,NL 1042293248,1042293503,GB -1042293504,1042293535,NL +1042293504,1042293535,IT 1042293536,1042293631,IR -1042293632,1042296063,GE +1042293632,1042293759,GE +1042293760,1042293985,IT +1042293986,1042294783,NL +1042294784,1042296063,GE 1042296064,1042296191,CY 1042296192,1042296575,GE 1042296576,1042296831,BY @@ -3631,8 +4292,10 @@ 1043356032,1043357695,DE 1043357696,1043365887,CH 1043365888,1043398655,PT -1043398656,1043464191,GB -1043464192,1043464799,NL +1043398656,1043464311,GB +1043464312,1043464351,NL +1043464352,1043464383,GB +1043464384,1043464799,NL 1043464800,1043464807,GB 1043464808,1043464823,NL 1043464824,1043464831,GB @@ -4229,7 +4892,8 @@ 1044454512,1044454559,NO 1044454560,1044454583,SE 1044454584,1044454655,NO -1044454656,1044455423,SE +1044454656,1044454911,SE +1044454912,1044455423,NO 1044455424,1044463615,EE 1044463616,1044479999,SE 1044480000,1044488191,CH @@ -4246,10 +4910,14 @@ 1044588288,1044588575,GB 1044588576,1044588607,DE 1044588608,1044588799,GB -1044588800,1044590463,DE -1044590464,1044590591,GB +1044588800,1044589567,DE +1044589568,1044590079,GB +1044590080,1044590335,DE +1044590336,1044590591,GB 1044590592,1044590671,DE -1044590672,1044590847,GB +1044590672,1044590719,GB +1044590720,1044590783,DE +1044590784,1044590847,GB 1044590848,1044591615,DE 1044591616,1044591871,GB 1044591872,1044592127,DE @@ -4311,7 +4979,9 @@ 1044697088,1044697343,DE 1044697344,1044697855,AT 1044697856,1044698110,DE -1044698111,1044701183,AT +1044698111,1044698111,AT +1044698112,1044698367,DE +1044698368,1044701183,AT 1044701184,1044709375,EG 1044709376,1044717567,RU 1044717568,1044742143,GB @@ -4329,9 +4999,7 @@ 1044774912,1044800383,NO 1044800384,1044800511,IT 1044800512,1044840447,NO -1044840448,1044842751,FI -1044842752,1044842815,AX -1044842816,1044905983,FI +1044840448,1044905983,FI 1044905984,1044908031,GB 1044908032,1044909055,US 1044909056,1044910847,GB @@ -4377,9 +5045,7 @@ 1044930928,1044930967,BE 1044930968,1044930975,FR 1044930976,1044930979,GB -1044930980,1044931231,BE -1044931232,1044931239,GB -1044931240,1044931375,BE +1044930980,1044931375,BE 1044931376,1044931391,GB 1044931392,1044931407,BE 1044931408,1044931439,GB @@ -4403,12 +5069,14 @@ 1044931904,1044931911,GB 1044931912,1044931915,BE 1044931916,1044931919,GB -1044931920,1044931935,BE +1044931920,1044931923,BE +1044931924,1044931927,GB +1044931928,1044931935,BE 1044931936,1044931951,GB 1044931952,1044931975,BE 1044931976,1044931983,GB -1044931984,1044932063,BE -1044932064,1044932087,GB +1044931984,1044932047,BE +1044932048,1044932087,GB 1044932088,1044932383,BE 1044932384,1044932391,GB 1044932392,1044932399,BE @@ -4435,8 +5103,8 @@ 1044932952,1044932959,GB 1044932960,1044933007,BE 1044933008,1044933015,GB -1044933016,1044933023,BE -1044933024,1044933039,GB +1044933016,1044933019,BE +1044933020,1044933039,GB 1044933040,1044933055,BE 1044933056,1044933071,GB 1044933072,1044933103,BE @@ -4472,12 +5140,14 @@ 1044933848,1044933863,BE 1044933864,1044933871,GB 1044933872,1044933919,BE -1044933920,1044933951,GB -1044933952,1044934191,BE +1044933920,1044933935,GB +1044933936,1044934191,BE 1044934192,1044934199,GB 1044934200,1044934239,BE 1044934240,1044934247,GB -1044934248,1044934359,BE +1044934248,1044934287,BE +1044934288,1044934295,GB +1044934296,1044934359,BE 1044934360,1044934503,GB 1044934504,1044934575,BE 1044934576,1044934583,GB @@ -4612,16 +5282,14 @@ 1045013472,1045018207,GB 1045018208,1045018231,FI 1045018232,1045018367,GB -1045018368,1045018423,ES -1045018424,1045018431,GB -1045018432,1045018559,ES +1045018368,1045018559,ES 1045018560,1045018623,GB 1045018624,1045018751,ES 1045018752,1045020159,GB 1045020160,1045020255,ES 1045020256,1045020287,GB -1045020288,1045020639,ES -1045020640,1045020671,GB +1045020288,1045020655,ES +1045020656,1045020671,GB 1045020672,1045037055,NO 1045037056,1045119231,GR 1045119232,1045119743,AL @@ -4765,8 +5433,7 @@ 1045743680,1045743743,GB 1045743744,1045743803,SE 1045743804,1045743807,GB -1045743808,1045743999,SE -1045744000,1045744007,LU +1045743808,1045744007,SE 1045744008,1045744015,GB 1045744016,1045744031,SE 1045744032,1045744063,GB @@ -4853,8 +5520,13 @@ 1046229120,1046282239,NO 1046282240,1046283007,DE 1046283008,1046283263,BZ -1046283264,1046284287,DE -1046284288,1046285311,BZ +1046283264,1046283327,LU +1046283328,1046284287,DE +1046284288,1046285055,BZ +1046285056,1046285119,HR +1046285120,1046285183,MT +1046285184,1046285247,BZ +1046285248,1046285311,BA 1046285312,1046286663,DE 1046286664,1046286671,BZ 1046286672,1046286927,DE @@ -4892,8 +5564,7 @@ 1046316032,1046316543,FR 1046316544,1046317055,DK 1046317056,1046317567,ES -1046317568,1046317823,GB -1046317824,1046318335,NL +1046317568,1046318335,NL 1046318336,1046318591,GB 1046318592,1046320127,NL 1046320128,1046320639,GB @@ -4924,10 +5595,8 @@ 1046338048,1046339839,EU 1046339840,1046340095,FR 1046340096,1046340607,EU -1046340608,1046341119,NL -1046341120,1046341631,EU -1046341632,1046341887,FR -1046341888,1046342143,EU +1046340608,1046340863,NL +1046340864,1046342143,EU 1046342144,1046342719,NL 1046342720,1046343423,EU 1046343424,1046343935,NL @@ -5189,8 +5858,8 @@ 1046528600,1046528603,DE 1046528604,1046528607,GB 1046528608,1046528639,DE -1046528640,1046528671,GB -1046528672,1046528767,DE +1046528640,1046528703,GB +1046528704,1046528767,DE 1046528768,1046530047,GB 1046530048,1046530687,DE 1046530688,1046530815,GB @@ -5216,8 +5885,8 @@ 1046535312,1046535359,GB 1046535360,1046535423,DE 1046535424,1046535487,GB -1046535488,1046535615,DE -1046535616,1046535619,GB +1046535488,1046535551,DE +1046535552,1046535619,GB 1046535620,1046535623,DE 1046535624,1046535631,GB 1046535632,1046535935,DE @@ -5276,13 +5945,17 @@ 1046543104,1046543263,GB 1046543264,1046543295,DE 1046543296,1046543327,GB -1046543328,1046543351,DE -1046543352,1046543359,GB +1046543328,1046543343,DE +1046543344,1046543359,GB 1046543360,1046543615,DE 1046543616,1046544127,GB 1046544128,1046544383,DE 1046544384,1046560767,IT -1046560768,1046585343,ES +1046560768,1046569831,ES +1046569832,1046569839,GB +1046569840,1046570591,ES +1046570592,1046570607,CH +1046570608,1046585343,ES 1046585344,1046609919,NO 1046609920,1046675455,IT 1046675456,1046708223,ES @@ -5381,8 +6054,8 @@ 1046896384,1046897663,GB 1046897664,1046898431,BE 1046898432,1046898687,EU -1046898688,1046898943,BE -1046898944,1046899167,EU +1046898688,1046898975,BE +1046898976,1046899167,EU 1046899168,1046904831,BE 1046904832,1046937599,RU 1046937600,1047003135,GR @@ -5424,7 +6097,9 @@ 1047340800,1047341055,NO 1047341056,1047343871,SE 1047343872,1047344127,NO -1047344128,1047347199,SE +1047344128,1047346431,SE +1047346432,1047346687,FI +1047346688,1047347199,SE 1047347200,1047363583,DE 1047363584,1047371775,CZ 1047371776,1047379967,RU @@ -5449,8 +6124,8 @@ 1047563304,1047563311,CH 1047563312,1047563319,DE 1047563320,1047563323,CH -1047563324,1047563347,DE -1047563348,1047563355,CH +1047563324,1047563351,DE +1047563352,1047563355,CH 1047563356,1047563363,DE 1047563364,1047563367,ES 1047563368,1047563403,DE @@ -5466,7 +6141,9 @@ 1047563452,1047563455,NL 1047563456,1047563467,DE 1047563468,1047563471,CH -1047563472,1047566363,DE +1047563472,1047565131,DE +1047565132,1047565135,GB +1047565136,1047566363,DE 1047566364,1047566367,CH 1047566368,1047566403,DE 1047566404,1047566415,CH @@ -5480,9 +6157,13 @@ 1047566492,1047566499,CH 1047566500,1047566507,DE 1047566508,1047566511,CH -1047566512,1047566535,DE +1047566512,1047566519,DE +1047566520,1047566527,CH +1047566528,1047566535,DE 1047566536,1047566539,CH -1047566540,1047566559,DE +1047566540,1047566543,DE +1047566544,1047566547,CH +1047566548,1047566559,DE 1047566560,1047566563,CH 1047566564,1047566847,DE 1047566848,1047566851,AT @@ -5491,7 +6172,9 @@ 1047566872,1047566879,CH 1047566880,1047566891,DE 1047566892,1047566903,CH -1047566904,1047566963,DE +1047566904,1047566947,DE +1047566948,1047566951,AT +1047566952,1047566963,DE 1047566964,1047566967,AT 1047566968,1047566995,DE 1047566996,1047566999,CH @@ -5550,7 +6233,9 @@ 1047567756,1047567759,CH 1047567760,1047567799,DE 1047567800,1047567803,CH -1047567804,1047567847,DE +1047567804,1047567823,DE +1047567824,1047567839,CH +1047567840,1047567847,DE 1047567848,1047567851,CH 1047567852,1047567855,BE 1047567856,1047567871,DE @@ -5578,7 +6263,9 @@ 1047568368,1047568383,DE 1047568384,1047576575,NL 1047576576,1047584767,HU -1047584768,1047592959,NL +1047584768,1047592735,NL +1047592736,1047592743,FR +1047592744,1047592959,NL 1047592960,1047601151,BA 1047601152,1047625727,RU 1047625728,1047633919,NO @@ -5589,7 +6276,8 @@ 1047728128,1047732223,SE 1047732224,1047740415,EU 1047740416,1047740431,US -1047740432,1047740543,EU +1047740432,1047740447,DE +1047740448,1047740543,EU 1047740544,1047740671,DE 1047740672,1047740927,A2 1047740928,1047781663,EU @@ -5600,7 +6288,14 @@ 1047782720,1047782751,SE 1047782752,1047782783,NO 1047782784,1047782815,FI -1047782816,1047789567,EU +1047782816,1047789375,EU +1047789376,1047789383,GB +1047789384,1047789407,EU +1047789408,1047789423,DE +1047789424,1047789439,EU +1047789440,1047789471,SE +1047789472,1047789535,EU +1047789536,1047789567,DE 1047789568,1047806031,AT 1047806032,1047806047,IT 1047806048,1047822335,AT @@ -5668,8 +6363,8 @@ 1048604966,1048604967,UA 1048604968,1048604971,LT 1048604972,1048604975,UA -1048604976,1048605071,LT -1048605072,1048607231,UA +1048604976,1048605079,LT +1048605080,1048607231,UA 1048607232,1048607247,EE 1048607248,1048607487,UA 1048607488,1048607519,EE @@ -6425,7 +7120,9 @@ 1049020480,1049020543,GE 1049020544,1049026559,DE 1049026560,1049026815,EU -1049026816,1049032143,DE +1049026816,1049031871,DE +1049031872,1049031903,EU +1049031904,1049032143,DE 1049032144,1049032167,EU 1049032168,1049032171,DE 1049032172,1049032175,EU @@ -6433,7 +7130,9 @@ 1049032288,1049032295,EU 1049032296,1049032383,DE 1049032384,1049032399,EU -1049032400,1049032639,DE +1049032400,1049032623,DE +1049032624,1049032631,EU +1049032632,1049032639,DE 1049032640,1049032647,EU 1049032648,1049032699,DE 1049032700,1049032703,EU @@ -6605,9 +7304,7 @@ 1049778336,1049778351,AE 1049778352,1049778535,DE 1049778536,1049778543,AT -1049778544,1049779063,DE -1049779064,1049779071,PL -1049779072,1049779135,DE +1049778544,1049779135,DE 1049779136,1049779167,AE 1049779168,1049782303,DE 1049782304,1049782335,AE @@ -6627,7 +7324,9 @@ 1049787136,1049787391,PL 1049787392,1049790207,DE 1049790208,1049790463,LU -1049790464,1049817151,DE +1049790464,1049794559,DE +1049794560,1049795583,CH +1049795584,1049817151,DE 1049817152,1049817159,PL 1049817160,1049817287,DE 1049817288,1049817295,AE @@ -6860,13 +7559,11 @@ 1051578352,1051578363,GB 1051578364,1051578367,DE 1051578368,1051580415,SZ -1051580416,1051584511,GB -1051584512,1051585663,MG -1051585664,1051585919,GB -1051585920,1051586047,MG -1051586048,1051586175,GB -1051586176,1051586303,MG -1051586304,1051590655,GB +1051580416,1051584767,GB +1051584768,1051585535,MG +1051585536,1051585599,GB +1051585600,1051585663,MG +1051585664,1051590655,GB 1051590656,1051702527,ES 1051702528,1051702783,US 1051702784,1051721727,ES @@ -6967,7 +7664,9 @@ 1052003840,1052003967,EU 1052003968,1052003999,DE 1052004000,1052004671,EU -1052004672,1052004759,DE +1052004672,1052004687,DE +1052004688,1052004703,EU +1052004704,1052004759,DE 1052004760,1052004767,EU 1052004768,1052004783,DE 1052004784,1052004815,EU @@ -7080,9 +7779,7 @@ 1052016896,1052017151,DE 1052017152,1052017231,EU 1052017232,1052017247,DE -1052017248,1052017279,EU -1052017280,1052017343,DE -1052017344,1052017471,EU +1052017248,1052017471,EU 1052017472,1052017503,DE 1052017504,1052017535,EU 1052017536,1052017567,DE @@ -8256,13 +8953,9 @@ 1053340416,1053340479,EU 1053340480,1053340511,NL 1053340512,1053340671,EU -1053340672,1053341183,GB -1053341184,1053341439,EU -1053341440,1053341567,GB +1053340672,1053341567,GB 1053341568,1053341575,EU -1053341576,1053341599,GB -1053341600,1053341615,EU -1053341616,1053341695,GB +1053341576,1053341695,GB 1053341696,1053343743,EU 1053343744,1053344255,FI 1053344256,1053344511,EU @@ -8282,8 +8975,8 @@ 1053350336,1053350351,EU 1053350352,1053350359,IE 1053350360,1053350367,EU -1053350368,1053350383,IE -1053350384,1053350399,EU +1053350368,1053350391,IE +1053350392,1053350399,EU 1053350400,1053350479,BE 1053350480,1053350655,EU 1053350656,1053350911,BE @@ -8370,7 +9063,8 @@ 1053835264,1053835775,DE 1053835776,1053837311,EU 1053837312,1053837439,FK -1053837440,1053837567,EU +1053837440,1053837455,GB +1053837456,1053837567,EU 1053837568,1053837823,GB 1053837824,1053838335,FK 1053838336,1053838591,DE @@ -8627,8 +9321,8 @@ 1055200424,1055201023,EU 1055201024,1055201279,US 1055201280,1055203327,EU -1055203328,1055203359,CZ -1055203360,1055203839,EU +1055203328,1055203343,CZ +1055203344,1055203839,EU 1055203840,1055204095,CZ 1055204096,1055204863,EU 1055204864,1055205119,CZ @@ -8685,8 +9379,8 @@ 1055218448,1055218463,EU 1055218464,1055218471,PT 1055218472,1055218479,EU -1055218480,1055219711,PT -1055219712,1055220223,EU +1055218480,1055218687,PT +1055218688,1055220223,EU 1055220224,1055220287,NL 1055220288,1055220351,EU 1055220352,1055220399,NL @@ -8795,8 +9489,8 @@ 1056244256,1056244287,FR 1056244288,1056244335,MC 1056244336,1056244351,FR -1056244352,1056244447,CH -1056244448,1056244479,MC +1056244352,1056244415,CH +1056244416,1056244479,MC 1056244480,1056251903,CH 1056251904,1056260095,RU 1056260096,1056276479,CZ @@ -8813,7 +9507,6 @@ 1056505856,1056514047,PT 1056514048,1056522239,IT 1056522240,1056538623,AT -1056538624,1056546815,DE 1056546816,1056555007,NO 1056555008,1056571391,GB 1056571392,1056669695,NL @@ -8850,9 +9543,7 @@ 1056964608,1061227007,US 1061227008,1061227263,HT 1061227264,1061227774,BO -1061227775,1061478143,US -1061478144,1061478399,BO -1061478400,1061518015,US +1061227775,1061518015,US 1061518016,1061518047,A2 1061518048,1061558271,US 1061558272,1061559295,PK @@ -8860,13 +9551,7 @@ 1061588736,1061588991,GU 1061588992,1061633567,US 1061633568,1061633575,CA -1061633576,1061749152,US -1061749153,1061749182,PR -1061749183,1061749183,US -1061749184,1061749191,PR -1061749192,1061749199,US -1061749200,1061749231,PR -1061749232,1061762047,US +1061633576,1061762047,US 1061762048,1061762303,FR 1061762304,1061776479,US 1061776480,1061776639,CA @@ -9034,11 +9719,9 @@ 1065583424,1065583439,HK 1065583440,1065611263,US 1065611264,1065615359,PR -1065615360,1065806947,US -1065806948,1065806957,TH -1065806958,1065811967,US +1065615360,1065811967,US 1065811968,1065820159,CA -1065820160,1065873407,US +1065824256,1065873407,US 1065873408,1065877503,PR 1065877504,1065906175,US 1065906176,1065908223,KY @@ -9261,11 +9944,7 @@ 1071477248,1071480831,CA 1071480832,1071985631,US 1071985632,1071985663,ML -1071985664,1072440639,US -1072440640,1072440671,CA -1072440672,1072445631,US -1072445632,1072445663,AU -1072445664,1072512951,US +1071985664,1072512951,US 1072512952,1072512959,CA 1072512960,1072619023,US 1072619024,1072619039,CA @@ -9310,7 +9989,7 @@ 1072785472,1072790015,US 1072790016,1072790031,JP 1072790032,1072922623,US -1072922624,1072922879,PH +1072922624,1072922879,CA 1072922880,1072923135,US 1072923136,1072923391,CA 1072923392,1072923903,US @@ -9333,33 +10012,33 @@ 1072928128,1072928255,US 1072928256,1072928263,CA 1072928264,1072928287,US -1072928288,1072928319,CA -1072928320,1072928447,US +1072928288,1072928383,CA +1072928384,1072928447,US 1072928448,1072929535,CA 1072929536,1072929791,US 1072929792,1072930047,CA 1072930048,1072930303,US 1072930304,1072931071,CA -1072931072,1072931327,US -1072931328,1072931583,CA +1072931072,1072931199,US +1072931200,1072931583,CA 1072931584,1072931839,SY 1072931840,1072932607,CA 1072932608,1072932863,NG 1072932864,1072934399,CA -1072934400,1072934783,US +1072934400,1072934655,US +1072934656,1072934783,CA 1072934784,1072934847,AU 1072934848,1072934879,CA 1072934880,1072934911,TW 1072934912,1072934943,CA 1072934944,1072934975,PH -1072934976,1072935135,US +1072934976,1072935039,CA +1072935040,1072935135,US 1072935136,1072935159,CA 1072935160,1072935167,US 1072935168,1072935679,CA 1072935680,1072935807,PH -1072935808,1072935871,CA -1072935872,1072935935,US -1072935936,1072936447,CA +1072935808,1072936447,CA 1072936448,1072936703,PH 1072936704,1072937215,US 1072937216,1072937471,IR @@ -9367,7 +10046,9 @@ 1072937728,1072938239,CA 1072938240,1072938495,VG 1072938496,1072938751,CA -1072938752,1072940031,US +1072938752,1072939007,US +1072939008,1072939519,CA +1072939520,1072940031,US 1072940032,1072955391,CA 1072955392,1073022975,US 1073022976,1073025791,HN @@ -9398,9 +10079,7 @@ 1073045504,1073047551,CO 1073047552,1073049599,PR 1073049600,1073053695,BS -1073053696,1073090269,US -1073090270,1073090300,PE -1073090301,1073091397,US +1073053696,1073091397,US 1073091398,1073091407,CH 1073091408,1073092335,US 1073092336,1073092351,CA @@ -9469,8 +10148,8 @@ 1073394192,1073394207,MX 1073394208,1073394239,CA 1073394240,1073394247,MX -1073394248,1073394255,US -1073394256,1073394271,MX +1073394248,1073394263,US +1073394264,1073394271,MX 1073394272,1073394279,US 1073394280,1073394287,MX 1073394288,1073394295,US @@ -9685,7 +10364,9 @@ 1075558912,1075576831,US 1075576832,1075576871,NO 1075576872,1075576879,GB -1075576880,1075576967,NO +1075576880,1075576951,NO +1075576952,1075576959,GB +1075576960,1075576967,NO 1075576968,1075576975,GB 1075576976,1075576991,NO 1075576992,1075577023,GB @@ -9804,7 +10485,9 @@ 1075972096,1075972351,GB 1075972352,1075973887,US 1075973888,1075974143,CA -1075974144,1075976191,US +1075974144,1075975167,US +1075975168,1075975423,CA +1075975424,1075976191,US 1075976192,1075976511,CA 1075976512,1075976543,US 1075976544,1075976647,CA @@ -9863,8 +10546,8 @@ 1075988480,1075988735,US 1075988736,1075988991,CA 1075988992,1075989119,US -1075989120,1075989183,CA -1075989184,1075989247,US +1075989120,1075989231,CA +1075989232,1075989247,US 1075989248,1075989311,FI 1075989312,1075989359,CA 1075989360,1075989375,US @@ -10108,22 +10791,23 @@ 1076049920,1076050175,IL 1076050176,1076166655,US 1076183040,1076183071,IN -1076183072,1076183103,US -1076183104,1076183135,CA -1076183136,1076183263,US -1076183264,1076183295,CA +1076183072,1076183231,US +1076183232,1076183295,CA 1076183296,1076183807,US 1076183808,1076184063,CA -1076184064,1076184127,US +1076184064,1076184095,VE +1076184096,1076184127,US 1076184128,1076184159,VE -1076184160,1076184191,US +1076184160,1076184191,PK 1076184192,1076184223,IN 1076184224,1076184255,US 1076184256,1076184287,BE 1076184288,1076184319,CA 1076184320,1076184575,US -1076184576,1076184703,SG -1076184704,1076184895,US +1076184576,1076184639,CA +1076184640,1076184703,SG +1076184704,1076184831,CA +1076184832,1076184895,US 1076184896,1076184927,FR 1076184928,1076184959,US 1076184960,1076184991,VE @@ -10137,7 +10821,9 @@ 1076185504,1076185535,DO 1076185536,1076185599,US 1076185600,1076185855,MY -1076185856,1076185983,US +1076185856,1076185919,US +1076185920,1076185951,CA +1076185952,1076185983,US 1076185984,1076186015,PK 1076186016,1076186047,US 1076186048,1076186079,IN @@ -10147,17 +10833,20 @@ 1076186368,1076186623,CA 1076186624,1076186751,US 1076186752,1076186783,CA -1076186784,1076187391,US +1076186784,1076186815,TW +1076186816,1076187391,US 1076187392,1076187647,CA 1076187648,1076187679,BE -1076187680,1076187775,US +1076187680,1076187743,US +1076187744,1076187775,CA 1076187776,1076187807,AU 1076187808,1076187903,US 1076187904,1076188159,CA 1076188160,1076188287,US 1076188288,1076188415,BE -1076188416,1076188671,MY -1076188672,1076189183,US +1076188416,1076188799,US +1076188800,1076188927,CA +1076188928,1076189183,US 1076189184,1076189215,VE 1076189216,1076189279,CA 1076189280,1076189311,US @@ -10171,24 +10860,35 @@ 1076190144,1076190175,BE 1076190176,1076190207,IN 1076190208,1076190463,CA -1076190464,1076190815,US +1076190464,1076190655,US +1076190656,1076190719,CA +1076190720,1076190783,US +1076190784,1076190815,CA 1076190816,1076190847,IN -1076190848,1076192255,US +1076190848,1076190913,US +1076190914,1076190945,IN +1076190946,1076191231,US +1076191232,1076191487,CA +1076191488,1076192063,US +1076192064,1076192191,CA +1076192192,1076192255,US 1076192256,1076192383,BE -1076192384,1076192767,US +1076192384,1076192639,US +1076192640,1076192767,CA 1076192768,1076192831,IN -1076192832,1076193023,US -1076193024,1076193055,GB +1076192832,1076192895,KR +1076192896,1076193055,US 1076193056,1076193087,AU 1076193088,1076193151,US 1076193152,1076193183,TR 1076193184,1076193247,US 1076193248,1076193279,CA -1076193280,1076194367,US +1076193280,1076193535,PK +1076193536,1076194367,US 1076194368,1076194399,IN 1076194400,1076194431,IL -1076194432,1076194495,US -1076194496,1076194527,BE +1076194432,1076194463,IN +1076194464,1076194527,BE 1076194528,1076194559,US 1076194560,1076194815,CA 1076194816,1076195071,US @@ -10198,28 +10898,33 @@ 1076195584,1076195871,US 1076195872,1076195903,BE 1076195904,1076195935,CA -1076195936,1076196095,US -1076196096,1076196383,CA -1076196384,1076196479,US +1076195936,1076195999,US +1076196000,1076196031,CN +1076196032,1076196063,CA +1076196064,1076196095,US +1076196096,1076196415,CA +1076196416,1076196479,US 1076196480,1076196511,FR -1076196512,1076196543,AT -1076196544,1076196641,US +1076196512,1076196575,AT +1076196576,1076196607,CA +1076196608,1076196641,US 1076196642,1076196671,BE 1076196672,1076196703,US 1076196704,1076196735,FR -1076196736,1076197119,US +1076196736,1076196863,US +1076196864,1076196991,IN +1076196992,1076197119,US 1076197120,1076197375,CA 1076197376,1076197631,US 1076197632,1076197663,BE -1076197664,1076198655,US +1076197664,1076198399,US +1076198400,1076198655,CA 1076198656,1076198911,AE 1076198912,1076218015,US 1076218016,1076218023,GB 1076218024,1076219407,US 1076219408,1076219415,GB -1076219416,1076281631,US -1076281632,1076281663,AT -1076281664,1076281695,US +1076219416,1076281695,US 1076281696,1076281727,TH 1076281728,1076282111,US 1076282112,1076282143,AU @@ -11223,9 +11928,11 @@ 1077940206,1077940209,IT 1077940210,1077940213,US 1077940214,1077940217,MX -1077940218,1077963775,US -1077963776,1077964031,CA -1077964032,1077977087,US +1077940218,1077960839,US +1077960840,1077960847,CA +1077960848,1077960943,US +1077960944,1077960951,CO +1077960952,1077977087,US 1077977088,1077985279,CA 1077985280,1077993471,US 1077993472,1078001663,CA @@ -11248,13 +11955,11 @@ 1078280192,1078280575,CA 1078280576,1078280591,US 1078280592,1078280639,CA -1078280640,1078280655,CR +1078280640,1078280655,US 1078280656,1078280671,CA 1078280672,1078280695,US -1078280696,1078280943,CA -1078280944,1078281071,US -1078281072,1078281079,CA -1078281080,1078281087,US +1078280696,1078280895,CA +1078280896,1078281087,US 1078281088,1078281279,CA 1078281280,1078281295,US 1078281296,1078281663,CA @@ -11279,16 +11984,13 @@ 1078283264,1078283264,US 1078283265,1078283375,CA 1078283376,1078283391,MX -1078283392,1078283407,CA -1078283408,1078283423,US +1078283392,1078283423,US 1078283424,1078283487,CA -1078283488,1078283495,US -1078283496,1078283551,CA +1078283488,1078283503,US +1078283504,1078283551,CA 1078283552,1078283583,US 1078283584,1078283647,CA -1078283648,1078283663,US -1078283664,1078283671,CA -1078283672,1078283679,US +1078283648,1078283679,US 1078283680,1078283687,CA 1078283688,1078283695,US 1078283696,1078283751,CA @@ -11296,21 +11998,19 @@ 1078283776,1078284031,CA 1078284032,1078284159,BS 1078284160,1078284255,CA -1078284256,1078284287,US -1078284288,1078284319,CA -1078284320,1078284351,US +1078284256,1078284351,US 1078284352,1078284367,CA 1078284368,1078284383,BV 1078284384,1078284399,US 1078284400,1078284687,CA 1078284688,1078284695,US 1078284696,1078284703,MX -1078284704,1078284991,CA +1078284704,1078284719,CA +1078284720,1078284735,US +1078284736,1078284991,CA 1078284992,1078285007,US 1078285008,1078285015,CA -1078285016,1078285023,US -1078285024,1078285031,CA -1078285032,1078285039,US +1078285016,1078285039,US 1078285040,1078285191,CA 1078285192,1078285215,US 1078285216,1078285231,CA @@ -11324,12 +12024,16 @@ 1078285304,1078285567,US 1078285568,1078285639,CA 1078285640,1078285647,US -1078285648,1078285695,CA +1078285648,1078285655,CA +1078285656,1078285663,US +1078285664,1078285695,CA 1078285696,1078285703,MX 1078285704,1078285711,US 1078285712,1078285919,CA 1078285920,1078285943,US -1078285944,1078286047,CA +1078285944,1078285951,CA +1078285952,1078286015,US +1078286016,1078286047,CA 1078286048,1078286079,US 1078286080,1078286111,CA 1078286112,1078286115,US @@ -11361,13 +12065,15 @@ 1078287184,1078287199,US 1078287200,1078287231,CA 1078287232,1078287247,US -1078287248,1078287295,CA -1078287296,1078287311,US +1078287248,1078287279,CA +1078287280,1078287311,US 1078287312,1078287327,CA 1078287328,1078287343,US 1078287344,1078287759,CA 1078287760,1078287767,US -1078287768,1078287839,CA +1078287768,1078287775,CA +1078287776,1078287807,US +1078287808,1078287839,CA 1078287840,1078287863,US 1078287864,1078288383,CA 1078288384,1078309695,US @@ -11690,21 +12396,20 @@ 1079354704,1079354711,CA 1079354712,1079355359,US 1079355360,1079355367,CA -1079355368,1079355903,US -1079355904,1079355939,CA -1079355940,1079355951,AU -1079355952,1079356415,CA -1079356416,1079356663,US +1079355368,1079355967,US +1079355968,1079355991,CA +1079355992,1079356663,US 1079356664,1079356671,CA 1079356672,1079377919,US 1079377920,1079378943,CA 1079378944,1079379711,US 1079379712,1079380927,CA -1079380928,1079381183,US -1079381184,1079381503,CA -1079381504,1079381599,US +1079380928,1079380991,US +1079380992,1079381567,CA +1079381568,1079381599,US 1079381600,1079381631,WS -1079381632,1079382015,US +1079381632,1079381759,CA +1079381760,1079382015,US 1079382016,1079382527,CA 1079382528,1079383039,US 1079383040,1079383295,VG @@ -11713,25 +12418,28 @@ 1079384064,1079384319,LR 1079384320,1079384575,CA 1079384576,1079385087,ZW -1079385088,1079385471,CA +1079385088,1079385343,US +1079385344,1079385471,CA 1079385472,1079385599,US 1079385600,1079385855,CA 1079385856,1079386111,SZ -1079386112,1079386623,US +1079386112,1079386623,CA 1079386624,1079386879,SG 1079386880,1079387135,EG 1079387136,1079387903,US 1079387904,1079388159,PH 1079388160,1079389439,CA -1079389440,1079389951,US +1079389440,1079389567,US +1079389568,1079389695,CA +1079389696,1079389951,US 1079389952,1079390719,CA 1079390720,1079391487,US 1079391488,1079391615,CA 1079391616,1079391679,US 1079391680,1079391743,CA 1079391744,1079392255,HT -1079392256,1079393279,CA -1079393280,1079394047,US +1079392256,1079393791,CA +1079393792,1079394047,US 1079394048,1079394063,CA 1079394064,1079394071,SG 1079394072,1079394079,CA @@ -11747,31 +12455,27 @@ 1079396096,1079396351,CA 1079396352,1079397375,MP 1079397376,1079397631,MH -1079397632,1079398399,US -1079398400,1079399583,CA +1079397632,1079399583,CA 1079399584,1079399599,US -1079399600,1079399935,CA -1079399936,1079400447,US +1079399600,1079400447,CA 1079400448,1079400511,FR 1079400512,1079400575,CA 1079400576,1079400639,US -1079400640,1079400703,CA -1079400704,1079400831,US +1079400640,1079400767,CA +1079400768,1079400831,US 1079400832,1079401215,CA 1079401216,1079401471,US -1079401472,1079401983,CA -1079401984,1079402495,US -1079402496,1079403007,CA -1079403008,1079403519,US -1079403520,1079403775,CA +1079401472,1079403775,CA 1079403776,1079403807,US -1079403808,1079403839,CA -1079403840,1079403935,US +1079403808,1079403903,CA +1079403904,1079403935,US 1079403936,1079403999,CA -1079404000,1079404799,US +1079404000,1079404031,US +1079404032,1079404543,CA +1079404544,1079404799,US 1079404800,1079405023,CA -1079405024,1079405247,US -1079405248,1079405407,CA +1079405024,1079405119,US +1079405120,1079405407,CA 1079405408,1079405439,BD 1079405440,1079405567,US 1079405568,1079407103,CA @@ -11790,35 +12494,24 @@ 1079410944,1079411199,CA 1079411200,1079411455,US 1079411456,1079411711,PK -1079411712,1079412735,CA -1079412736,1079413247,US -1079413248,1079413311,CA +1079411712,1079413311,CA 1079413312,1079413343,US -1079413344,1079414271,CA -1079414272,1079415039,US +1079413344,1079414783,CA +1079414784,1079415039,US 1079415040,1079415295,HN -1079415296,1079415551,CA -1079415552,1079416319,US -1079416320,1079419135,CA -1079419136,1079419903,US -1079419904,1079420159,CA -1079420160,1079420671,US -1079420672,1079421951,CA +1079415296,1079415807,CA +1079415808,1079416319,US +1079416320,1079421951,CA 1079421952,1079422207,US -1079422208,1079422463,CA -1079422464,1079423487,MZ -1079423488,1079423999,CA -1079424000,1079424767,MZ -1079424768,1079425279,US +1079422208,1079425023,CA +1079425024,1079425279,US 1079425280,1079425535,CA 1079425536,1079425551,US 1079425552,1079427071,CA 1079427072,1079427327,US 1079427328,1079427583,CA 1079427584,1079428095,PW -1079428096,1079429375,CA -1079429376,1079429887,US -1079429888,1079431679,CA +1079428096,1079431679,CA 1079431680,1079432191,ZM 1079432192,1079432703,CA 1079432704,1079432959,US @@ -11845,7 +12538,8 @@ 1079576496,1079578623,PR 1079578624,1079585391,US 1079585392,1079585407,IN -1079585408,1079664639,US +1079585408,1079648255,US +1079656448,1079664639,US 1079664640,1079668735,CA 1079668736,1079827871,US 1079827872,1079827887,RU @@ -11863,7 +12557,9 @@ 1079946432,1079946463,CA 1079946464,1079953567,US 1079953568,1079953599,GB -1079953600,1079994367,US +1079953600,1079962879,US +1079962880,1079963135,GB +1079963136,1079994367,US 1079994368,1079996415,CA 1079996416,1080021999,US 1080022000,1080022007,GT @@ -11996,7 +12692,6 @@ 1080750612,1080820871,US 1080820872,1080820879,PR 1080820880,1080954879,US -1080955904,1080957183,US 1080957952,1080958207,A2 1080958208,1080958463,BH 1080958464,1080958719,A2 @@ -12038,9 +12733,7 @@ 1081369120,1081369151,CO 1081369152,1081369599,US 1081369600,1081370111,CO -1081370112,1081377055,US -1081377056,1081377071,VE -1081377072,1081377079,US +1081370112,1081377079,US 1081377080,1081377087,VE 1081377088,1081377119,US 1081377120,1081377135,VE @@ -12055,20 +12748,16 @@ 1081377824,1081377887,US 1081377888,1081377919,VE 1081377920,1081377935,US -1081377936,1081377999,VE -1081378000,1081378015,US +1081377936,1081377983,VE +1081377984,1081378015,US 1081378016,1081378047,VE -1081378048,1081378303,US -1081378304,1081378319,VE -1081378320,1081378375,US +1081378048,1081378375,US 1081378376,1081378399,VE 1081378400,1081378495,US 1081378496,1081378575,VE 1081378576,1081378607,US 1081378608,1081378655,VE -1081378656,1081378751,US -1081378752,1081378815,VE -1081378816,1081379327,US +1081378656,1081379327,US 1081379328,1081379839,VE 1081379840,1081385215,US 1081385216,1081385535,PA @@ -12077,9 +12766,7 @@ 1081385992,1081385999,US 1081386000,1081386015,PA 1081386016,1081386047,VE -1081386048,1081386623,US -1081386624,1081386687,PA -1081386688,1081387519,US +1081386048,1081387519,US 1081387520,1081388031,PA 1081388032,1081388127,US 1081388128,1081388143,PA @@ -12090,9 +12777,7 @@ 1081393408,1081393751,CL 1081393752,1081393759,US 1081393760,1081393783,CL -1081393784,1081393799,US -1081393800,1081393807,CL -1081393808,1081393831,US +1081393784,1081393831,US 1081393832,1081393839,CL 1081393840,1081393887,US 1081393888,1081393903,CL @@ -12102,13 +12787,23 @@ 1081397760,1081398783,CL 1081398784,1081399295,US 1081399296,1081401343,CL -1081401344,1081401391,AR +1081401344,1081401375,AR +1081401376,1081401383,US +1081401384,1081401391,AR 1081401392,1081401415,US -1081401416,1081401535,AR -1081401536,1081401567,US -1081401568,1081401735,AR -1081401736,1081401743,US -1081401744,1081402367,AR +1081401416,1081401471,AR +1081401472,1081401567,US +1081401568,1081401599,AR +1081401600,1081401615,US +1081401616,1081401735,AR +1081401736,1081401751,US +1081401752,1081401775,AR +1081401776,1081401791,US +1081401792,1081401807,AR +1081401808,1081401815,US +1081401816,1081401823,AR +1081401824,1081401855,US +1081401856,1081402367,AR 1081402368,1081402895,US 1081402896,1081403007,AR 1081403008,1081403055,US @@ -12127,8 +12822,8 @@ 1081403904,1081403967,AR 1081403968,1081404031,US 1081404032,1081404095,AR -1081404096,1081404991,US -1081404992,1081405119,AR +1081404096,1081405055,US +1081405056,1081405119,AR 1081405120,1081409791,US 1081409792,1081410047,PR 1081410048,1081410559,US @@ -12145,43 +12840,31 @@ 1081413584,1081413631,PR 1081413632,1081416191,US 1081416192,1081416447,PR -1081416448,1081419199,US -1081419200,1081419231,PR -1081419232,1081419263,US -1081419264,1081419391,PR +1081416448,1081419327,US +1081419328,1081419391,PR 1081419392,1081419423,US 1081419424,1081419431,PR 1081419432,1081419447,US 1081419448,1081419455,PR -1081419456,1081419487,US -1081419488,1081419519,PR -1081419520,1081419775,US +1081419456,1081419775,US 1081419776,1081420287,PR 1081420288,1081420319,US 1081420320,1081420351,PR -1081420352,1081420479,US -1081420480,1081420543,PR -1081420544,1081421183,US -1081421184,1081421215,PR -1081421216,1081442367,US +1081420352,1081442367,US 1081442368,1081442399,CL -1081442400,1081442463,US -1081442464,1081442495,CL -1081442496,1081442911,US +1081442400,1081442911,US 1081442912,1081442927,CL 1081442928,1081442959,US 1081442960,1081442967,CL 1081442968,1081443327,US -1081443328,1081444863,CL -1081444864,1081445303,US -1081445304,1081445311,CL -1081445312,1081445375,US -1081445376,1081450495,CL -1081450496,1081460735,US +1081443328,1081444351,CL +1081444352,1081445375,US +1081445376,1081446399,CL +1081446400,1081460735,US 1081460736,1081462783,PA 1081462784,1081462815,CO -1081462816,1081462911,BR -1081462912,1081462919,US +1081462816,1081462847,BR +1081462848,1081462919,US 1081462920,1081462927,BR 1081462928,1081463231,US 1081463232,1081463247,BR @@ -12360,9 +13043,7 @@ 1082093680,1082093695,AU 1082093696,1082097055,US 1082097056,1082097071,CA -1082097072,1082097143,US -1082097144,1082097151,AU -1082097152,1082138623,US +1082097072,1082138623,US 1082138624,1082140671,A2 1082140672,1082314751,US 1082314752,1082315263,CA @@ -12380,9 +13061,7 @@ 1082348400,1082348407,BE 1082348408,1082348415,US 1082348416,1082348423,GB -1082348424,1082348439,US -1082348440,1082348447,SE -1082348448,1082348471,US +1082348424,1082348471,US 1082348472,1082348479,GB 1082348480,1082348735,US 1082348736,1082348799,NL @@ -12402,9 +13081,7 @@ 1082349776,1082349783,IT 1082349784,1082349815,US 1082349816,1082349823,RU -1082349824,1082350623,US -1082350624,1082350639,IT -1082350640,1082350655,US +1082349824,1082350655,US 1082350656,1082350671,IT 1082350672,1082350911,US 1082350912,1082350943,RU @@ -12426,15 +13103,13 @@ 1082952704,1082952959,CA 1082952960,1082982399,US 1082982400,1083015167,CA -1083015168,1083396095,US +1083015168,1083263743,US +1083263744,1083263999,GB +1083264000,1083396095,US 1083396096,1083400191,BM 1083400192,1083417727,US 1083417728,1083417791,CA -1083417792,1083421695,US -1083421696,1083421759,AU -1083421760,1083424511,US -1083424512,1083424767,AU -1083424768,1083437055,US +1083417792,1083437055,US 1083437056,1083441151,CA 1083441152,1083486911,US 1083486912,1083486943,IS @@ -12580,8 +13255,8 @@ 1086022208,1086022303,US 1086022304,1086022367,CA 1086022368,1086022591,US -1086022592,1086022655,CA -1086022656,1086023175,US +1086022592,1086022623,CA +1086022624,1086023175,US 1086023176,1086023183,GB 1086023184,1086023215,US 1086023216,1086023223,CA @@ -12595,15 +13270,15 @@ 1086027392,1086027407,IT 1086027408,1086027423,US 1086027424,1086027455,VN -1086027456,1086028663,US +1086027456,1086028031,US +1086028032,1086028287,PA +1086028288,1086028663,US 1086028664,1086028671,BR 1086028672,1086028751,US 1086028752,1086028759,BR 1086028760,1086029567,US 1086029568,1086029599,BO -1086029600,1086029703,US -1086029704,1086029719,GB -1086029720,1086029727,US +1086029600,1086029727,US 1086029728,1086029743,CA 1086029744,1086309887,US 1086309888,1086310143,AU @@ -12811,17 +13486,13 @@ 1089154969,1089154977,IN 1089154978,1089155011,US 1089155012,1089155031,TR -1089155032,1089156607,US -1089156608,1089156863,CA -1089156864,1089167359,US +1089155032,1089167359,US 1089167360,1089171455,CA 1089171456,1089171967,A2 1089171968,1089172735,US 1089172736,1089172839,A2 1089172840,1089172863,US -1089172864,1089172879,A2 -1089172880,1089172887,US -1089172888,1089172895,A2 +1089172864,1089172895,A2 1089172896,1089172927,US 1089172928,1089172983,A2 1089172984,1089172991,US @@ -12840,9 +13511,7 @@ 1089192592,1089192599,IT 1089192600,1089196623,CA 1089196624,1089196639,US -1089196640,1089197311,CA -1089197312,1089197567,AU -1089197568,1089200127,CA +1089196640,1089200127,CA 1089200128,1089200751,US 1089200752,1089200783,CA 1089200784,1089203439,US @@ -12953,13 +13622,14 @@ 1089970176,1089974271,PR 1089974272,1090146303,US 1090146304,1090150399,CA -1090150400,1090154495,US -1090158592,1090207743,US +1090150400,1090207743,US 1090207744,1090215935,CA 1090215936,1090355199,US 1090355200,1090356327,CA 1090356328,1090356335,US -1090356336,1090357535,CA +1090356336,1090356407,CA +1090356408,1090356415,US +1090356416,1090357535,CA 1090357536,1090357567,US 1090357568,1090357663,CA 1090357664,1090357679,US @@ -12977,10 +13647,10 @@ 1090396160,1090423759,US 1090423760,1090423783,FI 1090423784,1090424095,US -1090424096,1090424111,FI -1090424112,1090424287,US -1090424288,1090424303,FI -1090424304,1090424831,US +1090424096,1090424127,FI +1090424128,1090424287,US +1090424288,1090424319,FI +1090424320,1090424831,US 1090424832,1090428927,CA 1090428928,1090445311,US 1090445312,1090447359,CA @@ -13075,9 +13745,7 @@ 1091797264,1091797279,IT 1091797280,1091797855,US 1091797856,1091797871,IT -1091797872,1091797999,US -1091798000,1091798015,DE -1091798016,1091798639,US +1091797872,1091798639,US 1091798640,1091798647,CN 1091798648,1091798783,US 1091798784,1091799039,CN @@ -13087,7 +13755,11 @@ 1091800320,1091800327,JP 1091800328,1091802111,US 1091802112,1091802367,CA -1091802368,1091803135,US +1091802368,1091802831,US +1091802832,1091802847,CN +1091802848,1091802863,US +1091802864,1091802871,HK +1091802872,1091803135,US 1091803136,1091803391,CN 1091803392,1091803711,US 1091803712,1091803775,TH @@ -13097,17 +13769,15 @@ 1091804264,1091804271,BM 1091804272,1091806719,US 1091806720,1091806847,IT -1091806848,1091807087,US -1091807088,1091807095,MY -1091807096,1091807231,US +1091806848,1091807231,US 1091807232,1091807487,CA 1091807488,1091807999,US 1091808000,1091808511,CA 1091808512,1091809375,US 1091809376,1091809391,GB 1091809392,1091809407,US -1091809408,1091809439,JP -1091809440,1091811839,US +1091809408,1091809471,JP +1091809472,1091811839,US 1091811840,1091812095,IT 1091812096,1091812351,US 1091812352,1091812607,CN @@ -13165,8 +13835,8 @@ 1093057104,1093057119,JP 1093057120,1093057263,US 1093057264,1093057279,IT -1093057280,1093057295,US -1093057296,1093057343,CY +1093057280,1093057311,US +1093057312,1093057343,CY 1093057344,1093057391,US 1093057392,1093057407,RO 1093057408,1093057423,PH @@ -13218,9 +13888,13 @@ 1093112416,1093112431,CA 1093112432,1093112479,US 1093112480,1093112527,CA -1093112528,1093112895,US +1093112528,1093112855,US +1093112856,1093112863,CA +1093112864,1093112895,US 1093112896,1093112911,CA -1093112912,1093114623,US +1093112912,1093113087,US +1093113088,1093113119,CA +1093113120,1093114623,US 1093114624,1093114679,CA 1093114680,1093114703,US 1093114704,1093114711,CA @@ -13423,15 +14097,20 @@ 1093740096,1093740159,JP 1093740160,1093740167,US 1093740168,1093740191,CN -1093740192,1093740335,US +1093740192,1093740223,US +1093740224,1093740239,CN +1093740240,1093740247,US +1093740248,1093740255,HK +1093740256,1093740271,US +1093740272,1093740279,CN +1093740280,1093740335,US 1093740336,1093740351,SG 1093740352,1093740415,JP 1093740416,1093741599,US 1093741600,1093741607,ES 1093741608,1093743103,US 1093743104,1093743359,HK -1093743360,1093743391,US -1093743392,1093743423,PH +1093743360,1093743423,US 1093743424,1093743487,JP 1093743488,1093743743,US 1093743744,1093743807,CA @@ -13441,9 +14120,9 @@ 1093746880,1093746943,DE 1093746944,1093748799,US 1093748800,1093748863,CN -1093748864,1094319583,US -1094319584,1094319599,CA -1094319600,1094549687,US +1093748864,1093753111,US +1093753112,1093753119,CN +1093753120,1094549687,US 1094549688,1094549695,CA 1094549696,1094549783,US 1094549784,1094549791,AU @@ -13972,9 +14651,7 @@ 1096960768,1096960895,GB 1096960896,1096961023,US 1096961024,1096961151,GB -1096961152,1096964119,US -1096964120,1096964127,GB -1096964128,1096964263,US +1096961152,1096964263,US 1096964264,1096964271,IN 1096964272,1096968127,US 1096968128,1096968159,CA @@ -14008,29 +14685,19 @@ 1097067520,1097068031,GB 1097068032,1097069055,US 1097069056,1097069311,CA -1097069312,1097727999,US +1097069312,1097131439,US +1097131440,1097131447,HK +1097131448,1097727999,US 1097728000,1097729151,CA 1097729152,1097729167,US 1097729168,1097730847,CA 1097730848,1097730855,US -1097730856,1097730919,CA -1097730920,1097730927,US -1097730928,1097731447,CA +1097730856,1097731447,CA 1097731448,1097731455,GB 1097731456,1097736191,CA 1097736192,1097768959,US 1097768960,1097777151,CA -1097777152,1097798495,US -1097798496,1097798527,CA -1097798528,1097799167,US -1097799168,1097799199,CA -1097799200,1097799231,US -1097799232,1097799423,CA -1097799424,1097799679,US -1097799680,1097799711,CA -1097799712,1097799775,US -1097799776,1097799871,CA -1097799872,1097800959,US +1097777152,1097800959,US 1097800960,1097800991,CY 1097800992,1097801183,US 1097801184,1097801215,DE @@ -14206,12 +14873,17 @@ 1101983232,1101983743,AN 1101983744,1102004223,US 1102004224,1102004479,IN -1102004480,1102005503,US +1102004480,1102004735,US +1102004736,1102004991,IN +1102004992,1102005247,US +1102005248,1102005503,CA 1102005504,1102005759,PK 1102005760,1102005823,BE 1102005824,1102006271,US 1102006272,1102006527,CA -1102006528,1102007599,US +1102006528,1102007295,US +1102007296,1102007551,PK +1102007552,1102007599,US 1102007600,1102007615,AR 1102007616,1102007679,US 1102007680,1102007695,IN @@ -14223,7 +14895,10 @@ 1102008096,1102008103,CA 1102008104,1102008159,US 1102008160,1102008167,GB -1102008168,1102008639,US +1102008168,1102008223,US +1102008224,1102008231,CA +1102008232,1102008607,US +1102008608,1102008639,CA 1102008640,1102008671,BE 1102008672,1102008735,US 1102008736,1102008767,BE @@ -14233,8 +14908,7 @@ 1102010624,1102010879,PK 1102010880,1102011647,US 1102011648,1102011663,VE -1102011664,1102011679,GB -1102011680,1102011743,US +1102011664,1102011743,US 1102011744,1102011759,TR 1102011760,1102011855,US 1102011856,1102011871,CR @@ -14246,13 +14920,19 @@ 1102012976,1102012991,RU 1102012992,1102013167,US 1102013168,1102013183,VE -1102013184,1102016255,US +1102013184,1102014271,US +1102014272,1102014335,IN +1102014336,1102014399,CA +1102014400,1102016255,US 1102016256,1102016287,AR -1102016288,1102019583,US +1102016288,1102016351,US +1102016352,1102016383,MY +1102016384,1102019583,US 1102019584,1102019711,IN 1102019712,1102389247,US 1102389248,1102393343,CA -1102393344,1102446591,US +1102393344,1102397439,US +1102413824,1102446591,US 1102446592,1102448383,HN 1102448384,1102449151,US 1102449152,1102449407,SV @@ -14442,7 +15122,7 @@ 1107247104,1107275775,US 1107275776,1107279871,CA 1107279872,1107288063,US -1107288064,1107296255,CA +1107288064,1107292159,CA 1107296256,1107701759,US 1107701760,1107705855,CA 1107705856,1107800063,US @@ -14620,8 +15300,7 @@ 1109705824,1109705839,CD 1109705840,1109705855,US 1109705856,1109705983,CD -1109705984,1109706239,HT -1109706240,1109707007,US +1109705984,1109707007,US 1109707008,1109707263,JM 1109707264,1109707519,US 1109707520,1109707775,MW @@ -14746,7 +15425,9 @@ 1110458848,1110458879,US 1110458880,1110458927,CA 1110458928,1110458943,US -1110458944,1110459071,CA +1110458944,1110459007,CA +1110459008,1110459023,US +1110459024,1110459071,CA 1110459072,1110459087,US 1110459088,1110459151,CA 1110459152,1110459167,US @@ -14766,8 +15447,8 @@ 1110460320,1110460383,US 1110460384,1110460447,CA 1110460448,1110460479,US -1110460480,1110460511,CA -1110460512,1110460671,US +1110460480,1110460607,CA +1110460608,1110460671,US 1110460672,1110460719,CA 1110460720,1110460743,US 1110460744,1110460775,CA @@ -14832,16 +15513,15 @@ 1110870816,1110870847,HK 1110870848,1110870919,US 1110870920,1110870927,JP -1110870928,1110921215,US -1110925312,1110929407,US +1110870928,1110887423,US +1110887424,1110887679,IE +1110887680,1110929407,US 1110929408,1110933503,BM 1110933504,1111195647,US 1111195648,1111212031,CA 1111212032,1111228415,US 1111228416,1111244799,AR -1111244800,1111472127,US -1111472128,1111472383,AU -1111472384,1111888905,US +1111244800,1111888905,US 1111888906,1111888915,IN 1111888916,1111900223,US 1111900224,1111900287,NL @@ -14923,9 +15603,7 @@ 1114054656,1114062847,CA 1114062848,1114095615,US 1114095616,1114103807,CA -1114103808,1114163967,US -1114163968,1114164479,VI -1114164480,1114170095,US +1114103808,1114170095,US 1114170096,1114170111,CA 1114170112,1114505215,US 1114505216,1114507263,CA @@ -14949,9 +15627,7 @@ 1114533376,1114533887,ZA 1114533888,1114537983,AO 1114537984,1114550271,CA -1114550272,1114623999,US -1114624000,1114625023,NZ -1114625024,1114627071,US +1114550272,1114627071,US 1114627072,1114628095,NZ 1114628096,1114653951,US 1114653952,1114653983,MO @@ -14992,9 +15668,7 @@ 1114881344,1114881407,CY 1114881408,1114881471,US 1114881472,1114881535,CY -1114881536,1114881743,US -1114881744,1114881759,CA -1114881760,1114930175,US +1114881536,1114930175,US 1114930176,1114930303,GB 1114930304,1114966815,US 1114966816,1114966831,GB @@ -15022,6 +15696,7 @@ 1115117568,1115118591,HN 1115118592,1115119615,SV 1115119616,1115127807,US +1115127808,1115131903,CA 1115131904,1115135999,US 1115136000,1115138671,CA 1115138672,1115138679,US @@ -15077,9 +15752,7 @@ 1115698432,1115698687,DO 1115698688,1115698783,US 1115698784,1115698791,CO -1115698792,1115698943,US -1115698944,1115698951,CA -1115698952,1115698983,US +1115698792,1115698983,US 1115698984,1115698991,CO 1115698992,1115699903,US 1115699904,1115699911,CA @@ -15089,9 +15762,7 @@ 1115700224,1115700479,DO 1115700480,1115700735,US 1115700736,1115700743,CA -1115700744,1115700791,US -1115700792,1115700799,CA -1115700800,1115705343,US +1115700744,1115705343,US 1115705344,1115709439,CA 1115709440,1115783167,US 1115783168,1115784599,CA @@ -15361,8 +16032,8 @@ 1117417280,1117417343,US 1117417344,1117418655,CA 1117418656,1117418671,US -1117418672,1117419007,CA -1117419008,1117419519,US +1117418672,1117419263,CA +1117419264,1117419519,US 1117419520,1117419775,CA 1117419776,1117420543,US 1117420544,1117421055,CA @@ -15450,12 +16121,15 @@ 1118031760,1118031799,US 1118031800,1118031871,CA 1118031872,1118126079,US -1118126080,1118126591,CA -1118126592,1118126847,US +1118126080,1118126719,CA +1118126720,1118126847,US 1118126848,1118127231,CA 1118127232,1118127359,US 1118127360,1118127615,CA -1118127616,1118128383,US +1118127616,1118128191,US +1118128192,1118128255,MY +1118128256,1118128319,CA +1118128320,1118128383,MY 1118128384,1118128639,CA 1118128640,1118129151,US 1118129152,1118129663,CA @@ -15481,12 +16155,17 @@ 1118134912,1118134975,CA 1118134976,1118135007,US 1118135008,1118135039,IN -1118135040,1118135647,US +1118135040,1118135567,US +1118135568,1118135583,CA +1118135584,1118135615,US +1118135616,1118135631,TZ +1118135632,1118135647,US 1118135648,1118135663,CA -1118135664,1118135791,US -1118135792,1118135807,ID +1118135664,1118135807,US 1118135808,1118136191,CA -1118136192,1118136831,US +1118136192,1118136319,US +1118136320,1118136351,CA +1118136352,1118136831,US 1118136832,1118136863,IN 1118136864,1118136895,BE 1118136896,1118136927,US @@ -15499,15 +16178,24 @@ 1118137280,1118137311,FR 1118137312,1118138559,US 1118138560,1118138591,AU -1118138592,1118139903,US +1118138592,1118138623,FR +1118138624,1118138879,US +1118138880,1118139135,CA +1118139136,1118139903,US 1118139904,1118140415,CA -1118140416,1118140735,US +1118140416,1118140703,US +1118140704,1118140735,IN 1118140736,1118140767,AU -1118140768,1118141183,US +1118140768,1118140831,US +1118140832,1118140895,VE +1118140896,1118141183,US 1118141184,1118141439,CA 1118141440,1118141695,US 1118141696,1118141951,CA -1118141952,1118151215,US +1118141952,1118141967,CN +1118141968,1118142063,US +1118142064,1118142079,IN +1118142080,1118151215,US 1118151216,1118151231,TT 1118151232,1118151391,US 1118151392,1118151407,PR @@ -15607,7 +16295,8 @@ 1118476896,1118477535,CA 1118477536,1118477543,US 1118477544,1118478335,CA -1118478336,1118789783,US +1118478336,1118502911,US +1118568448,1118789783,US 1118789784,1118789791,BB 1118789792,1118790351,US 1118790352,1118790367,GB @@ -15615,12 +16304,10 @@ 1118791552,1118791567,LU 1118791568,1118791599,US 1118791600,1118791615,ES -1118791616,1118792703,US -1118792704,1118792831,JM -1118792832,1118792959,US -1118792960,1118793087,JM -1118793088,1118793343,US -1118793344,1118793727,JM +1118791616,1118792815,US +1118792816,1118792831,DO +1118792832,1118793471,US +1118793472,1118793727,CO 1118793728,1118793823,US 1118793824,1118793839,CA 1118793840,1118793935,US @@ -16027,8 +16714,7 @@ 1118992736,1118992743,SA 1118992744,1118992767,A2 1118992768,1118992839,US -1118992840,1118993919,A2 -1118993920,1118994431,GY +1118992840,1118994431,A2 1118994432,1119023735,US 1119023736,1119023743,UY 1119023744,1119109119,US @@ -16150,16 +16836,13 @@ 1119469568,1119477759,CA 1119477760,1119486623,US 1119486624,1119486631,AU -1119486632,1119490015,US -1119490016,1119490047,IE -1119490048,1119490495,US +1119486632,1119490495,US 1119490496,1119490527,GI 1119490528,1119502335,US 1119502336,1119510527,CA 1119510528,1119558143,US 1119558144,1119558655,PR 1119558656,1119567871,US -1119567872,1119571967,CA 1119571968,1119580159,US 1119580160,1119584255,CA 1119584256,1119999935,US @@ -16218,18 +16901,22 @@ 1120299264,1120299519,US 1120299520,1120300799,PK 1120300800,1120301055,US -1120301056,1120306175,CA -1120306176,1120306943,PH +1120301056,1120304895,CA +1120304896,1120305151,US +1120305152,1120306687,CA +1120306688,1120306943,PH 1120306944,1120307199,US 1120307200,1120307967,EC 1120307968,1120308223,PH -1120308224,1120309247,HT -1120309248,1120310015,CA +1120308224,1120309247,CA +1120309248,1120309503,US +1120309504,1120309759,CA +1120309760,1120310015,US 1120310016,1120310783,PH 1120310784,1120311807,CA 1120311808,1120312063,US 1120312064,1120312447,PH -1120312448,1120312575,US +1120312448,1120312575,CA 1120312576,1120312831,PH 1120312832,1120313343,CA 1120313344,1120313599,US @@ -16239,7 +16926,9 @@ 1120321536,1120346111,US 1120346112,1120350207,CA 1120350208,1120370687,US -1120370688,1120371511,CA +1120370688,1120371487,CA +1120371488,1120371503,US +1120371504,1120371511,CA 1120371512,1120371519,US 1120371520,1120371647,CA 1120371648,1120371651,US @@ -16249,7 +16938,9 @@ 1120372080,1120372223,US 1120372224,1120372479,CA 1120372480,1120372735,US -1120372736,1120374047,CA +1120372736,1120373423,CA +1120373424,1120373503,US +1120373504,1120374047,CA 1120374048,1120374063,US 1120374064,1120374271,CA 1120374272,1120374303,US @@ -16295,7 +16986,9 @@ 1120378920,1120378927,US 1120378928,1120379039,CA 1120379040,1120379071,PA -1120379072,1120380027,CA +1120379072,1120379167,CA +1120379168,1120379183,US +1120379184,1120380027,CA 1120380028,1120380031,US 1120380032,1120380095,CA 1120380096,1120380127,US @@ -16319,8 +17012,8 @@ 1120381120,1120382231,CA 1120382232,1120382239,US 1120382240,1120382271,CA -1120382272,1120382335,US -1120382336,1120382431,CA +1120382272,1120382367,US +1120382368,1120382431,CA 1120382432,1120382463,US 1120382464,1120382975,CA 1120382976,1120383263,US @@ -16342,14 +17035,17 @@ 1120385144,1120385151,US 1120385152,1120385183,GB 1120385184,1120385535,CA -1120385536,1120485759,US +1120385536,1120386559,US +1120386560,1120386815,CA +1120386816,1120485759,US 1120485760,1120485887,CA 1120485888,1120486079,US 1120486080,1120486143,IN 1120486144,1120486399,US 1120486400,1120486911,CA 1120486912,1120487039,US -1120487040,1120487167,CA +1120487040,1120487103,IN +1120487104,1120487167,CA 1120487168,1120487199,US 1120487200,1120487231,CA 1120487232,1120487359,US @@ -16357,9 +17053,7 @@ 1120487392,1120487423,BE 1120487424,1120487679,CA 1120487680,1120487935,US -1120487936,1120488191,CA -1120488192,1120488447,US -1120488448,1120488703,CA +1120487936,1120488703,CA 1120488704,1120488767,US 1120488768,1120488799,VE 1120488800,1120488831,IL @@ -16371,8 +17065,7 @@ 1120489344,1120489471,US 1120489472,1120489727,CA 1120489728,1120489983,US -1120489984,1120490111,SG -1120490112,1120490751,CA +1120489984,1120490751,CA 1120490752,1120490783,GB 1120490784,1120491007,US 1120491008,1120491775,CA @@ -16389,7 +17082,9 @@ 1120493824,1120494079,CA 1120494080,1120494335,US 1120494336,1120494591,CA -1120494592,1120495359,US +1120494592,1120494975,US +1120494976,1120495039,CA +1120495040,1120495359,US 1120495360,1120495615,CA 1120495616,1120495743,US 1120495744,1120495871,SG @@ -16399,20 +17094,21 @@ 1120496288,1120496385,US 1120496386,1120496638,CA 1120496639,1120496639,US -1120496640,1120497023,CA -1120497024,1120497151,IN +1120496640,1120497151,CA 1120497152,1120497183,BE 1120497184,1120497215,US 1120497216,1120497247,BE -1120497248,1120497375,US +1120497248,1120497311,US +1120497312,1120497343,IN +1120497344,1120497375,US 1120497376,1120497663,CA 1120497664,1120497791,US 1120497792,1120497919,AU 1120497920,1120497983,US 1120497984,1120498013,BE 1120498014,1120498143,US -1120498144,1120498175,CA -1120498176,1120498943,US +1120498144,1120498303,CA +1120498304,1120498943,US 1120498944,1120499199,CA 1120499200,1120499487,US 1120499488,1120499519,CA @@ -16434,9 +17130,7 @@ 1120568640,1120568671,CA 1120568672,1120575167,US 1120575168,1120575199,CA -1120575200,1120616807,US -1120616808,1120616815,CA -1120616816,1120641023,US +1120575200,1120641023,US 1120641024,1120657407,CA 1120657408,1120735487,US 1120735488,1120735743,BB @@ -16462,7 +17156,9 @@ 1120744704,1120854015,US 1120854016,1120862207,CA 1120862208,1120870399,US -1120874496,1120874519,A2 +1120874496,1120874503,A2 +1120874504,1120874511,US +1120874512,1120874519,A2 1120874520,1120874527,US 1120874528,1120874631,A2 1120874632,1120874639,US @@ -16495,7 +17191,9 @@ 1120876800,1120878359,US 1120878360,1120878591,A2 1120878592,1120886783,US -1120886784,1120894975,CA +1120886784,1120888127,CA +1120888128,1120888159,US +1120888160,1120894975,CA 1120894976,1120911359,US 1120911360,1120914415,CA 1120914416,1120914431,AT @@ -16534,7 +17232,7 @@ 1121247504,1121247511,AW 1121247512,1121247519,VG 1121247520,1121247527,BZ -1121247528,1121247535,GI +1121247528,1121247535,CA 1121247536,1121247543,BZ 1121247544,1121247551,CA 1121247552,1121247559,VG @@ -16542,7 +17240,7 @@ 1121247568,1121247583,PA 1121247584,1121247591,CY 1121247592,1121247615,CA -1121247616,1121247631,BZ +1121247616,1121247631,PA 1121247632,1121247639,AW 1121247640,1121247647,VG 1121247648,1121247663,US @@ -16581,8 +17279,7 @@ 1121248448,1121248495,BZ 1121248496,1121248783,CA 1121248784,1121248799,VG -1121248800,1121248831,GI -1121248832,1121248863,CA +1121248800,1121248863,CA 1121248864,1121248879,VG 1121248880,1121248911,CA 1121248912,1121248919,BZ @@ -16590,8 +17287,7 @@ 1121248960,1121248983,CA 1121248984,1121248991,AW 1121248992,1121249023,VG -1121249024,1121249279,CA -1121249280,1121249375,SE +1121249024,1121249375,CA 1121249376,1121249383,VG 1121249384,1121249407,CA 1121249408,1121249439,AG @@ -16619,7 +17315,9 @@ 1121250208,1121250239,CA 1121250240,1121250303,GB 1121250304,1121250815,BZ -1121250816,1121250879,AG +1121250816,1121250831,AG +1121250832,1121250839,BZ +1121250840,1121250879,AG 1121250880,1121250911,CA 1121250912,1121250927,VG 1121250928,1121250935,CA @@ -16630,15 +17328,14 @@ 1121251048,1121251055,AW 1121251056,1121251071,CA 1121251072,1121251079,GB -1121251080,1121251103,CY -1121251104,1121251135,CA +1121251080,1121251087,CY +1121251088,1121251135,CA 1121251136,1121251167,AG 1121251168,1121251199,VG 1121251200,1121251263,AW 1121251264,1121251271,CA 1121251272,1121251279,KN -1121251280,1121251287,CA -1121251288,1121251295,MU +1121251280,1121251295,CA 1121251296,1121251311,IM 1121251312,1121251583,CA 1121251584,1121251591,BZ @@ -17014,11 +17711,7 @@ 1122093808,1122093815,HK 1122093816,1122103471,US 1122103472,1122103479,BE -1122103480,1122108671,US -1122108672,1122108735,GR -1122108736,1122125978,US -1122125979,1122125988,PH -1122125989,1122125996,US +1122103480,1122125996,US 1122125997,1122126004,GB 1122126005,1122126239,US 1122126240,1122126249,GB @@ -17033,16 +17726,14 @@ 1122197608,1122197623,US 1122197624,1122197631,FR 1122197632,1122197695,US -1122197696,1122197759,GB +1122197696,1122197727,GB +1122197728,1122197735,US +1122197736,1122197759,GB 1122197760,1122197767,US 1122197768,1122197775,FR 1122197776,1122197823,US 1122197824,1122197831,GB -1122197832,1122197839,US -1122197840,1122197855,GB -1122197856,1122197887,US -1122197888,1122198015,GB -1122198016,1122203135,US +1122197832,1122203135,US 1122203136,1122203391,GB 1122203392,1122320959,US 1122320960,1122320995,PT @@ -17065,13 +17756,9 @@ 1122480168,1122480207,US 1122480208,1122480223,GB 1122480224,1122480231,PL -1122480232,1122480343,US -1122480344,1122480351,PR -1122480352,1122480415,US +1122480232,1122480415,US 1122480416,1122480423,CL -1122480424,1122480447,US -1122480448,1122480455,PR -1122480456,1122480479,US +1122480424,1122480479,US 1122480480,1122480487,CA 1122480488,1122493055,US 1122493056,1122493183,ES @@ -17082,11 +17769,11 @@ 1122496000,1122497407,US 1122497408,1122497471,SV 1122497472,1122497535,US -1122497536,1122498303,PR -1122498304,1122498559,US +1122497536,1122498047,PR +1122498048,1122498559,US 1122498560,1122498815,PR -1122498816,1122499327,US -1122499328,1122500095,PR +1122498816,1122499583,US +1122499584,1122500095,PR 1122500096,1122506751,US 1122506752,1122507007,IN 1122507008,1122525855,US @@ -17095,13 +17782,9 @@ 1122526097,1122526111,RU 1122526112,1122526454,US 1122526455,1122526462,RU -1122526463,1122526517,US -1122526518,1122526541,HK -1122526542,1122526876,US +1122526463,1122526876,US 1122526877,1122526888,RU -1122526889,1122526925,US -1122526926,1122526939,RU -1122526940,1122528183,US +1122526889,1122528183,US 1122528184,1122528254,RU 1122528255,1122528603,US 1122528604,1122528613,ES @@ -17138,15 +17821,11 @@ 1123582272,1123582399,US 1123582400,1123582431,DE 1123582432,1123582463,CA -1123582464,1123583327,US -1123583328,1123583359,CA -1123583360,1123583455,US +1123582464,1123583455,US 1123583456,1123583519,CY 1123583520,1123584351,US 1123584352,1123584383,DE -1123584384,1123584703,US -1123584704,1123584735,CA -1123584736,1123588063,US +1123584384,1123588063,US 1123588064,1123588095,CY 1123588096,1123590143,US 1123590144,1123598335,VI @@ -17163,15 +17842,7 @@ 1123801088,1123801343,RU 1123801344,1123848191,US 1123848192,1123852287,CA -1123852288,1123862080,US -1123862081,1123862270,RU -1123862271,1123862454,US -1123862455,1123862520,RU -1123862521,1123862592,US -1123862593,1123862782,RU -1123862783,1123862880,US -1123862881,1123862888,RU -1123862889,1123870063,US +1123852288,1123870063,US 1123870064,1123870071,GB 1123870072,1123870295,US 1123870296,1123870303,HK @@ -17234,9 +17905,7 @@ 1125091744,1125091759,US 1125091760,1125091775,UY 1125091776,1125091839,CA -1125091840,1125093375,US -1125093376,1125093407,TH -1125093408,1125093471,US +1125091840,1125093471,US 1125093472,1125093503,IL 1125093504,1125093567,SK 1125093568,1125093631,AU @@ -17244,8 +17913,7 @@ 1125094464,1125094527,BR 1125094528,1125094655,US 1125094656,1125094671,GB -1125094672,1125094687,SK -1125094688,1125094783,US +1125094672,1125094783,US 1125094784,1125094799,GB 1125094800,1125094847,CA 1125094848,1125094911,BR @@ -17354,11 +18022,110 @@ 1125120848,1125120863,US 1125120864,1125120895,GB 1125120896,1125121023,RO -1125121024,1125474303,US +1125121024,1125454111,US +1125454112,1125454119,ES +1125454120,1125454143,US +1125454144,1125454151,GB +1125454152,1125454271,US +1125454272,1125454279,DE +1125454280,1125454303,US +1125454304,1125454323,NO +1125454324,1125454327,SG +1125454328,1125454343,US +1125454344,1125454351,NO +1125454352,1125454371,US +1125454372,1125454375,ES +1125454376,1125454383,US +1125454384,1125454395,NO +1125454396,1125454411,US +1125454412,1125454423,NO +1125454424,1125454435,ES +1125454436,1125454439,NO +1125454440,1125454447,ES +1125454448,1125454451,NO +1125454452,1125454459,US +1125454460,1125454463,NO +1125454464,1125454467,ES +1125454468,1125454471,NO +1125454472,1125454479,ES +1125454480,1125454483,NO +1125454484,1125454487,ES +1125454488,1125454495,NO +1125454496,1125454499,CA +1125454500,1125454503,ES +1125454504,1125454507,US +1125454508,1125454511,ES +1125454512,1125454527,NO +1125454528,1125454543,US +1125454544,1125454555,ES +1125454556,1125454587,US +1125454588,1125454591,CA +1125454592,1125455359,US +1125455360,1125455363,CA +1125455364,1125455367,US +1125455368,1125455371,GB +1125455372,1125455395,US +1125455396,1125455399,NO +1125455400,1125455423,US +1125455424,1125455427,ES +1125455428,1125455431,GB +1125455432,1125455435,US +1125455436,1125455439,ES +1125455440,1125455443,CA +1125455444,1125455447,US +1125455448,1125455451,NO +1125455452,1125455475,US +1125455476,1125455479,NO +1125455480,1125455491,US +1125455492,1125455495,GB +1125455496,1125455499,CA +1125455500,1125455507,US +1125455508,1125455515,ES +1125455516,1125455519,CA +1125455520,1125455523,ES +1125455524,1125455527,US +1125455528,1125455531,ES +1125455532,1125455535,NO +1125455536,1125455543,US +1125455544,1125455547,ES +1125455548,1125455551,VG +1125455552,1125455555,ES +1125455556,1125455559,US +1125455560,1125455563,NZ +1125455564,1125455567,ES +1125455568,1125455571,US +1125455572,1125455575,NO +1125455576,1125455579,AN +1125455580,1125456131,US +1125456132,1125456135,NO +1125456136,1125456151,US +1125456152,1125456155,NL +1125456156,1125456163,US +1125456164,1125456167,NO +1125456168,1125456175,US +1125456176,1125456179,NO +1125456180,1125456191,US +1125456192,1125456195,GB +1125456196,1125456199,NO +1125456200,1125456203,AN +1125456204,1125456207,US +1125456208,1125456211,SG +1125456212,1125456231,US +1125456232,1125456239,ES +1125456240,1125456247,GB +1125456248,1125456259,AN +1125456260,1125456263,ES +1125456264,1125456407,US +1125456408,1125456411,AN +1125456412,1125456415,US +1125456416,1125456419,AN +1125456420,1125474303,US 1125474304,1125478399,CA 1125478400,1125479199,US 1125479200,1125479231,BR -1125479232,1125498879,US +1125479232,1125493127,US +1125493128,1125493135,CA +1125493136,1125498879,US 1125498880,1125508095,CA 1125508096,1125508351,PA 1125508352,1125514495,CA @@ -17382,9 +18149,17 @@ 1125540704,1125540711,US 1125540712,1125540927,CA 1125540928,1125540959,US -1125540960,1125543935,CA +1125540960,1125541151,CA +1125541152,1125541159,CN +1125541160,1125541183,CA +1125541184,1125541215,KY +1125541216,1125543935,CA 1125543936,1125545983,US -1125548032,1125552127,CA +1125548032,1125548291,CA +1125548292,1125548351,US +1125548352,1125550079,CA +1125550080,1125550335,US +1125550336,1125552127,CA 1125552128,1125572607,US 1125572608,1125576703,CA 1125576704,1125613567,US @@ -17411,15 +18186,12 @@ 1126682720,1126682727,PR 1126682728,1126682823,US 1126682824,1126682831,PR -1126682832,1126907535,US -1126907536,1126907543,ES -1126907544,1126924287,US +1126682832,1126924287,US 1126924288,1126928383,CA 1126928384,1126948863,US 1126948864,1126949375,CA 1126949376,1126949503,GB -1126949504,1126949551,CA -1126949552,1126949559,GB +1126949504,1126949559,CA 1126949560,1126949567,BZ 1126949568,1126949583,CA 1126949584,1126949591,LB @@ -17428,35 +18200,21 @@ 1126949616,1126949631,LB 1126949632,1126949695,CA 1126949696,1126949759,PK -1126949760,1126949823,CA -1126949824,1126949855,US -1126949856,1126950191,CA +1126949760,1126950191,CA 1126950192,1126950199,ES 1126950200,1126950207,HR -1126950208,1126950303,CA -1126950304,1126950335,US -1126950336,1126950367,CA -1126950368,1126950399,US -1126950400,1126950415,CA +1126950208,1126950415,CA 1126950416,1126950423,PK 1126950424,1126950431,RU 1126950432,1126950463,CA 1126950464,1126950495,IT -1126950496,1126950527,US -1126950528,1126950559,CA -1126950560,1126950591,US -1126950592,1126950599,CA +1126950496,1126950599,CA 1126950600,1126950607,CN 1126950608,1126950623,CA 1126950624,1126950655,FR 1126950656,1126950783,CA 1126950784,1126950847,MY -1126950848,1126950911,US -1126950912,1126951039,CA -1126951040,1126951071,US -1126951072,1126951103,CA -1126951104,1126951135,US -1126951136,1126951775,CA +1126950848,1126951775,CA 1126951776,1126951783,PH 1126951784,1126951967,CA 1126951968,1126951975,KP @@ -17470,29 +18228,13 @@ 1126952264,1126952271,PH 1126952272,1126952447,CA 1126952448,1126952511,AE -1126952512,1126952543,US -1126952544,1126952559,CA +1126952512,1126952559,CA 1126952560,1126952567,TH -1126952568,1126952703,CA -1126952704,1126952767,CY -1126952768,1126952895,CA +1126952568,1126952895,CA 1126952896,1126952959,CY 1126952960,1127677951,US 1127677952,1127694335,CA -1127694336,1127874559,US -1127875328,1127875839,US -1127875840,1127876095,CA -1127876608,1127876863,US -1127877120,1127877375,US -1127877376,1127877631,CA -1127878144,1127878399,US -1127878400,1127878911,CA -1127878912,1127879167,US -1127879680,1127879935,CA -1127879936,1127880191,US -1127880448,1127880703,US -1127880704,1127882751,CA -1127882752,1127923711,US +1127694336,1127923711,US 1127923712,1127931903,CA 1127931904,1127976191,US 1127976192,1127976223,IL @@ -17542,7 +18284,9 @@ 1132947432,1132947439,CA 1132947440,1133785375,US 1133785376,1133785383,NE -1133785384,1133785471,US +1133785384,1133785391,US +1133785392,1133785407,GB +1133785408,1133785471,US 1133785472,1133785503,GB 1133785504,1133785567,US 1133785568,1133785599,BE @@ -18280,13 +19024,9 @@ 1136721920,1136787455,CA 1136787456,1137090815,US 1137090816,1137091327,NZ -1137091328,1137134083,US -1137134084,1137134099,CA -1137134100,1137134283,US -1137134284,1137134331,CA -1137134332,1137189135,US +1137091328,1137189135,US 1137189136,1137189151,IE -1137189152,1137189183,GB +1137189152,1137189183,US 1137189184,1137189247,IE 1137189248,1137189255,GB 1137189256,1137189263,US @@ -18299,9 +19039,7 @@ 1137278976,1137283071,CA 1137283072,1137287167,US 1137287168,1137295359,CA -1137295360,1137337599,US -1137337600,1137337855,CA -1137337856,1137369087,US +1137295360,1137369087,US 1137369088,1137369519,CA 1137369520,1137369535,US 1137369536,1137370111,CA @@ -18631,8 +19369,7 @@ 1138164008,1138164015,FR 1138164016,1138164127,CA 1138164128,1138164151,FR -1138164152,1138164159,GB -1138164160,1138164175,CA +1138164152,1138164175,CA 1138164176,1138164183,SK 1138164184,1138164191,PH 1138164192,1138164199,PK @@ -18643,8 +19380,7 @@ 1138164256,1138164263,LB 1138164264,1138164271,FR 1138164272,1138164279,PH -1138164280,1138164311,CA -1138164312,1138164327,GB +1138164280,1138164327,CA 1138164328,1138164335,PA 1138164336,1138164367,CA 1138164368,1138164375,PH @@ -18661,14 +19397,11 @@ 1138164832,1138164839,PH 1138164840,1138164863,CA 1138164864,1138165247,US -1138165248,1138165255,GB -1138165256,1138165311,CA +1138165248,1138165311,CA 1138165312,1138165319,US 1138165320,1138165431,CA 1138165432,1138165439,LB -1138165440,1138165463,CA -1138165464,1138165471,GB -1138165472,1138165487,CA +1138165440,1138165487,CA 1138165488,1138165503,SK 1138165504,1138165807,CA 1138165808,1138165815,FR @@ -18734,10 +19467,13 @@ 1138212864,1138216959,CA 1138216960,1138271087,US 1138271088,1138271103,TN -1138271104,1138417663,US +1138271104,1138401279,US +1138409472,1138417663,US 1138417664,1138417695,CA 1138417696,1138417727,DE -1138417728,1138450959,US +1138417728,1138421759,US +1138421760,1138421791,DE +1138421792,1138450959,US 1138450960,1138450967,JM 1138450968,1138450991,US 1138450992,1138450999,MX @@ -18764,8 +19500,7 @@ 1138452016,1138452047,US 1138452048,1138452055,AU 1138452056,1138452063,GB -1138452064,1138452255,US -1138452256,1138452263,GB +1138452064,1138452263,US 1138452264,1138452271,IN 1138452272,1138452287,US 1138452288,1138452295,GR @@ -18785,7 +19520,9 @@ 1138454016,1138454271,RU 1138454272,1138454591,US 1138454592,1138454599,CA -1138454600,1138499583,US +1138454600,1138480127,US +1138480128,1138482687,AU +1138482688,1138499583,US 1138499584,1138503679,CA 1138503680,1138508031,US 1138508032,1138508095,GB @@ -18814,35 +19551,23 @@ 1138512672,1138512895,US 1138512896,1138512927,ID 1138512928,1138548735,US -1138548736,1138549260,CA -1138549261,1138549347,HK -1138549348,1138549503,CA -1138549504,1138549631,PL -1138549632,1138550015,CA -1138550016,1138552575,US -1138552576,1138556927,CA +1138548736,1138556927,CA 1138556928,1138593791,US 1138593792,1138597887,CA 1138597888,1138600447,US 1138600448,1138600703,BE 1138600704,1138615299,US 1138615300,1138615323,IT -1138615324,1138655241,US -1138655242,1138655316,CA -1138655317,1138655328,US -1138655329,1138655336,CA -1138655337,1138655374,US +1138615324,1138655245,US +1138655246,1138655316,CA +1138655317,1138655374,US 1138655375,1138655382,CA -1138655383,1138655422,US -1138655423,1138655430,RU -1138655431,1138655446,US +1138655383,1138655446,US 1138655447,1138655454,CA 1138655455,1138655458,US 1138655459,1138655486,CA 1138655487,1138655503,US -1138655504,1138655513,MX -1138655514,1138655519,US -1138655520,1138655521,MX +1138655504,1138655521,MX 1138655522,1138655609,US 1138655610,1138655617,MX 1138655618,1138655695,US @@ -18851,84 +19576,39 @@ 1138655716,1138655723,GB 1138655724,1138655841,US 1138655842,1138655849,CN -1138655850,1138655857,US -1138655858,1138655865,CN -1138655866,1138655899,US +1138655850,1138655899,US 1138655900,1138655911,MX -1138655912,1138656021,US -1138656022,1138656029,TW -1138656030,1138656077,US +1138655912,1138656077,US 1138656078,1138656093,MX -1138656094,1138656097,US -1138656098,1138656113,GB -1138656114,1138656121,US -1138656122,1138656129,GB -1138656130,1138656141,US +1138656094,1138656141,US 1138656142,1138656173,GB 1138656174,1138656190,US 1138656191,1138656198,CH 1138656199,1138656206,GB 1138656207,1138656222,US 1138656223,1138656230,EG -1138656231,1138656301,US -1138656302,1138656309,MO -1138656310,1138656330,US -1138656331,1138656338,TR -1138656339,1138656398,US -1138656399,1138656406,MO -1138656407,1138656407,GB -1138656408,1138656413,US -1138656414,1138656415,GB -1138656416,1138656521,US -1138656522,1138656529,EG -1138656530,1138656661,US +1138656231,1138656661,US 1138656662,1138656669,MA 1138656670,1138656745,US 1138656746,1138656753,AE -1138656754,1138656777,US -1138656778,1138656793,UY -1138656794,1138656933,US -1138656934,1138656941,UY -1138656942,1138656973,US -1138656974,1138656981,UY -1138656982,1138656997,US -1138656998,1138657005,UY -1138657006,1138657041,US -1138657042,1138657056,SA -1138657057,1138657123,US +1138656754,1138657123,US 1138657124,1138657131,EG -1138657132,1138657159,US -1138657160,1138657173,MO +1138657132,1138657173,US 1138657174,1138657181,EG -1138657182,1138657193,US -1138657194,1138657195,AE -1138657196,1138657197,US -1138657198,1138657199,EG -1138657200,1138657201,AE -1138657202,1138657205,EG +1138657182,1138657197,US +1138657198,1138657205,EG 1138657206,1138657206,US 1138657207,1138657214,EG 1138657215,1138657222,IN 1138657223,1138657235,US 1138657236,1138657244,MA -1138657245,1138657346,US -1138657347,1138657354,MO -1138657355,1138657504,US +1138657245,1138657324,US +1138657325,1138657332,LK +1138657333,1138657504,US 1138657505,1138657520,EG -1138657521,1138657569,US -1138657570,1138657577,UY -1138657578,1138657597,US -1138657598,1138657605,UY -1138657606,1138657671,US -1138657672,1138657679,UY -1138657680,1138657681,US -1138657682,1138657691,UY -1138657692,1138657707,US -1138657708,1138657732,UY -1138657733,1138657748,US +1138657521,1138657748,US 1138657749,1138657780,GB -1138657781,1138657790,UY -1138657791,1138658057,US +1138657781,1138658057,US 1138658058,1138658123,GB 1138658124,1138658175,US 1138658176,1138658302,GB @@ -18937,35 +19617,30 @@ 1138658497,1138658497,US 1138658498,1138658525,PK 1138658526,1138659081,US -1138659082,1138659211,ES -1138659212,1138659369,US +1138659082,1138659207,ES +1138659208,1138659369,US 1138659370,1138659401,GB 1138659402,1138659465,US 1138659466,1138659497,GB 1138659498,1138659593,US 1138659594,1138659609,LK 1138659610,1138659642,GB -1138659643,1138659650,US -1138659651,1138659660,UY -1138659661,1138659673,US +1138659643,1138659673,US 1138659674,1138659681,MA 1138659682,1138659705,US 1138659706,1138659713,CA -1138659714,1138659721,UY -1138659722,1138659723,US +1138659714,1138659723,US 1138659724,1138659731,ID 1138659732,1138659789,US 1138659790,1138659797,ID -1138659798,1138659805,UY +1138659798,1138659805,US 1138659806,1138659813,ID -1138659814,1138659823,UY +1138659814,1138659823,US 1138659824,1138659831,ID 1138659832,1138659849,US 1138659850,1138659857,MA 1138659858,1138659889,GB -1138659890,1138659903,US -1138659904,1138659911,CA -1138659912,1138659922,US +1138659890,1138659922,US 1138659923,1138659930,LK 1138659931,1138659983,US 1138659984,1138659999,EG @@ -18991,9 +19666,7 @@ 1138660362,1138660483,EG 1138660484,1138660499,US 1138660500,1138660507,AE -1138660508,1138660563,US -1138660564,1138660571,GB -1138660572,1138660617,US +1138660508,1138660617,US 1138660618,1138660625,AE 1138660626,1138660633,EG 1138660634,1138660665,US @@ -19001,13 +19674,11 @@ 1138660674,1138660694,US 1138660695,1138660726,GB 1138660727,1138660734,EG -1138660735,1138660778,US -1138660779,1138660786,MY -1138660787,1138660805,US +1138660735,1138660805,US 1138660806,1138660821,EG 1138660822,1138660873,US 1138660874,1138660881,EG -1138660882,1138660889,MA +1138660882,1138660889,US 1138660890,1138660897,EG 1138660898,1138660921,US 1138660922,1138660929,EG @@ -19024,14 +19695,9 @@ 1138661056,1138661063,EG 1138661064,1138661169,US 1138661170,1138661177,LK -1138661178,1138661185,US -1138661186,1138661193,UY -1138661194,1138661201,US +1138661178,1138661201,US 1138661202,1138661209,MA -1138661210,1138661217,UY -1138661218,1138661249,US -1138661250,1138661257,UY -1138661258,1138661265,US +1138661210,1138661265,US 1138661266,1138661281,EG 1138661282,1138661299,US 1138661300,1138661307,GB @@ -19059,9 +19725,7 @@ 1138661914,1138661954,EG 1138661955,1138661985,US 1138661986,1138661993,EG -1138661994,1138662017,US -1138662018,1138662025,EG -1138662026,1138662057,US +1138661994,1138662057,US 1138662058,1138662107,EG 1138662108,1138662169,US 1138662170,1138662233,EG @@ -19081,8 +19745,8 @@ 1138662802,1138662841,US 1138662842,1138662849,GB 1138662850,1138662966,US -1138662967,1138662974,EG -1138662975,1138663037,US +1138662967,1138662982,EG +1138662983,1138663037,US 1138663038,1138663166,GB 1138663167,1138712575,US 1138712576,1138713583,CA @@ -19110,15 +19774,11 @@ 1138819072,1138851839,CA 1138851840,1138851847,US 1138851848,1138851855,IN -1138851856,1138865562,US -1138865563,1138865566,IN -1138865567,1138865578,US +1138851856,1138865578,US 1138865579,1138865586,IN 1138865587,1138874252,US 1138874253,1138874264,UY -1138874265,1138879999,US -1138880000,1138880511,CA -1138880512,1138882331,US +1138874265,1138882331,US 1138882332,1138882339,GB 1138882340,1138882445,US 1138882446,1138882453,GB @@ -19126,16 +19786,30 @@ 1138917376,1138937855,CA 1138937856,1138941951,US 1138941952,1138950143,CA -1138950144,1139120127,US -1139120128,1139124223,NZ -1139124224,1139146751,US +1138950144,1139146751,US 1139146752,1139154943,GT 1139154944,1139167231,JM 1139167232,1139179519,US -1139179520,1139195903,CA -1139195904,1139204095,US -1139212288,1139261439,US -1139261440,1139269631,CA +1139179520,1139188223,CA +1139188224,1139188479,GB +1139188480,1139188735,CA +1139188736,1139188991,GB +1139188992,1139189503,US +1139189504,1139189759,CA +1139189760,1139190015,US +1139190016,1139191551,CA +1139191552,1139191807,GB +1139191808,1139192063,CA +1139192064,1139192575,US +1139192576,1139192831,GB +1139192832,1139193215,US +1139193216,1139193599,CA +1139193600,1139195135,US +1139195136,1139195391,GB +1139195392,1139195775,US +1139195776,1139195903,CA +1139195904,1139265535,US +1139265536,1139269631,CA 1139269632,1142187775,US 1142187776,1142187783,PR 1142187784,1142191847,US @@ -19164,11 +19838,38 @@ 1145261056,1145261119,IN 1145261120,1145261311,US 1145261312,1145261375,IN -1145261376,1145262079,US -1145262080,1145266175,CA -1145266176,1145307135,US +1145261376,1145307135,US 1145307136,1145311231,CA -1145311232,1145376767,US +1145311232,1145315559,US +1145315560,1145315567,GB +1145315568,1145331711,US +1145331712,1145331967,DK +1145331968,1145333031,US +1145333032,1145333039,IT +1145333040,1145333239,US +1145333240,1145333247,CN +1145333248,1145333327,US +1145333328,1145333343,CN +1145333344,1145333351,US +1145333352,1145333367,CN +1145333368,1145333375,PA +1145333376,1145333503,BD +1145333504,1145333863,US +1145333864,1145333871,EG +1145333872,1145333879,US +1145333880,1145333903,CN +1145333904,1145333911,US +1145333912,1145333919,CN +1145333920,1145334055,US +1145334056,1145334063,CN +1145334064,1145334143,US +1145334144,1145334167,CN +1145334168,1145334175,HK +1145334176,1145335167,US +1145335168,1145335199,CN +1145335200,1145335215,US +1145335216,1145335231,CN +1145335232,1145376767,US 1145376768,1145380863,CA 1145380864,1145405439,US 1145405440,1145413631,CA @@ -19176,7 +19877,11 @@ 1145421824,1145430015,CA 1145430016,1145475071,US 1145475072,1145479167,CA -1145479168,1145491455,US +1145479168,1145483583,US +1145483584,1145483591,VG +1145483592,1145484031,US +1145484032,1145484063,VG +1145484064,1145503743,US 1145503744,1145520127,CA 1145520128,1145552895,US 1145552896,1145556991,CA @@ -19205,9 +19910,7 @@ 1151889792,1151889823,MA 1151889824,1151889839,CA 1151889840,1151889847,PH -1151889848,1151889919,CA -1151889920,1151889943,GB -1151889944,1151890007,CA +1151889848,1151890007,CA 1151890008,1151890015,GB 1151890016,1151890079,CA 1151890080,1151890087,GB @@ -19217,35 +19920,23 @@ 1151890216,1151890223,GB 1151890224,1151892735,CA 1151892736,1151892991,MA -1151892992,1151897599,CA -1151897600,1151943679,US -1151943680,1151943807,GB -1151943808,1151943871,NL -1151943872,1151943935,CA -1151943936,1151943999,DE +1151892992,1151894783,CA +1151894784,1151895039,US +1151895040,1151895295,CA +1151895296,1151895807,US +1151895808,1151895919,CA +1151895920,1151895935,US +1151895936,1151896079,CA +1151896080,1151896087,US +1151896088,1151896127,CA +1151896128,1151896191,US +1151896192,1151896319,CA +1151896320,1151943999,US 1151944000,1151944063,HK -1151944064,1151944079,CH -1151944080,1151944095,NO -1151944096,1151944111,KR -1151944112,1151944127,US -1151944128,1151944159,AU -1151944160,1151944175,FR -1151944176,1151944575,US -1151944576,1151944703,ES -1151944704,1151945727,US -1151945728,1151945759,RU +1151944064,1151945759,US 1151945760,1151945791,IE -1151945792,1151945823,IT -1151945824,1151945855,AT -1151945856,1151945887,SE -1151945888,1151945919,US -1151945920,1151945935,JP -1151945936,1151946239,US -1151946240,1151946751,GB -1151946752,1151954943,US -1151959040,1152057343,US -1152057344,1152061439,CA -1152061440,1152073727,US +1151945792,1151954943,US +1151959040,1152073727,US 1152073728,1152077823,CA 1152077824,1152581631,US 1152581632,1152614399,CA @@ -19255,13 +19946,22 @@ 1154488320,1154488575,A2 1154488576,1156071423,US 1156071424,1156079615,CA -1156079616,1156259839,US +1156079616,1156129479,US +1156129480,1156129487,SG +1156129488,1156129495,JP +1156129496,1156129503,US +1156129504,1156129791,CA +1156129792,1156129983,US +1156129984,1156129999,CY +1156130000,1156130015,US +1156130016,1156130303,CA +1156130304,1156131327,US +1156131328,1156131583,CA +1156131584,1156259839,US 1156259840,1156265983,CA 1156265984,1156296703,US 1156296704,1156300799,CA -1156300800,1156335367,US -1156335368,1156335375,PR -1156335376,1157670431,US +1156300800,1157670431,US 1157670432,1157670463,CA 1157670464,1157713663,US 1157713664,1157713791,CA @@ -19926,9 +20626,7 @@ 1159480440,1159480447,CA 1159480448,1159481167,US 1159481168,1159481183,VG -1159481184,1159481855,US -1159481856,1159481887,EG -1159481888,1159482423,US +1159481184,1159482423,US 1159482424,1159482431,AN 1159482432,1159512063,US 1159512064,1159512159,CA @@ -19940,8 +20638,8 @@ 1159513024,1159513343,CA 1159513344,1159513375,US 1159513376,1159513439,CA -1159513440,1159513471,US -1159513472,1159513519,CA +1159513440,1159513487,US +1159513488,1159513519,CA 1159513520,1159513535,US 1159513536,1159513567,CA 1159513568,1159513599,US @@ -19959,32 +20657,34 @@ 1159517120,1159517151,CA 1159517152,1159517183,US 1159517184,1159517327,CA -1159517328,1159517343,US -1159517344,1159517359,CA -1159517360,1159517439,US -1159517440,1159517599,CA +1159517328,1159517567,US +1159517568,1159517599,CA 1159517600,1159517631,US -1159517632,1159517679,CA -1159517680,1159517695,US +1159517632,1159517663,CA +1159517664,1159517695,US 1159517696,1159517975,CA 1159517976,1159517991,US -1159517992,1159518007,CA -1159518008,1159518015,US +1159517992,1159517999,CA +1159518000,1159518015,US 1159518016,1159518175,CA 1159518176,1159518199,US 1159518200,1159518207,CA 1159518208,1159519743,US 1159519744,1159520767,CA 1159520768,1159520799,US -1159520800,1159521023,CA -1159521024,1159521087,US +1159520800,1159520959,CA +1159520960,1159520975,US +1159520976,1159521007,CA +1159521008,1159521087,US 1159521088,1159521199,CA 1159521200,1159521215,US 1159521216,1159521823,CA 1159521824,1159521855,US 1159521856,1159522031,CA 1159522032,1159522047,US -1159522048,1159522095,CA +1159522048,1159522063,CA +1159522064,1159522071,US +1159522072,1159522095,CA 1159522096,1159522111,US 1159522112,1159522143,CA 1159522144,1159522167,US @@ -19997,9 +20697,7 @@ 1159522304,1159523327,CA 1159523328,1159523583,US 1159523584,1159524351,CA -1159524352,1159525071,US -1159525072,1159525087,CA -1159525088,1159525375,US +1159524352,1159525375,US 1159525376,1159526399,CA 1159526400,1159527935,US 1159527936,1159528191,CA @@ -20020,17 +20718,17 @@ 1159657072,1159657087,NZ 1159657088,1159659063,US 1159659064,1159659079,IN -1159659080,1159667967,US -1159667968,1159668991,AU -1159668992,1159669247,US -1159669248,1159669759,AU -1159669760,1159700479,US +1159659080,1159668479,US +1159668480,1159668735,CA +1159668736,1159694591,US +1159694592,1159694847,CA +1159694848,1159700479,US 1159700480,1159725055,CA 1159725056,1159988735,US 1159988736,1159988991,MX -1159988992,1159990783,US -1159990784,1159991039,MX -1159991040,1159995935,US +1159988992,1159995647,US +1159995648,1159995655,AU +1159995656,1159995935,US 1159995936,1159995951,CA 1159995952,1159996063,US 1159996064,1159996079,GB @@ -20105,56 +20803,17 @@ 1160017160,1160019967,CA 1160019968,1160364031,US 1160364032,1160368127,CA -1160368128,1160392751,US -1160392752,1160392799,CA -1160392800,1160392815,US -1160392816,1160392939,CA -1160392940,1160392959,US -1160392960,1160393031,CA -1160393032,1160393039,US -1160393040,1160393055,CA -1160393056,1160393087,US -1160393088,1160393151,CA -1160393152,1160393215,US -1160393216,1160393279,CA -1160393280,1160393295,HK -1160393296,1160393311,CA -1160393312,1160393327,US -1160393328,1160393343,CA -1160393344,1160393359,US -1160393360,1160393535,CA -1160393536,1160393599,US -1160393600,1160393791,CA -1160393792,1160393799,HK -1160393800,1160393807,US -1160393808,1160393871,CA -1160393872,1160393879,GB -1160393880,1160393951,CA -1160393952,1160393959,HK -1160393960,1160393983,CA -1160393984,1160394239,US -1160394240,1160394295,CA -1160394296,1160394303,US -1160394304,1160394495,CA -1160394496,1160394751,US -1160394752,1160395007,CA -1160395008,1160395263,US -1160395264,1160395391,CA -1160395392,1160395775,US -1160395776,1160396031,CA -1160396032,1160396287,US -1160396288,1160396543,CA -1160396544,1160397007,US +1160368128,1160397007,US 1160397008,1160397023,GB -1160397024,1160405503,US -1160405504,1160405615,DO -1160405616,1160405631,US +1160397024,1160405631,US 1160405632,1160406015,DO 1160406016,1160406271,US 1160406272,1160406303,VE 1160406304,1160406319,US 1160406320,1160406335,DO -1160406336,1160406479,US +1160406336,1160406431,US +1160406432,1160406447,ES +1160406448,1160406479,US 1160406480,1160406487,A2 1160406488,1160408095,US 1160408096,1160408111,GD @@ -20170,7 +20829,9 @@ 1160410192,1160410207,BM 1160410208,1160410239,US 1160410240,1160410255,MX -1160410256,1160410447,US +1160410256,1160410287,US +1160410288,1160410303,DO +1160410304,1160410447,US 1160410448,1160410463,UY 1160410464,1160410479,TT 1160410480,1160410495,US @@ -20219,9 +20880,7 @@ 1160437504,1160437535,PT 1160437536,1160437695,US 1160437696,1160437759,IN -1160437760,1160483263,US -1160483264,1160483295,MX -1160483296,1160486911,US +1160437760,1160486911,US 1160486912,1160487423,AU 1160487424,1160503295,US 1160503296,1160503871,A2 @@ -20378,19 +21037,9 @@ 1160925184,1160941535,US 1160941536,1160941567,CA 1160941568,1160945663,US -1160947712,1160948991,US -1160948992,1160949023,CA -1160949024,1160949087,US -1160949120,1160949151,US -1160949168,1160949183,JP -1160949200,1160949215,US -1160949248,1160949535,US -1160949632,1160949759,CY -1160949760,1160973439,US +1160953856,1160973439,US 1160973440,1160973503,MX -1160973504,1160973567,US -1160973568,1160973599,CA -1160973600,1160973863,US +1160973504,1160973863,US 1160973864,1160973871,GR 1160973872,1160974591,US 1160974592,1160974623,HK @@ -20408,7 +21057,9 @@ 1161293824,1161297919,CA 1161297920,1161298303,US 1161298304,1161298311,IL -1161298312,1161304591,US +1161298312,1161300511,US +1161300512,1161300519,CA +1161300520,1161304591,US 1161304592,1161304599,AU 1161304600,1161311743,US 1161311744,1161311759,KN @@ -20471,8 +21122,14 @@ 1161627744,1161627759,US 1161627760,1161627775,GB 1161627776,1161627807,US -1161627808,1161627863,AR -1161627864,1161628479,US +1161627808,1161627823,AR +1161627824,1161627831,AU +1161627832,1161627863,AR +1161627864,1161627871,US +1161627872,1161627879,GB +1161627880,1161627895,US +1161627896,1161627903,AZ +1161627904,1161628479,US 1161628480,1161628487,GB 1161628488,1161628607,US 1161628608,1161628639,AR @@ -20560,7 +21217,7 @@ 1161632664,1161632719,US 1161632720,1161632735,GB 1161632736,1161633023,US -1161633024,1161633055,IL +1161633024,1161633055,CA 1161633056,1161633215,US 1161633216,1161633231,EE 1161633232,1161634063,US @@ -20569,7 +21226,7 @@ 1161634128,1161634135,AR 1161634136,1161634199,US 1161634200,1161634207,NZ -1161634208,1161634239,AR +1161634208,1161634239,US 1161634240,1161634247,GB 1161634248,1161634271,US 1161634272,1161634287,CH @@ -20699,11 +21356,21 @@ 1161650848,1161650863,AR 1161650864,1161650927,US 1161650928,1161650935,HR -1161650936,1161651103,US +1161650936,1161651055,US +1161651056,1161651071,PL +1161651072,1161651103,US 1161651104,1161651135,GB 1161651136,1161651487,US 1161651488,1161651503,GB -1161651504,1161651967,US +1161651504,1161651535,US +1161651536,1161651543,PL +1161651544,1161651551,US +1161651552,1161651559,CA +1161651560,1161651599,US +1161651600,1161651607,AR +1161651608,1161651647,US +1161651648,1161651711,PL +1161651712,1161651967,US 1161651968,1161651975,CH 1161651976,1161652007,US 1161652008,1161652015,GB @@ -20713,7 +21380,9 @@ 1161652128,1161652135,AR 1161652136,1161653023,US 1161653024,1161653055,AR -1161653056,1161653791,US +1161653056,1161653503,US +1161653504,1161653759,CA +1161653760,1161653791,US 1161653792,1161653799,SI 1161653800,1161653831,US 1161653832,1161653839,HR @@ -20736,9 +21405,7 @@ 1161790840,1161790848,CA 1161790849,1161818111,US 1161818112,1161822207,CA -1161822208,1161832671,US -1161832672,1161832703,CL -1161832704,1161832799,US +1161822208,1161832799,US 1161832800,1161832831,ZA 1161832832,1161832863,DE 1161832864,1161833967,US @@ -20749,8 +21416,7 @@ 1161836032,1161836063,CA 1161836064,1161836159,US 1161836160,1161836191,BR -1161836192,1161836255,US -1161836256,1161836287,UA +1161836192,1161836287,US 1161836288,1161836319,RS 1161836320,1161836383,US 1161836384,1161836415,CY @@ -20759,9 +21425,7 @@ 1161836480,1161836511,UA 1161836512,1161837567,US 1161837568,1161837823,JP -1161837824,1161838351,US -1161838352,1161838367,GB -1161838368,1161838548,US +1161837824,1161838548,US 1161838549,1161838560,RU 1161838561,1161841101,US 1161841102,1161841112,DE @@ -20824,8 +21488,8 @@ 1162059776,1162067967,CA 1162067968,1162215423,US 1162215424,1162280959,CA -1162280960,1162296007,US -1162296008,1162296023,CA +1162280960,1162296015,US +1162296016,1162296023,CA 1162296024,1162296407,US 1162296408,1162296415,CA 1162296416,1162297343,US @@ -20887,7 +21551,7 @@ 1162811648,1162812159,US 1162812160,1162812415,DO 1162812416,1162813439,BS -1162813440,1162821631,CO +1162813440,1162821631,US 1162821632,1162823679,PR 1162823680,1162825727,GT 1162825728,1162827775,US @@ -20901,16 +21565,11 @@ 1162870784,1162871295,BB 1162871296,1162874367,LC 1162874368,1162887167,BB -1162903552,1162923391,US -1162923392,1162923519,BE -1162923520,1162924031,US -1162924032,1162924287,AU -1162924288,1162925983,US +1162903552,1162925983,US 1162925984,1162926015,AU 1162926016,1162926071,US 1162926072,1162926079,AU -1162926080,1162932223,US -1162936320,1163395071,US +1162926080,1163395071,US 1163395072,1163395839,A2 1163395840,1163395847,BD 1163395848,1163395855,ID @@ -21350,13 +22009,15 @@ 1163876472,1163876479,PA 1163876480,1163878399,US 1163878400,1163878407,CN -1163878408,1167320679,US -1167320680,1167320687,IN -1167320688,1167321959,US +1163878408,1167321959,US 1167321960,1167321967,GB 1167321968,1167322695,US 1167322696,1167322703,IN -1167322704,1167325935,US +1167322704,1167323799,US +1167323800,1167323807,IN +1167323808,1167323823,US +1167323824,1167323831,IN +1167323832,1167325935,US 1167325936,1167325951,CA 1167325952,1167326207,US 1167326208,1167326271,IN @@ -21367,14 +22028,17 @@ 1167326400,1167326431,IN 1167326432,1167326439,US 1167326440,1167326447,IN -1167326448,1167326463,US -1167326464,1167326719,IN -1167326720,1167693199,US +1167326448,1167326983,US +1167326984,1167326991,IN +1167326992,1167327111,US +1167327112,1167327119,IN +1167327120,1167327207,US +1167327208,1167327215,IN +1167327216,1167693199,US 1167693200,1167693215,UA 1167693216,1167851519,US 1167851520,1168113663,CA -1168113664,1168121855,US -1168130048,1168138239,US +1168113664,1168138239,US 1168138240,1168146431,JM 1168146432,1168211967,US 1168211968,1168220159,CA @@ -21382,30 +22046,29 @@ 1168318720,1168318975,CA 1168318976,1168321535,US 1168321536,1168321791,CA -1168321792,1168330751,US -1168343040,1168393215,US +1168321792,1168393215,US 1168393216,1168394271,CA 1168394272,1168394279,US 1168394280,1168394375,CA 1168394376,1168394383,US -1168394384,1168394407,CA -1168394408,1168394415,US -1168394416,1168394423,CA +1168394384,1168394423,CA 1168394424,1168394463,US 1168394464,1168394471,CA 1168394472,1168394479,US -1168394480,1168394495,CA -1168394496,1168394511,US +1168394480,1168394503,CA +1168394504,1168394511,US 1168394512,1168394527,CA 1168394528,1168394559,US -1168394560,1168394687,CA -1168394688,1168420863,US +1168394560,1168394751,CA +1168394752,1168420863,US 1168420864,1168424959,CA 1168424960,1168474111,US 1168474112,1168506879,CA 1168508928,1168510975,US 1168510976,1168515071,CA -1168515072,1168670719,US +1168515072,1168535551,US +1168535552,1168539647,CA +1168539648,1168670719,US 1168670720,1168687103,CA 1168687104,1168859135,US 1168859136,1168863231,CA @@ -21431,13 +22094,11 @@ 1168952888,1168952895,CA 1168952896,1168952959,US 1168952960,1168953343,CA -1168953344,1168954015,US -1168954016,1168954047,EG -1168954048,1168954075,US +1168953344,1168954075,US 1168954076,1168954079,CA -1168954080,1168955647,US -1168955648,1168956415,CA -1168956416,1168957439,US +1168954080,1168955903,US +1168955904,1168956159,CA +1168956160,1168957439,US 1168957440,1168958047,CA 1168958048,1168958055,DE 1168958056,1168958063,CA @@ -21455,11 +22116,7 @@ 1168958464,1168958479,CA 1168958480,1168958495,US 1168958496,1168958527,FR -1168958528,1168958655,US -1168958656,1168958687,EG -1168958688,1168958719,US -1168958720,1168958975,CA -1168958976,1168960543,US +1168958528,1168960543,US 1168960544,1168960591,CA 1168960592,1168960607,US 1168960608,1168960623,CA @@ -21477,7 +22134,8 @@ 1168961992,1168961999,CA 1168962000,1168962303,US 1168962304,1168962559,CA -1168962560,1168963071,US +1168962560,1168963039,US +1168963040,1168963071,ES 1168963072,1168965631,CA 1168965632,1168973823,US 1168973824,1168982015,CA @@ -21521,8 +22179,13 @@ 1169186048,1169186303,SG 1169186304,1169203199,US 1169203200,1169211391,CA -1169211392,1170448383,US -1170456576,1170461183,US +1169211392,1170456959,US +1170456960,1170456975,CR +1170456976,1170456991,US +1170456992,1170457007,PR +1170457008,1170458063,US +1170458064,1170458079,DE +1170458080,1170461183,US 1170461184,1170461439,CO 1170461440,1170461695,US 1170461696,1170462719,IL @@ -21532,13 +22195,83 @@ 1170489344,1170497535,CA 1170497536,1170505727,US 1170505728,1170522111,CA -1170522112,1170544255,US +1170522112,1170539329,US +1170539330,1170539330,CN +1170539331,1170539393,US +1170539394,1170539394,TR +1170539395,1170539399,US +1170539400,1170539400,TR +1170539401,1170539416,US +1170539417,1170539417,TR +1170539418,1170539463,US +1170539464,1170539464,CN +1170539465,1170539466,US +1170539467,1170539467,IE +1170539468,1170539523,US +1170539524,1170539524,IE +1170539525,1170539586,US +1170539587,1170539587,FR +1170539588,1170539590,US +1170539591,1170539591,CN +1170539592,1170539592,US +1170539593,1170539593,CN +1170539594,1170539652,US +1170539653,1170539653,GB +1170539654,1170539714,US +1170539715,1170539715,PK +1170539716,1170539776,US +1170539777,1170539777,FR +1170539778,1170539778,US +1170539779,1170539779,FR +1170539780,1170539969,US +1170539970,1170539970,KH +1170539971,1170540038,US +1170540039,1170540039,PH +1170540040,1170540097,US +1170540098,1170540098,TR +1170540099,1170540104,US +1170540105,1170540105,PK +1170540106,1170540231,US +1170540232,1170540232,CN +1170540233,1170540289,US +1170540290,1170540290,CN +1170540291,1170544199,US +1170544200,1170544207,TR +1170544208,1170544255,US 1170544256,1170544383,IN -1170544384,1170544639,US +1170544384,1170544387,US +1170544388,1170544391,BD +1170544392,1170544431,US +1170544432,1170544439,CN +1170544440,1170544511,US +1170544512,1170544575,SE +1170544576,1170544639,US 1170544640,1170544767,MY 1170544768,1170547455,US 1170547456,1170547711,CA -1170547712,1175977983,US +1170547712,1170553087,US +1170553088,1170553151,GB +1170553152,1170553215,FR +1170553216,1170553343,PK +1170553344,1170553407,CN +1170553408,1170553431,US +1170553432,1170553435,TR +1170553436,1170553439,CA +1170553440,1170553471,US +1170553472,1170553535,PK +1170553536,1170553599,CN +1170553600,1170553855,US +1170553856,1170553983,MY +1170553984,1170554367,US +1170554368,1170554431,CN +1170554432,1170554463,US +1170554464,1170554479,CN +1170554480,1170554483,TR +1170554484,1170554487,BD +1170554488,1170554495,CN +1170554496,1170554559,US +1170554560,1170554623,CN +1170554624,1175977983,US 1175977984,1176068167,CA 1176068168,1176068175,US 1176068176,1176068191,CA @@ -21556,7 +22289,11 @@ 1176108560,1176502271,CA 1176502272,1176512151,US 1176512152,1176512159,GB -1176512160,1176609535,US +1176512160,1176513879,US +1176513880,1176513887,GB +1176513888,1176514271,US +1176514272,1176514303,IN +1176514304,1176609535,US 1176609536,1176609583,CA 1176609584,1176609599,US 1176609600,1176609615,CA @@ -21587,13 +22324,15 @@ 1176620992,1176620999,US 1176621000,1176621023,CA 1176621024,1176621055,US -1176621056,1176622079,CA -1176622080,1176623103,US -1176623104,1176623359,CA +1176621056,1176623359,CA 1176623360,1176623487,US -1176623488,1176623615,CA +1176623488,1176623567,CA +1176623568,1176623583,US +1176623584,1176623615,CA 1176623616,1176623871,US -1176623872,1176629303,CA +1176623872,1176629287,CA +1176629288,1176629295,US +1176629296,1176629303,CA 1176629304,1176629311,US 1176629312,1176629343,CA 1176629344,1176629375,US @@ -21604,13 +22343,11 @@ 1176629472,1176629503,US 1176629504,1176629519,CA 1176629520,1176629535,NZ -1176629536,1176629695,CA -1176629696,1176629727,US +1176629536,1176629631,CA +1176629632,1176629727,US 1176629728,1176631295,CA 1176631296,1176631551,NL -1176631552,1176631807,US -1176631808,1176632063,CR -1176632064,1176662015,US +1176631552,1176662015,US 1176662016,1176666111,CA 1176666112,1176682527,US 1176682528,1176682535,JM @@ -21638,7 +22375,13 @@ 1176752128,1176756223,CA 1176756224,1176764415,US 1176764416,1176768511,PM -1176768512,1176776703,US +1176768512,1176770751,US +1176770752,1176770783,AE +1176770784,1176770831,US +1176770832,1176770847,BR +1176770848,1176771895,US +1176771896,1176771903,AE +1176771904,1176776703,US 1176776704,1176780799,CA 1176780800,1176895487,US 1176895488,1176896519,CA @@ -21664,11 +22407,11 @@ 1177053696,1177053951,GB 1177053952,1177059327,US 1177059328,1177061375,CA -1177061376,1177063423,US -1177063424,1177067519,CA -1177067520,1177071615,US -1177071616,1177074687,CA -1177074688,1177164255,US +1177061376,1177062399,US +1177062400,1177074943,CA +1177074944,1177075199,US +1177075200,1177075455,CA +1177075456,1177164255,US 1177164256,1177164263,CA 1177164264,1177164415,US 1177164416,1177164479,CA @@ -21678,11 +22421,7 @@ 1177164928,1177164943,CA 1177164944,1177165311,US 1177165312,1177165823,CA -1177165824,1177168127,US -1177168128,1177168143,FR -1177168144,1177169687,US -1177169688,1177169695,GB -1177169696,1177175199,US +1177165824,1177175199,US 1177175200,1177175231,CZ 1177175232,1177182527,US 1177182528,1177182591,CA @@ -21832,7 +22571,9 @@ 1208197520,1208197527,AU 1208197528,1208197559,US 1208197560,1208197567,AU -1208197568,1208197631,US +1208197568,1208197579,US +1208197580,1208197583,GB +1208197584,1208197631,US 1208197632,1208197639,AU 1208197640,1208197671,US 1208197672,1208197679,MX @@ -21848,7 +22589,9 @@ 1208198280,1208198287,ZA 1208198288,1208198303,US 1208198304,1208198319,FR -1208198320,1208198463,US +1208198320,1208198343,US +1208198344,1208198347,GB +1208198348,1208198463,US 1208198464,1208198471,CA 1208198472,1208198559,US 1208198560,1208198575,IN @@ -22087,23 +22830,41 @@ 1208337920,1208338175,A2 1208338176,1208516607,US 1208516608,1208516623,MX -1208516624,1208516671,US +1208516624,1208516639,US +1208516640,1208516671,CN 1208516672,1208516735,TR 1208516736,1208516799,ID 1208516800,1208516855,US 1208516856,1208516859,CN -1208516860,1208518143,US +1208516860,1208517001,US +1208517002,1208517002,CN +1208517003,1208517009,US +1208517010,1208517011,CN +1208517012,1208517017,US +1208517018,1208517018,GB +1208517019,1208517019,US +1208517020,1208517020,FR +1208517021,1208517119,US +1208517120,1208517375,KH +1208517376,1208517631,US +1208517632,1208517887,KH +1208517888,1208518143,US 1208518144,1208518207,MY -1208518208,1208518291,US +1208518208,1208518246,US +1208518247,1208518247,KH +1208518248,1208518263,US +1208518264,1208518264,GB +1208518265,1208518271,US +1208518272,1208518287,GB +1208518288,1208518291,US 1208518292,1208518295,CN -1208518296,1208519167,US +1208518296,1208518335,US +1208518336,1208518399,TR +1208518400,1208519167,US 1208519168,1208519423,CN 1208519424,1208519551,US 1208519552,1208519679,TR -1208519680,1208519935,CA -1208519936,1208521983,US -1208521984,1208522239,CA -1208522240,1208523775,US +1208519680,1208523775,US 1208523776,1208523903,GB 1208523904,1208523991,US 1208523992,1208523995,TR @@ -22114,9 +22875,7 @@ 1208524224,1208524287,US 1208524288,1208524351,PK 1208524352,1208524415,CN -1208524416,1208524563,US -1208524564,1208524567,IT -1208524568,1208525823,US +1208524416,1208525823,US 1208525824,1208526079,CA 1208526080,1208527615,US 1208527616,1208527871,CA @@ -22181,8 +22940,7 @@ 1208587419,1208587426,TR 1208587427,1208587427,US 1208587428,1208587443,GB -1208587444,1208587457,TW -1208587458,1208587479,US +1208587444,1208587479,US 1208587480,1208587487,LK 1208587488,1208587488,US 1208587489,1208587504,GB @@ -22201,9 +22959,7 @@ 1208587738,1208587759,CN 1208587760,1208587873,US 1208587874,1208587881,PK -1208587882,1208587909,US -1208587910,1208587943,UY -1208587944,1208587944,US +1208587882,1208587944,US 1208587945,1208587976,GB 1208587977,1208588071,US 1208588072,1208588079,RU @@ -22215,11 +22971,7 @@ 1208588212,1208588219,CA 1208588220,1208588427,US 1208588428,1208588435,MO -1208588436,1208588437,US -1208588438,1208588445,PK -1208588446,1208588451,US -1208588452,1208588455,EG -1208588456,1208588463,US +1208588436,1208588463,US 1208588464,1208588476,AU 1208588477,1208588591,US 1208588592,1208588599,IN @@ -22227,22 +22979,15 @@ 1208588729,1208588760,GB 1208588761,1208588771,US 1208588772,1208588779,GB -1208588780,1208588819,US -1208588820,1208588839,PK -1208588840,1208588941,US -1208588942,1208588949,MO -1208588950,1208588953,US +1208588780,1208588953,US 1208588954,1208588961,TR 1208588962,1208588972,US 1208588973,1208588985,GB 1208588986,1208588989,US 1208588990,1208589000,GB -1208589001,1208589011,US -1208589012,1208589021,MO -1208589022,1208589065,US -1208589066,1208589073,CA -1208589074,1208589082,GB -1208589083,1208589156,US +1208589001,1208589065,US +1208589066,1208589081,CA +1208589082,1208589156,US 1208589157,1208589165,GB 1208589166,1208589174,US 1208589175,1208589186,CA @@ -22262,16 +23007,12 @@ 1208589971,1208590002,GB 1208590003,1208590004,US 1208590005,1208590014,GB -1208590015,1208590045,US -1208590046,1208590053,SA -1208590054,1208590061,US +1208590015,1208590061,US 1208590062,1208590071,CN 1208590072,1208590091,US 1208590092,1208590108,GB 1208590109,1208590115,US -1208590116,1208590119,EG -1208590120,1208590120,US -1208590121,1208590123,EG +1208590116,1208590123,EG 1208590124,1208590140,US 1208590141,1208590154,CA 1208590155,1208590157,US @@ -22285,25 +23026,16 @@ 1208590266,1208590335,US 1208590336,1208598527,CA 1208598528,1208647679,US -1208647680,1208656159,CA -1208656160,1208656191,US -1208656192,1208656223,CA -1208656224,1208656255,US -1208656256,1208656319,CA +1208647680,1208656319,CA 1208656320,1208656351,US -1208656352,1208656383,CA -1208656384,1208656511,ID +1208656352,1208656511,CA 1208656512,1208656543,US 1208656544,1208656575,CA 1208656576,1208656583,DO 1208656584,1208656591,PA -1208656592,1208656599,RS -1208656600,1208656607,UA -1208656608,1208656639,US +1208656592,1208656639,CA 1208656640,1208656703,MY -1208656704,1208656711,UA -1208656712,1208656735,CA -1208656736,1208656767,US +1208656704,1208656767,CA 1208656768,1208656895,MY 1208656896,1208656903,CA 1208656904,1208656911,LB @@ -22324,24 +23056,18 @@ 1208657720,1208657727,CH 1208657728,1208657775,CA 1208657776,1208657783,PA -1208657784,1208657823,CA -1208657824,1208657831,DO -1208657832,1208657855,CA +1208657784,1208657855,CA 1208657856,1208657871,PA 1208657872,1208657919,CA 1208657920,1208657975,MA 1208657976,1208657983,CA 1208657984,1208657991,CN 1208657992,1208658015,MA -1208658016,1208658023,CA -1208658024,1208658031,DO +1208658016,1208658031,CA 1208658032,1208658039,MA -1208658040,1208658047,CA -1208658048,1208658079,US -1208658080,1208658103,CA +1208658040,1208658103,CA 1208658104,1208658111,FR -1208658112,1208658119,DO -1208658120,1208658127,CA +1208658112,1208658127,CA 1208658128,1208658143,MA 1208658144,1208658159,CA 1208658160,1208658167,MA @@ -22349,29 +23075,23 @@ 1208658176,1208658199,MA 1208658200,1208658223,CA 1208658224,1208658239,MA -1208658240,1208658247,CY -1208658248,1208658263,CA +1208658240,1208658263,CA 1208658264,1208658271,KE 1208658272,1208658279,IL 1208658280,1208658303,CA 1208658304,1208658335,US 1208658336,1208658343,KE -1208658344,1208658351,CA -1208658352,1208658367,US -1208658368,1208658431,CA -1208658432,1208658767,US +1208658344,1208658431,CA +1208658432,1208658687,US +1208658688,1208658767,CA 1208658768,1208658775,MA -1208658776,1208658783,UA -1208658784,1208658799,CA +1208658776,1208658799,CA 1208658800,1208658807,KE -1208658808,1208658815,RS -1208658816,1208658847,CA +1208658808,1208658847,CA 1208658848,1208658855,MA 1208658856,1208658879,CA 1208658880,1208658887,DO -1208658888,1208658895,GB -1208658896,1208659103,CA -1208659104,1208659135,US +1208658888,1208659135,CA 1208659136,1208659151,CN 1208659152,1208659167,CA 1208659168,1208659199,AE @@ -22390,9 +23110,7 @@ 1208659744,1208659775,ID 1208659776,1208659791,CA 1208659792,1208659799,US -1208659800,1208659815,CA -1208659816,1208659823,UA -1208659824,1208659831,CA +1208659800,1208659831,CA 1208659832,1208659839,ID 1208659840,1208659903,PK 1208659904,1208721407,US @@ -22408,13 +23126,14 @@ 1208814720,1208814855,US 1208814856,1208814863,CA 1208814864,1208832455,US -1208832456,1208832463,CA +1208832456,1208832463,CN 1208832464,1208832567,US 1208832568,1208832575,CN -1208832576,1208832607,US +1208832576,1208832599,US +1208832600,1208832607,CN 1208832608,1208832623,IT 1208832624,1208832631,NZ -1208832632,1208832639,US +1208832632,1208832639,HK 1208832640,1208832703,IN 1208832704,1208832775,US 1208832776,1208832783,CA @@ -22429,8 +23148,8 @@ 1208920008,1208920015,US 1208920016,1208922111,CA 1208922112,1208954879,US -1208954880,1208958463,CA -1208958464,1208975359,US +1208954880,1208958975,CA +1208958976,1208975359,US 1208975360,1208980191,CA 1208980192,1208980223,US 1208980224,1208980503,CA @@ -22442,15 +23161,9 @@ 1208995456,1208995471,CA 1208995472,1209004863,US 1209004864,1209004927,GB -1209004928,1209189308,US -1209189309,1209189310,ES -1209189311,1209189342,US -1209189343,1209189374,ES -1209189375,1209189379,US +1209004928,1209189379,US 1209189380,1209189395,MX -1209189396,1209189631,US -1209189632,1209189887,MX -1209189888,1209190147,US +1209189396,1209190147,US 1209190148,1209190163,MX 1209190164,1209190167,US 1209190168,1209190195,GR @@ -22458,52 +23171,99 @@ 1209190852,1209190883,CA 1209190884,1209190911,US 1209190912,1209191167,MX -1209191168,1209270579,US +1209191168,1209270543,US +1209270544,1209270547,CN +1209270548,1209270579,US 1209270580,1209270583,ID 1209270584,1209270759,US -1209270760,1209270767,CA -1209270768,1209270859,US +1209270760,1209270763,CA +1209270764,1209270859,US 1209270860,1209270863,CA -1209270864,1209270919,US -1209270920,1209270923,CA -1209270924,1209271067,US +1209270864,1209271067,US 1209271068,1209271071,VN -1209271072,1209271095,US -1209271096,1209271099,CA -1209271100,1209271111,US +1209271072,1209271111,US 1209271112,1209271115,CA -1209271116,1209271435,US +1209271116,1209271207,US +1209271208,1209271211,FR +1209271212,1209271371,US +1209271372,1209271375,PE +1209271376,1209271435,US 1209271436,1209271439,CN 1209271440,1209271463,US 1209271464,1209271467,IN 1209271468,1209271491,US 1209271492,1209271499,CA 1209271500,1209271503,MX -1209271504,1209271507,TR -1209271508,1209271527,US +1209271504,1209271527,US 1209271528,1209271531,CA 1209271532,1209271579,US 1209271580,1209271583,BD -1209271584,1209271691,US +1209271584,1209271607,US +1209271608,1209271611,KH +1209271612,1209271639,US +1209271640,1209271643,CZ +1209271644,1209271691,US 1209271692,1209271695,CA -1209271696,1209271827,US -1209271828,1209271831,CA -1209271832,1209271871,US +1209271696,1209271791,US +1209271792,1209271795,GB +1209271796,1209271871,US 1209271872,1209271875,TR 1209271876,1209271967,US 1209271968,1209271971,VN 1209271972,1209271975,TR -1209271976,1209272003,US -1209272004,1209272007,GB -1209272008,1209272035,US -1209272036,1209272039,IT -1209272040,1209273663,US +1209271976,1209271995,US +1209271996,1209271999,FR +1209272000,1209272015,US +1209272016,1209272019,GB +1209272020,1209272031,US +1209272032,1209272035,GB +1209272036,1209272407,US +1209272408,1209272415,PE +1209272416,1209272447,US +1209272448,1209272479,KH +1209272480,1209272511,US +1209272512,1209272575,CN +1209272576,1209272583,US +1209272584,1209272591,PH +1209272592,1209272655,US +1209272656,1209272671,TR +1209272672,1209272895,US +1209272896,1209272959,CN +1209272960,1209273215,US +1209273216,1209273279,CN +1209273280,1209273647,US +1209273648,1209273655,CN +1209273656,1209273663,US 1209273664,1209273671,BD -1209273672,1209274623,US -1209274624,1209274751,CA +1209273672,1209273991,US +1209273992,1209273999,FR +1209274000,1209274031,US +1209274032,1209274039,TR +1209274040,1209274115,US +1209274116,1209274119,CZ +1209274120,1209274135,US +1209274136,1209274151,TR +1209274152,1209274175,US +1209274176,1209274239,FR +1209274240,1209274303,US +1209274304,1209274367,CN +1209274368,1209274607,US +1209274608,1209274623,FR +1209274624,1209274751,CN 1209274752,1209274815,US 1209274816,1209274879,CA -1209274880,1209275910,US +1209274880,1209274911,CZ +1209274912,1209274927,US +1209274928,1209274943,TR +1209274944,1209274959,US +1209274960,1209274967,PH +1209274968,1209275071,US +1209275072,1209275135,GB +1209275136,1209275863,US +1209275864,1209275871,FR +1209275872,1209275906,US +1209275907,1209275908,KH +1209275909,1209275910,US 1209275911,1209275911,MY 1209275912,1209275924,US 1209275925,1209275925,CN @@ -22513,44 +23273,76 @@ 1209275932,1209275932,CN 1209275933,1209276351,US 1209276352,1209276415,CN -1209276416,1209276511,US -1209276512,1209276543,VN -1209276544,1209276799,US +1209276416,1209276799,US 1209276800,1209276807,BD -1209276808,1209277183,US -1209277184,1209277215,BD -1209277216,1209277575,US +1209276808,1209276815,FR +1209276816,1209276911,US +1209276912,1209276927,TR +1209276928,1209277087,US +1209277088,1209277095,FR +1209277096,1209277103,US +1209277104,1209277119,TR +1209277120,1209277135,US +1209277136,1209277143,FR +1209277144,1209277155,US +1209277156,1209277156,SE +1209277157,1209277177,US +1209277178,1209277178,FR +1209277179,1209277575,US 1209277576,1209277583,BD -1209277584,1209278911,US +1209277584,1209278207,US +1209278208,1209278463,IE +1209278464,1209278911,US 1209278912,1209278919,TR 1209278920,1209279167,US 1209279168,1209279231,VN -1209279232,1209279871,US +1209279232,1209279615,US +1209279616,1209279743,GB +1209279744,1209279871,US 1209279872,1209279935,MY 1209279936,1209280191,US 1209280192,1209280255,VN -1209280256,1209280975,US -1209280976,1209280983,IT -1209280984,1209281247,US +1209280256,1209280575,US +1209280576,1209280607,FR +1209280608,1209280619,US +1209280620,1209280623,GB +1209280624,1209280959,US +1209280960,1209280975,GB +1209280976,1209281247,US 1209281248,1209281279,CA -1209281280,1209281983,US +1209281280,1209281535,KH +1209281536,1209281983,US 1209281984,1209282047,TR -1209282048,1209283587,US +1209282048,1209282583,US +1209282584,1209282591,GB +1209282592,1209283479,US +1209283480,1209283487,GB +1209283488,1209283535,US +1209283536,1209283543,GB +1209283544,1209283587,US 1209283588,1209283591,CN -1209283592,1209283751,US +1209283592,1209283695,US +1209283696,1209283703,GB +1209283704,1209283751,US 1209283752,1209283759,BD 1209283760,1209283871,US 1209283872,1209283875,TR 1209283876,1209283967,US 1209283968,1209284095,GB -1209284096,1209284799,US +1209284096,1209284223,US +1209284224,1209284351,IE +1209284352,1209284759,US +1209284760,1209284767,FR +1209284768,1209284799,US 1209284800,1209284815,TR 1209284816,1209284831,CN 1209284832,1209284855,US 1209284856,1209284863,TR 1209284864,1209285063,US 1209285064,1209285071,TR -1209285072,1209347839,US +1209285072,1209285183,US +1209285184,1209285247,TR +1209285248,1209347839,US 1209347840,1209348095,GB 1209348096,1209357215,US 1209357216,1209357231,SI @@ -22579,7 +23371,9 @@ 1209860576,1209860607,IN 1209860608,1209860863,US 1209860864,1209860895,CY -1209860896,1209861119,US +1209860896,1209860927,US +1209860928,1209860959,AU +1209860960,1209861119,US 1209861120,1209861375,CA 1209861376,1209861759,US 1209861760,1209861887,FR @@ -22612,7 +23406,11 @@ 1209867200,1209867231,IN 1209867232,1209867263,US 1209867264,1209867519,CA -1209867520,1209884671,US +1209867520,1209877934,US +1209877935,1209877938,PK +1209877939,1209879554,US +1209879555,1209879558,PE +1209879559,1209884671,US 1209884672,1209884679,IT 1209884680,1209884687,ES 1209884688,1209884823,US @@ -22894,7 +23692,9 @@ 1210088960,1210088967,GB 1210088968,1210089047,US 1210089048,1210089055,MX -1210089056,1210089823,US +1210089056,1210089375,US +1210089376,1210089383,CA +1210089384,1210089823,US 1210089824,1210089855,CA 1210089856,1210090071,US 1210090072,1210090079,MX @@ -23268,8 +24068,8 @@ 1210418208,1210427039,US 1210427040,1210427071,JP 1210427072,1210449919,US -1210449920,1210468743,CA -1210468744,1210468767,US +1210449920,1210468751,CA +1210468752,1210468767,US 1210468768,1210580991,CA 1210580992,1210861207,US 1210861208,1210861215,GB @@ -23300,14 +24100,11 @@ 1211036032,1211036095,EC 1211036096,1211036703,US 1211036704,1211036719,BO -1211036720,1211036727,US -1211036728,1211036735,JM +1211036720,1211036735,US 1211036736,1211036751,GT 1211036752,1211036991,US 1211036992,1211037055,BR -1211037056,1211037455,US -1211037456,1211037471,CR -1211037472,1211037519,US +1211037056,1211037519,US 1211037520,1211037535,UY 1211037536,1211037679,US 1211037680,1211037695,AR @@ -23336,8 +24133,8 @@ 1211304320,1211304351,NL 1211304352,1211304703,CA 1211304704,1211304767,GB -1211304768,1211304799,US -1211304800,1211304959,CA +1211304768,1211304831,US +1211304832,1211304959,CA 1211304960,1211305983,US 1211305984,1211306111,NL 1211306112,1211306751,US @@ -23357,10 +24154,18 @@ 1211308704,1211308719,VG 1211308720,1211308735,CA 1211308736,1211308751,BV -1211308752,1211309055,CA +1211308752,1211308767,CA +1211308768,1211308783,US +1211308784,1211309055,CA 1211309056,1211309311,US 1211309312,1211310079,CA -1211310080,1211314383,US +1211310080,1211313219,US +1211313220,1211313231,IN +1211313232,1211313431,US +1211313432,1211313439,IN +1211313440,1211313567,US +1211313568,1211313579,IN +1211313580,1211314383,US 1211314384,1211314399,CA 1211314400,1211314415,US 1211314416,1211314423,CA @@ -23368,9 +24173,7 @@ 1211314640,1211314671,CA 1211314672,1211314863,US 1211314864,1211314879,CA -1211314880,1211315711,US -1211315712,1211316223,CA -1211316224,1211316479,US +1211314880,1211316479,US 1211316480,1211316991,CA 1211316992,1211317503,US 1211317504,1211317759,CA @@ -23391,9 +24194,9 @@ 1211367504,1211367519,CH 1211367520,1211367615,US 1211367616,1211367679,GB -1211367680,1211367935,GI +1211367680,1211367935,US 1211367936,1211368191,CA -1211368192,1211368447,CY +1211368192,1211368447,EE 1211368448,1211384279,US 1211384280,1211384287,GB 1211384288,1211387983,US @@ -23446,9 +24249,7 @@ 1219256320,1219264511,CA 1219264512,1219272703,US 1219272704,1219276799,CA -1219276800,1219290047,US -1219290048,1219290063,CA -1219290064,1219290623,US +1219276800,1219290623,US 1219290624,1219290751,AU 1219290752,1219295295,US 1219295296,1219295359,GR @@ -23486,12 +24287,9 @@ 1224278600,1224278607,AU 1224278608,1224278815,US 1224278816,1224278823,CH -1224278824,1224285695,US -1224285696,1224286207,GB -1224286208,1224286719,US +1224278824,1224286719,US 1224286720,1224286975,CA -1224286976,1224290303,US -1224290304,1224290815,GB +1224286976,1224290815,US 1224290816,1224291071,CA 1224291072,1224292095,US 1224292096,1224292351,CA @@ -23503,9 +24301,7 @@ 1224299520,1224299775,CA 1224299776,1224303359,US 1224303360,1224303367,CA -1224303368,1224305151,US -1224305152,1224305663,GB -1224305664,1224311063,US +1224303368,1224311063,US 1224311064,1224311071,MX 1224311072,1224311247,US 1224311248,1224311255,CA @@ -23522,8 +24318,7 @@ 1224317440,1224317695,CA 1224317696,1224318207,US 1224318208,1224318463,CA -1224318464,1224320511,US -1224320512,1224321023,GB +1224318464,1224321023,US 1224321024,1224321535,CA 1224321536,1224322559,US 1224322560,1224323071,GB @@ -23553,9 +24348,7 @@ 1242300416,1242562559,CA 1242562560,1244659711,US 1244659712,1244790783,CA -1244790784,1244821247,US -1244821248,1244821375,CA -1244821376,1244831743,US +1244790784,1244831743,US 1244831744,1244839935,CA 1244839936,1244848127,US 1244848128,1244852223,CA @@ -23567,12 +24360,8 @@ 1246864900,1246864958,EG 1246864959,1246872069,US 1246872070,1246872081,GB -1246872082,1246873461,US -1246873462,1246873469,CA -1246873470,1246873491,US -1246873492,1246873501,GR -1246873502,1246874112,US -1246874113,1246874216,GB +1246872082,1246874127,US +1246874128,1246874216,GB 1246874217,1246874290,US 1246874291,1246874304,CA 1246874305,1246874368,US @@ -23587,9 +24376,10 @@ 1246902784,1246903039,NL 1246903040,1246937087,US 1246937088,1246945279,CA -1246945280,1246949375,US -1246953472,1247027199,US -1247027200,1247035391,A2 +1246945280,1247027199,US +1247027200,1247034559,A2 +1247034560,1247034575,US +1247034576,1247035391,A2 1247035392,1247069303,US 1247069304,1247069311,VA 1247069312,1247070815,US @@ -23622,7 +24412,25 @@ 1249010688,1249011711,CA 1249011712,1249019903,US 1249019904,1249020927,CA -1249020928,1249029119,US +1249020928,1249027175,US +1249027176,1249027183,IN +1249027184,1249027391,US +1249027392,1249027407,PH +1249027408,1249027455,US +1249027456,1249027471,CA +1249027472,1249027503,US +1249027504,1249027519,CA +1249027520,1249027551,US +1249027552,1249027559,CA +1249027560,1249027647,US +1249027648,1249027655,AU +1249027656,1249027823,US +1249027824,1249027839,CA +1249027840,1249027887,US +1249027888,1249027895,EG +1249027896,1249027919,US +1249027920,1249027935,AU +1249027936,1249029119,US 1249029120,1249030143,CA 1249030144,1249036287,US 1249036288,1249037311,TC @@ -23639,7 +24447,42 @@ 1249099776,1249101823,CA 1249101824,1249102847,PR 1249102848,1249103871,CA -1249103872,1249106943,US +1249103872,1249103887,TW +1249103888,1249103903,PH +1249103904,1249103951,US +1249103952,1249103967,TW +1249103968,1249104095,US +1249104096,1249104111,TW +1249104112,1249104127,US +1249104128,1249104191,GB +1249104192,1249104255,US +1249104256,1249104319,GB +1249104320,1249104351,US +1249104352,1249104367,AU +1249104368,1249104383,US +1249104384,1249104447,GB +1249104448,1249104511,US +1249104512,1249104543,GB +1249104544,1249104551,ES +1249104552,1249104575,US +1249104576,1249104607,ES +1249104608,1249104895,US +1249104896,1249104959,GB +1249104960,1249105119,US +1249105120,1249105127,AR +1249105128,1249105135,US +1249105136,1249105143,CH +1249105144,1249105183,US +1249105184,1249105191,ZA +1249105192,1249105215,US +1249105216,1249105279,GB +1249105280,1249105295,CA +1249105296,1249105367,US +1249105368,1249105375,ES +1249105376,1249105535,US +1249105536,1249105567,ES +1249105568,1249105599,CA +1249105600,1249106943,US 1249106944,1249107967,CA 1249107968,1249130495,US 1249130496,1249131519,JM @@ -23652,7 +24495,11 @@ 1249171456,1249173503,CA 1249173504,1249179831,US 1249179832,1249179839,CA -1249179840,1249191935,US +1249179840,1249179967,US +1249179968,1249179983,SE +1249179984,1249180031,US +1249180032,1249180095,TW +1249180096,1249191935,US 1249191936,1249193983,CA 1249193984,1249203199,US 1249203200,1249204223,GD @@ -23660,7 +24507,9 @@ 1249210368,1249212415,KY 1249212416,1249217535,US 1249217536,1249218559,CA -1249218560,1249236991,US +1249218560,1249221887,US +1249221888,1249222655,RO +1249222656,1249236991,US 1249236992,1249239039,KY 1249239040,1249245183,US 1249245184,1249247231,CA @@ -23692,7 +24541,9 @@ 1249474560,1249475583,CA 1249475584,1249484799,US 1249484800,1249486847,CA -1249486848,1249506303,US +1249486848,1249492735,US +1249492736,1249492991,CA +1249492992,1249506303,US 1249506304,1249507327,CA 1249507328,1249522687,US 1249522688,1249523711,CA @@ -23702,7 +24553,9 @@ 1249542144,1249544191,CA 1249544192,1249562623,US 1249562624,1249564671,CA -1249564672,1249571839,US +1249564672,1249568319,US +1249568320,1249568327,NL +1249568328,1249571839,US 1249571840,1249572863,CA 1249572864,1249577087,US 1249577088,1249577983,CA @@ -23726,9 +24579,15 @@ 1249796096,1249804287,CA 1249804288,1249838847,US 1249838848,1249838911,IN -1249838912,1249839423,US +1249838912,1249838975,US +1249838976,1249839039,IN +1249839040,1249839423,US 1249839424,1249839487,VE -1249839488,1249845311,US +1249839488,1249843231,US +1249843232,1249843247,IN +1249843248,1249843423,US +1249843424,1249843439,IN +1249843440,1249845311,US 1249845312,1249845327,IN 1249845328,1249845343,US 1249845344,1249845375,IN @@ -24309,8 +25168,8 @@ 1255007488,1255007711,CA 1255007712,1255011343,US 1255011344,1255011359,CA -1255011360,1255011367,US -1255011368,1255011551,CA +1255011360,1255011375,US +1255011376,1255011551,CA 1255011552,1255011559,US 1255011560,1255011839,CA 1255011840,1255039631,US @@ -24329,8 +25188,7 @@ 1255058672,1255058687,GB 1255058688,1255059151,US 1255059152,1255059167,GB -1255059168,1255059199,BS -1255059200,1255059327,US +1255059168,1255059327,US 1255059328,1255059343,NL 1255059344,1255059359,US 1255059360,1255059407,CA @@ -24357,19 +25215,15 @@ 1255062848,1255062863,CA 1255062864,1255063551,US 1255063552,1255071743,PR -1255071744,1255193599,US -1255193600,1255194623,GB -1255194624,1255210495,US +1255071744,1255210495,US 1255210496,1255211007,DE 1255211008,1255276543,US 1255276544,1255342079,CA 1255342080,1255369055,US 1255369056,1255369087,DE -1255369088,1255372287,US -1255372288,1255372543,CA -1255372544,1255373823,US -1255373824,1255374079,CA -1255374080,1255489535,US +1255369088,1255373759,US +1255373760,1255373791,DE +1255373792,1255489535,US 1255489536,1255505919,PR 1255505920,1255514111,US 1255514112,1255522303,CA @@ -24383,9 +25237,9 @@ 1255753216,1255753471,GB 1255753472,1255768063,US 1255768064,1255768575,CA -1255768576,1255771135,US -1255771136,1255772159,CA -1255772160,1255780351,US +1255768576,1255770367,US +1255770368,1255770623,CA +1255770624,1255780351,US 1255780352,1255782399,CA 1255782400,1255796743,US 1255796744,1255796751,GB @@ -24395,28 +25249,26 @@ 1256001536,1256005631,CA 1256005632,1256057975,US 1256057976,1256057983,BZ -1256057984,1256079359,US +1256057984,1256057999,US +1256058000,1256058007,CA +1256058008,1256058719,US +1256058720,1256058727,CA +1256058728,1256079359,US 1256079360,1256087551,KY -1256087552,1256098303,US -1256098304,1256098339,CA -1256098340,1256098343,US -1256098344,1256098815,CA +1256087552,1256098559,US +1256098560,1256098815,CA 1256098816,1263264273,US 1263264274,1263264289,PK -1263264290,1263264305,CA +1263264290,1263264305,US 1263264306,1263264354,PK -1263264355,1263264386,US -1263264387,1263264450,CA -1263264451,1263264767,US -1263264768,1263265023,CA -1263265024,1263266559,US -1263266560,1263266815,CA -1263266816,1263267327,US +1263264355,1263266623,US +1263266624,1263266655,CA +1263266656,1263267327,US 1263267328,1263267583,CA 1263267584,1263267647,US 1263267648,1263267679,CA -1263267680,1263268095,US -1263268096,1263268191,CA +1263267680,1263267839,US +1263267840,1263268191,CA 1263268192,1263268275,US 1263268276,1263268340,CA 1263268341,1263268343,US @@ -24425,20 +25277,15 @@ 1263268608,1263268672,CA 1263268673,1263268769,US 1263268770,1263268863,CA -1263268864,1263269119,US -1263269120,1263269631,CA -1263269632,1263270143,US -1263270144,1263270911,CA -1263270912,1263271423,US +1263268864,1263271423,US 1263271424,1263271679,CA 1263271680,1264717823,US 1264717824,1264718335,CA 1264718336,1264736255,US 1264736256,1264737279,DO -1264737280,1264738303,US -1264779264,1264980223,US -1264980224,1264980479,HK -1264980480,1264980735,US +1264737280,1264762879,US +1264762880,1264766975,CA +1264766976,1264980735,US 1264980736,1264980743,CA 1264980744,1266107759,US 1266107760,1266107775,UM @@ -24456,7 +25303,23 @@ 1268252672,1268776959,CA 1268776960,1275600895,US 1275600896,1275604991,BM -1275604992,1275621375,US +1275604992,1275605263,US +1275605264,1275605279,PL +1275605280,1275605567,US +1275605568,1275605583,PL +1275605584,1275605823,US +1275605824,1275605839,PL +1275605840,1275606207,US +1275606208,1275606223,PL +1275606224,1275606367,US +1275606368,1275606383,PL +1275606384,1275606975,US +1275606976,1275606991,PL +1275606992,1275607071,US +1275607072,1275607087,PL +1275607088,1275607407,US +1275607408,1275607423,PL +1275607424,1275621375,US 1275621376,1275625471,CA 1275625472,1275658239,US 1275658240,1275658495,GB @@ -24854,7 +25717,29 @@ 1279956312,1279956351,CA 1279956352,1279956455,US 1279956456,1279956463,PA -1279956464,1279959551,US +1279956464,1279956998,US +1279956999,1279957007,IN +1279957008,1279957119,US +1279957120,1279957128,IN +1279957129,1279957135,US +1279957136,1279957151,IN +1279957152,1279957231,US +1279957232,1279957243,IN +1279957244,1279957375,US +1279957376,1279957383,IN +1279957384,1279957407,US +1279957408,1279957427,IN +1279957428,1279957431,US +1279957432,1279957439,IN +1279957440,1279957631,US +1279957632,1279957651,IN +1279957652,1279957655,US +1279957656,1279957674,IN +1279957675,1279958020,US +1279958021,1279958030,IN +1279958031,1279958399,US +1279958400,1279958495,IN +1279958496,1279959551,US 1279959552,1279959807,CA 1279959808,1279960063,US 1279960064,1279960127,CA @@ -24903,8 +25788,8 @@ 1279975264,1279975295,EG 1279975296,1279975407,US 1279975408,1279975423,NZ -1279975424,1279975679,CA -1279975680,1279975959,US +1279975424,1279975695,CA +1279975696,1279975959,US 1279975960,1279975967,CA 1279975968,1279975975,HK 1279975976,1279975983,US @@ -24921,7 +25806,19 @@ 1279978272,1279978303,US 1279978304,1279978367,CA 1279978368,1279978495,VG -1279978496,1279979559,US +1279978496,1279978683,US +1279978684,1279978692,IN +1279978693,1279978693,US +1279978694,1279978702,IN +1279978703,1279978891,US +1279978892,1279978899,IN +1279978900,1279978927,US +1279978928,1279978939,IN +1279978940,1279979007,US +1279979008,1279979263,IN +1279979264,1279979327,US +1279979328,1279979391,IN +1279979392,1279979559,US 1279979560,1279979575,CA 1279979576,1279979583,US 1279979584,1279980063,CA @@ -24930,7 +25827,17 @@ 1279980080,1279980127,CA 1279980128,1279980135,US 1279980136,1279981567,CA -1279981568,1279999999,US +1279981568,1279981823,US +1279981824,1279981855,VG +1279981856,1279982778,US +1279982779,1279982788,IN +1279982789,1279983047,US +1279983048,1279983072,IN +1279983073,1279983079,US +1279983080,1279983087,IN +1279983088,1279983519,US +1279983520,1279983532,IN +1279983533,1279999999,US 1280000000,1280032767,CA 1280032768,1280040959,US 1280040960,1280043527,CA @@ -25059,193 +25966,8 @@ 1280049072,1280049095,CA 1280049096,1280049127,US 1280049128,1280049151,CA -1280049152,1280073735,US -1280073736,1280073743,DE -1280073744,1280073759,US -1280073760,1280073767,CA -1280073768,1280073775,US -1280073776,1280073791,CA -1280073792,1280073799,CR -1280073800,1280073807,US -1280073808,1280073815,MY -1280073816,1280073823,CA -1280073824,1280073831,US -1280073832,1280073847,CA -1280073848,1280073855,LT -1280073856,1280073863,UA -1280073864,1280073879,US -1280073880,1280073887,CA -1280073888,1280073895,RU -1280073896,1280073903,US -1280073904,1280073911,CA -1280073912,1280073919,NL -1280073920,1280073935,CA -1280073936,1280073943,US -1280073944,1280073951,ZA -1280073952,1280073959,CR -1280073960,1280073967,FR -1280073968,1280073975,US -1280073976,1280073983,CA -1280073984,1280073999,US -1280074000,1280074007,BR -1280074008,1280074023,US -1280074024,1280074039,CA -1280074040,1280074047,US -1280074048,1280074055,HU -1280074056,1280074071,US -1280074072,1280074087,CA -1280074088,1280074095,US -1280074096,1280074103,IL -1280074104,1280074127,US -1280074128,1280074135,CA -1280074136,1280074143,CN -1280074144,1280074151,GB -1280074152,1280074159,CA -1280074160,1280074175,US -1280074176,1280074183,CA -1280074184,1280074199,US -1280074200,1280074207,MY -1280074208,1280074215,DE -1280074216,1280074223,US -1280074224,1280074231,CA -1280074232,1280074239,SG -1280074240,1280074247,GB -1280074248,1280074255,US -1280074256,1280074263,DE -1280074264,1280074271,FR -1280074272,1280074279,CA -1280074280,1280074287,US -1280074288,1280074295,CA -1280074296,1280074303,US -1280074304,1280074311,CA -1280074312,1280074319,RU -1280074320,1280074327,US -1280074328,1280074359,CA -1280074360,1280074375,US -1280074376,1280074383,CA -1280074384,1280074391,PA -1280074392,1280074399,US -1280074400,1280074415,CA -1280074416,1280074423,JP -1280074424,1280074431,CA -1280074432,1280074439,US -1280074440,1280074455,CA -1280074456,1280074463,US -1280074464,1280074479,CA -1280074480,1280074487,AU -1280074488,1280074495,PA -1280074496,1280074511,US -1280074512,1280074519,MY -1280074520,1280074527,CA -1280074528,1280074567,US -1280074568,1280074575,CA -1280074576,1280074583,NL -1280074584,1280074599,US -1280074600,1280074607,CA -1280074608,1280074615,US -1280074616,1280074623,CA -1280074624,1280074631,VG -1280074632,1280074639,CA -1280074640,1280074655,US -1280074656,1280074663,AU -1280074664,1280074671,CA -1280074672,1280074687,US -1280074688,1280074695,FR -1280074696,1280074703,CA -1280074704,1280074711,MY -1280074712,1280074719,CA -1280074720,1280074735,US -1280074736,1280074751,CA -1280074752,1280074759,US -1280074760,1280074767,RO -1280074768,1280074775,CA -1280074776,1280074783,AE -1280074784,1280074791,AU -1280074792,1280074799,US -1280074800,1280074807,NL -1280074808,1280074815,GB -1280074816,1280074823,CA -1280074824,1280074831,FR -1280074832,1280074839,IL -1280074840,1280074847,CO -1280074848,1280074855,IT -1280074856,1280074871,CA -1280074872,1280074887,US -1280074888,1280074895,CA -1280074896,1280074911,US -1280074912,1280074919,CA -1280074920,1280074935,US -1280074936,1280074943,GB -1280074944,1280074959,CA -1280074960,1280074967,US -1280074968,1280074975,CA -1280074976,1280074999,US -1280075000,1280075007,GI -1280075008,1280075015,US -1280075016,1280075039,CA -1280075040,1280075047,IE -1280075048,1280075055,NL -1280075056,1280075063,RU -1280075064,1280075071,IT -1280075072,1280075087,CA -1280075088,1280075095,US -1280075096,1280075103,CL -1280075104,1280075119,US -1280075120,1280075127,CA -1280075128,1280075135,MY -1280075136,1280075143,CA -1280075144,1280075151,US -1280075152,1280075159,MY -1280075160,1280075167,US -1280075168,1280075175,MY -1280075176,1280075183,CA -1280075184,1280075191,US -1280075192,1280075231,CA -1280075232,1280075239,NL -1280075240,1280075271,US -1280075272,1280075295,CA -1280075296,1280075303,US -1280075304,1280075327,CA -1280075328,1280075343,US -1280075344,1280075351,CA -1280075352,1280075359,MY -1280075360,1280075367,US -1280075368,1280075375,CA -1280075376,1280075383,US -1280075384,1280075391,CA -1280075392,1280075415,MY -1280075416,1280075423,US -1280075424,1280075439,CA -1280075440,1280075471,US -1280075472,1280075487,CA -1280075488,1280075495,CR -1280075496,1280075503,GB -1280075504,1280075511,CA -1280075512,1280075519,CN -1280075520,1280075527,PH -1280075528,1280075535,CA -1280075536,1280075543,IT -1280075544,1280075551,ZA -1280075552,1280075559,TR -1280075560,1280075567,AE -1280075568,1280075575,US -1280075576,1280075583,CA -1280075584,1280075615,US -1280075616,1280075623,GB -1280075624,1280075655,CA -1280075656,1280075679,US -1280075680,1280075687,MY -1280075688,1280075719,CA -1280075720,1280075727,US -1280075728,1280075759,CA -1280075760,1280075767,US -1280075768,1280075775,GB -1280075776,1280075783,US -1280075784,1280078711,CA -1280078712,1280078719,US -1280078720,1280078743,CA -1280078744,1280078751,US -1280078752,1280081919,CA +1280049152,1280073727,US +1280073728,1280081919,CA 1280081920,1280090111,US 1280090112,1280091135,AI 1280091136,1280092159,VG @@ -25257,9 +25979,11 @@ 1280097280,1280097791,LC 1280097792,1280098303,AG 1280098304,1280102399,PR -1280102400,1280131071,US +1280102400,1280122879,US 1280131072,1280139263,CA -1280139264,1287877503,US +1280139264,1287612122,US +1287612123,1287612136,SE +1287612137,1287877503,US 1287877504,1287877567,UM 1287877568,1290252799,US 1290252800,1290252863,GB @@ -25333,8 +26057,7 @@ 1296238592,1296239103,NL 1296239104,1296239231,FR 1296239232,1296239359,NL -1296239360,1296239615,ES -1296239616,1296240127,FR +1296239360,1296240127,FR 1296240128,1296241151,BE 1296241152,1296241407,IT 1296241408,1296242175,NL @@ -25388,7 +26111,8 @@ 1296251328,1296251359,IE 1296251360,1296251391,DE 1296251392,1296251775,NL -1296251776,1296252111,FR +1296251776,1296252095,FR +1296252096,1296252111,US 1296252112,1296252127,GB 1296252128,1296252143,ES 1296252144,1296252159,US @@ -25404,7 +26128,9 @@ 1296252320,1296252367,FR 1296252368,1296252383,DE 1296252384,1296252415,IE -1296252416,1296252687,FR +1296252416,1296252671,FR +1296252672,1296252679,GB +1296252680,1296252687,FR 1296252688,1296252695,NL 1296252696,1296252703,IE 1296252704,1296252711,DE @@ -25424,7 +26150,7 @@ 1296252880,1296252887,DE 1296252888,1296252895,IE 1296252896,1296252911,BE -1296252912,1296252919,FR +1296252912,1296252919,GB 1296252920,1296252927,PL 1296252928,1296255743,DE 1296255744,1296255999,FR @@ -25438,7 +26164,8 @@ 1296259584,1296259839,FR 1296259840,1296260351,NL 1296260352,1296260607,US -1296260608,1296262143,FR +1296260608,1296260863,DE +1296260864,1296262143,FR 1296262144,1296262655,US 1296262656,1296262911,CA 1296262912,1296263935,US @@ -25493,15 +26220,15 @@ 1296466384,1296466399,NO 1296466400,1296466415,AO 1296466416,1296466431,NG -1296466432,1296466559,NO +1296466432,1296466439,TZ +1296466440,1296466559,NO 1296466560,1296466583,NG 1296466584,1296466607,NO 1296466608,1296466623,NG 1296466624,1296466639,NO 1296466640,1296466655,NG 1296466656,1296466671,BJ -1296466672,1296466679,NG -1296466680,1296466687,NO +1296466672,1296466687,NO 1296466688,1296466719,BJ 1296466720,1296466751,NO 1296466752,1296466759,ML @@ -25547,7 +26274,7 @@ 1296606336,1296606367,AT 1296606368,1296606399,CH 1296606400,1296607231,AT -1296607232,1296607743,DE +1296607232,1296607743,CH 1296607744,1296607999,NL 1296608000,1296609023,CH 1296609024,1296609279,NL @@ -25712,12 +26439,7 @@ 1296957440,1296973823,BG 1296973824,1296990207,CZ 1296990208,1297006591,BG -1297006592,1297018623,BA -1297018624,1297019135,MD -1297019136,1297020927,BA -1297020928,1297021183,RS -1297021184,1297021439,MD -1297021440,1297022207,BA +1297006592,1297022207,BA 1297022208,1297022463,MD 1297022464,1297022975,BA 1297022976,1297039359,LT @@ -25788,7 +26510,8 @@ 1297867584,1297867647,SC 1297867648,1297867687,RU 1297867688,1297867695,CY -1297867696,1297867871,RU +1297867696,1297867855,RU +1297867856,1297867871,MK 1297867872,1297867879,ES 1297867880,1297868799,RU 1297868800,1297870847,DE @@ -25817,7 +26540,7 @@ 1297993312,1297997823,CZ 1297997824,1298006015,IT 1298006016,1298014207,RU -1298014208,1298014719,LB +1298014208,1298014719,LT 1298014720,1298014975,RU 1298014976,1298015231,LT 1298015232,1298015487,RU @@ -25917,7 +26640,9 @@ 1299016960,1299017215,NL 1299017216,1299017727,RU 1299017728,1299021823,BE -1299021824,1299026111,CH +1299021824,1299024559,CH +1299024560,1299024575,DE +1299024576,1299026111,CH 1299026112,1299026127,ES 1299026128,1299026251,CH 1299026252,1299026263,PT @@ -25952,7 +26677,10 @@ 1306263552,1306271743,KE 1306271744,1306279935,RU 1306279936,1306286079,IT -1306286080,1306288127,CH +1306286080,1306287103,CH +1306287104,1306287615,IT +1306287616,1306287903,CH +1306287904,1306288127,IT 1306288128,1306296319,AT 1306296320,1306311143,RU 1306311144,1306311151,CH @@ -26034,6 +26762,7 @@ 1307435008,1307443199,DE 1307443200,1307451391,IT 1307451392,1307459583,SE +1307459584,1307467775,BG 1307467776,1307484159,RU 1307484160,1307488767,GB 1307488768,1307489023,IE @@ -26119,14 +26848,13 @@ 1307756448,1307756543,GB 1307756544,1307756847,FR 1307756848,1307756863,US -1307756864,1307756903,FR +1307756864,1307756903,GB 1307756904,1307756911,US -1307756912,1307757063,FR +1307756912,1307757063,GB 1307757064,1307757071,US -1307757072,1307757183,FR +1307757072,1307757183,GB 1307757184,1307757247,US -1307757248,1307757567,FR -1307757568,1307758591,GB +1307757248,1307758591,GB 1307758592,1307762687,SM 1307762688,1307766783,PL 1307766784,1307770879,GB @@ -26151,14 +26879,18 @@ 1307848704,1307852799,CH 1307852800,1307856895,RU 1307856896,1307860991,IT -1307860992,1307861119,DE +1307860992,1307861079,DE +1307861080,1307861083,LU +1307861084,1307861119,DE 1307861120,1307861123,LU 1307861124,1307861127,A2 1307861128,1307861151,DE 1307861152,1307861155,LU 1307861156,1307861919,DE 1307861920,1307861935,LU -1307861936,1307864127,DE +1307861936,1307861983,DE +1307861984,1307861987,A2 +1307861988,1307864127,DE 1307864128,1307864135,LU 1307864136,1307864143,DE 1307864144,1307864147,A2 @@ -26177,7 +26909,9 @@ 1307887104,1307889663,DK 1307889664,1307893759,RU 1307893760,1307897855,SE -1307897856,1307901951,AT +1307897856,1307901663,AT +1307901664,1307901671,DE +1307901672,1307901951,AT 1307901952,1307906047,JO 1307906048,1307906599,CH 1307906600,1307906607,DK @@ -26196,7 +26930,9 @@ 1307919700,1307919703,ZA 1307919704,1307920575,GB 1307920576,1307920583,AU -1307920584,1307921471,GB +1307920584,1307921431,GB +1307921432,1307921439,BD +1307921440,1307921471,GB 1307921472,1307921535,ES 1307921536,1307922431,GB 1307922432,1307926527,NL @@ -26800,7 +27536,9 @@ 1315860480,1315864575,IR 1315864576,1315868671,CH 1315868672,1315872767,RU -1315872768,1315876863,GB +1315872768,1315875183,GB +1315875184,1315875199,ES +1315875200,1315876863,GB 1315876864,1315880959,IT 1315880960,1315885055,BE 1315885056,1315889151,CZ @@ -26890,7 +27628,9 @@ 1317640704,1317641215,GB 1317641216,1317641471,IE 1317641472,1317641727,GB -1317641728,1317642975,IE +1317641728,1317642863,IE +1317642864,1317642879,GB +1317642880,1317642975,IE 1317642976,1317642991,GB 1317642992,1317645407,IE 1317645408,1317645823,GB @@ -26905,8 +27645,8 @@ 1317649920,1317650023,IE 1317650024,1317650031,GB 1317650032,1317650047,IE -1317650048,1317650111,GB -1317650112,1317650135,IE +1317650048,1317650095,GB +1317650096,1317650135,IE 1317650136,1317650143,GB 1317650144,1317650431,IE 1317650432,1317666815,RU @@ -26928,25 +27668,22 @@ 1317667040,1317667047,GH 1317667048,1317667055,A2 1317667056,1317667063,LR -1317667064,1317667071,A2 -1317667072,1317667079,AO -1317667080,1317667103,A2 +1317667064,1317667103,A2 1317667104,1317667111,NG -1317667112,1317667119,GH -1317667120,1317667135,A2 +1317667112,1317667135,A2 1317667136,1317667143,AO 1317667144,1317667151,A2 1317667152,1317667159,NG 1317667160,1317667167,AO 1317667168,1317667175,NG -1317667176,1317667183,GH -1317667184,1317667191,A2 +1317667176,1317667191,A2 1317667192,1317667231,NG 1317667232,1317667239,GH 1317667240,1317667247,NG 1317667248,1317667263,A2 1317667264,1317667271,GB -1317667272,1317667295,NG +1317667272,1317667279,A2 +1317667280,1317667295,NG 1317667296,1317667303,A2 1317667304,1317667335,NG 1317667336,1317667343,A2 @@ -26965,15 +27702,15 @@ 1317667496,1317667503,NG 1317667504,1317667551,A2 1317667552,1317667567,NG -1317667568,1317667583,A2 -1317667584,1317667719,NG +1317667568,1317667711,A2 +1317667712,1317667719,NG 1317667720,1317667735,A2 1317667736,1317667743,NG 1317667744,1317667751,A2 1317667752,1317667759,NG 1317667760,1317667767,FR 1317667768,1317667775,ZA -1317667776,1317667783,A2 +1317667776,1317667783,US 1317667784,1317667823,NG 1317667824,1317668095,A2 1317668096,1317668103,GH @@ -26992,8 +27729,7 @@ 1317668248,1317668255,NG 1317668256,1317668271,A2 1317668272,1317668279,SL -1317668280,1317668295,A2 -1317668296,1317668303,CD +1317668280,1317668303,A2 1317668304,1317668311,NG 1317668312,1317668319,IQ 1317668320,1317668343,A2 @@ -27032,8 +27768,7 @@ 1317668672,1317668703,NG 1317668704,1317668727,A2 1317668728,1317668735,NG -1317668736,1317668759,A2 -1317668760,1317668767,IQ +1317668736,1317668767,A2 1317668768,1317668775,LR 1317668776,1317668791,NG 1317668792,1317668807,A2 @@ -27045,18 +27780,18 @@ 1317668856,1317668863,A2 1317668864,1317668871,LR 1317668872,1317668911,A2 -1317668912,1317668927,NG -1317668928,1317668935,A2 +1317668912,1317668919,NG +1317668920,1317668935,A2 1317668936,1317668943,NG 1317668944,1317668959,A2 1317668960,1317668983,NG 1317668984,1317668999,A2 1317669000,1317669007,CD -1317669008,1317669023,NG -1317669024,1317669055,A2 +1317669008,1317669015,NG +1317669016,1317669055,A2 1317669056,1317669079,NG -1317669080,1317669087,A2 -1317669088,1317669103,NG +1317669080,1317669095,A2 +1317669096,1317669103,NG 1317669104,1317669111,A2 1317669112,1317669119,NG 1317669120,1317669375,GE @@ -27072,8 +27807,7 @@ 1317670016,1317670063,A2 1317670064,1317670103,NG 1317670104,1317670111,A2 -1317670112,1317670135,NG -1317670136,1317670143,A2 +1317670112,1317670143,NG 1317670144,1317670175,SL 1317670176,1317670215,A2 1317670216,1317670223,NG @@ -27082,13 +27816,12 @@ 1317670240,1317670247,NG 1317670248,1317670255,A2 1317670256,1317670263,NG -1317670264,1317670407,A2 -1317670408,1317670415,CD -1317670416,1317670423,A2 +1317670264,1317670423,A2 1317670424,1317670431,NG 1317670432,1317670447,A2 1317670448,1317670455,IQ -1317670456,1317670471,NG +1317670456,1317670463,A2 +1317670464,1317670471,NG 1317670472,1317670479,CO 1317670480,1317670511,A2 1317670512,1317670519,CI @@ -27115,7 +27848,7 @@ 1317670776,1317670783,A2 1317670784,1317670791,GH 1317670792,1317670807,NG -1317670808,1317670815,AO +1317670808,1317670815,A2 1317670816,1317670823,NG 1317670824,1317670847,A2 1317670848,1317670855,NG @@ -27126,9 +27859,7 @@ 1317670897,1317670911,NG 1317670912,1317671175,A2 1317671176,1317671191,NG -1317671192,1317671199,A2 -1317671200,1317671207,CI -1317671208,1317671231,A2 +1317671192,1317671231,A2 1317671232,1317671239,NG 1317671240,1317671247,CI 1317671248,1317671255,NG @@ -27137,22 +27868,21 @@ 1317671272,1317671279,A2 1317671280,1317671311,NG 1317671312,1317671319,A2 -1317671320,1317671335,NG +1317671320,1317671327,NG +1317671328,1317671335,A2 1317671336,1317671343,BW -1317671344,1317671351,CD -1317671352,1317671359,A2 +1317671344,1317671359,A2 1317671360,1317671367,NG 1317671368,1317671375,A2 1317671376,1317671383,NG 1317671384,1317671391,CI 1317671392,1317671399,NG 1317671400,1317671407,IQ -1317671408,1317671415,A2 +1317671408,1317671415,UG 1317671416,1317671423,NG 1317671424,1317671439,A2 1317671440,1317671487,NG -1317671488,1317671503,AO -1317671504,1317671527,A2 +1317671488,1317671527,A2 1317671528,1317671543,NG 1317671544,1317671551,GH 1317671552,1317671567,NG @@ -27196,9 +27926,7 @@ 1317672624,1317672655,A2 1317672656,1317672663,CD 1317672664,1317672679,NG -1317672680,1317672703,A2 -1317672704,1317672711,NG -1317672712,1317672727,A2 +1317672680,1317672727,A2 1317672728,1317672735,NG 1317672736,1317672743,LR 1317672744,1317672759,A2 @@ -27211,20 +27939,20 @@ 1317672832,1317672839,A2 1317672840,1317672847,NG 1317672848,1317672863,A2 -1317672864,1317672895,NG +1317672864,1317672871,NG +1317672872,1317672879,A2 +1317672880,1317672895,NG 1317672896,1317672903,A2 1317672904,1317672919,CI 1317672920,1317672927,GH 1317672928,1317672951,NG 1317672952,1317672959,A2 -1317672960,1317673239,NG -1317673240,1317673255,A2 -1317673256,1317673271,NG +1317672960,1317673247,NG +1317673248,1317673263,A2 +1317673264,1317673271,UG 1317673272,1317673279,A2 1317673280,1317673287,NG -1317673288,1317673311,A2 -1317673312,1317673319,NG -1317673320,1317673335,A2 +1317673288,1317673335,A2 1317673336,1317673343,GH 1317673344,1317673359,A2 1317673360,1317673375,NG @@ -27264,8 +27992,8 @@ 1317673744,1317673751,IQ 1317673752,1317673815,A2 1317673816,1317673823,LR -1317673824,1317673855,A2 -1317673856,1317673871,NG +1317673824,1317673863,A2 +1317673864,1317673871,NG 1317673872,1317673903,A2 1317673904,1317673911,NG 1317673912,1317673919,AO @@ -27280,11 +28008,11 @@ 1317674256,1317674263,CM 1317674264,1317674271,A2 1317674272,1317674279,NG -1317674280,1317674287,CD +1317674280,1317674287,A2 1317674288,1317674295,GH 1317674296,1317674303,AO -1317674304,1317674319,NG -1317674320,1317674351,A2 +1317674304,1317674335,NG +1317674336,1317674351,A2 1317674352,1317674359,NG 1317674360,1317674383,A2 1317674384,1317674399,NG @@ -27309,42 +28037,43 @@ 1317674632,1317674639,A2 1317674640,1317674647,NG 1317674648,1317674655,A2 -1317674656,1317674671,NG -1317674672,1317674687,A2 +1317674656,1317674679,NG +1317674680,1317674687,A2 1317674688,1317674703,NG 1317674704,1317674711,A2 1317674712,1317674735,NG 1317674736,1317674743,AO 1317674744,1317674751,IQ -1317674752,1317674791,NG +1317674752,1317674759,NG +1317674760,1317674767,A2 +1317674768,1317674791,NG 1317674792,1317674799,A2 1317674800,1317674807,NG 1317674808,1317674823,A2 -1317674824,1317674863,NG +1317674824,1317674839,NG +1317674840,1317674847,A2 +1317674848,1317674863,NG 1317674864,1317674879,A2 1317674880,1317674887,NG -1317674888,1317674895,AO -1317674896,1317674911,A2 +1317674888,1317674911,A2 1317674912,1317674927,NG 1317674928,1317674935,A2 1317674936,1317674943,NG 1317674944,1317674951,GA 1317674952,1317674959,NG 1317674960,1317674967,GH -1317674968,1317674975,NG -1317674976,1317674991,A2 +1317674968,1317674983,NG +1317674984,1317674991,A2 1317674992,1317675007,NG 1317675008,1317675023,A2 -1317675024,1317675031,NG -1317675032,1317675039,A2 -1317675040,1317675047,NG +1317675024,1317675047,NG 1317675048,1317675055,A2 1317675056,1317675063,NG 1317675064,1317675071,AO 1317675072,1317675095,NG -1317675096,1317675119,A2 -1317675120,1317675127,NG -1317675128,1317675183,A2 +1317675096,1317675103,A2 +1317675104,1317675111,CD +1317675112,1317675183,A2 1317675184,1317675199,CM 1317675200,1317675223,NG 1317675224,1317675231,A2 @@ -27394,47 +28123,210 @@ 1317675696,1317675703,NG 1317675704,1317675711,A2 1317675712,1317675719,CM -1317675720,1317675735,NG +1317675720,1317675727,A2 +1317675728,1317675735,NG 1317675736,1317675743,A2 1317675744,1317675751,GH 1317675752,1317675759,NG 1317675760,1317675775,GH 1317675776,1317675783,NG -1317675784,1317675815,A2 -1317675816,1317675831,NG -1317675832,1317675911,A2 -1317675912,1317675927,NG -1317675928,1317675951,A2 -1317675952,1317675967,NG -1317675968,1317676287,A2 -1317676288,1317676543,LR -1317676544,1317676583,A2 +1317675784,1317675799,A2 +1317675800,1317675807,NG +1317675808,1317675815,A2 +1317675816,1317675839,NG +1317675840,1317675855,A2 +1317675856,1317675863,NG +1317675864,1317675887,A2 +1317675888,1317675895,CD +1317675896,1317675911,A2 +1317675912,1317675935,NG +1317675936,1317675943,A2 +1317675944,1317675975,NG +1317675976,1317675983,A2 +1317675984,1317675991,LR +1317675992,1317675999,A2 +1317676000,1317676007,GN +1317676008,1317676015,GH +1317676016,1317676023,SD +1317676024,1317676031,GQ +1317676032,1317676039,NG +1317676040,1317676047,CD +1317676048,1317676063,A2 +1317676064,1317676071,CM +1317676072,1317676079,A2 +1317676080,1317676087,AO +1317676088,1317676095,NG +1317676096,1317676103,NE +1317676104,1317676111,NG +1317676112,1317676127,A2 +1317676128,1317676135,NG +1317676136,1317676151,A2 +1317676152,1317676159,CM +1317676160,1317676167,TG +1317676168,1317676175,ML +1317676176,1317676191,A2 +1317676192,1317676207,SD +1317676208,1317676215,A2 +1317676216,1317676223,GH +1317676224,1317676231,AO +1317676232,1317676239,NG +1317676240,1317676247,SD +1317676248,1317676255,NG +1317676256,1317676263,CD +1317676264,1317676271,NG +1317676272,1317676279,A2 +1317676280,1317676287,NG +1317676288,1317676551,LR +1317676552,1317676559,AO +1317676560,1317676567,NG +1317676568,1317676583,A2 1317676584,1317676591,NG -1317676592,1317676655,A2 +1317676592,1317676599,AO +1317676600,1317676607,UG +1317676608,1317676615,NG +1317676616,1317676623,A2 +1317676624,1317676631,CM +1317676632,1317676639,A2 +1317676640,1317676647,LR +1317676648,1317676655,A2 1317676656,1317676671,NG -1317676672,1317676823,A2 +1317676672,1317676687,A2 +1317676688,1317676695,LR +1317676696,1317676711,A2 +1317676712,1317676719,NG +1317676720,1317676727,GQ +1317676728,1317676751,A2 +1317676752,1317676759,ML +1317676760,1317676767,LR +1317676768,1317676775,A2 +1317676776,1317676783,UG +1317676784,1317676799,A2 +1317676800,1317676807,CD +1317676808,1317676815,NG +1317676816,1317676823,LR 1317676824,1317676831,NG -1317676832,1317676895,A2 -1317676896,1317676919,NG -1317676920,1317676991,A2 +1317676832,1317676847,A2 +1317676848,1317676855,NG +1317676856,1317676863,A2 +1317676864,1317676871,TG +1317676872,1317676879,NG +1317676880,1317676903,A2 +1317676904,1317676927,NG +1317676928,1317676943,A2 +1317676944,1317676959,CM +1317676960,1317676983,A2 +1317676984,1317676991,NG 1317676992,1317676999,LR 1317677000,1317677007,IQ -1317677008,1317677015,IT -1317677016,1317677023,A2 +1317677008,1317677015,CD +1317677016,1317677023,GH 1317677024,1317677031,NG -1317677032,1317677079,A2 +1317677032,1317677047,A2 +1317677048,1317677055,NG +1317677056,1317677071,A2 +1317677072,1317677079,NG 1317677080,1317677087,SD 1317677088,1317677143,A2 1317677144,1317677151,SD -1317677152,1317677199,A2 +1317677152,1317677191,A2 +1317677192,1317677199,SD 1317677200,1317677207,NG 1317677208,1317677223,A2 1317677224,1317677231,NG -1317677232,1317677247,A2 -1317677248,1317677255,NG -1317677256,1317677303,A2 -1317677304,1317677311,NG -1317677312,1317683199,A2 +1317677232,1317677239,UG +1317677240,1317677247,A2 +1317677248,1317677271,NG +1317677272,1317677295,A2 +1317677296,1317677311,NG +1317677312,1317677319,A2 +1317677320,1317677327,AO +1317677328,1317677335,CD +1317677336,1317677343,A2 +1317677344,1317677351,NG +1317677352,1317677367,CD +1317677368,1317677375,NG +1317677376,1317677399,A2 +1317677400,1317677407,NG +1317677408,1317677415,CD +1317677416,1317677423,A2 +1317677424,1317677431,CD +1317677432,1317677439,A2 +1317677440,1317677455,CD +1317677456,1317677463,AO +1317677464,1317677471,A2 +1317677472,1317677479,NG +1317677480,1317677487,AO +1317677488,1317677495,A2 +1317677496,1317677503,CD +1317677504,1317677511,NG +1317677512,1317677519,CD +1317677520,1317677527,NG +1317677528,1317677535,GQ +1317677536,1317677543,A2 +1317677544,1317677551,CD +1317677552,1317677591,NG +1317677592,1317677599,A2 +1317677600,1317677711,NG +1317677712,1317677719,A2 +1317677720,1317677735,NG +1317677736,1317677743,A2 +1317677744,1317677775,NG +1317677776,1317677791,A2 +1317677792,1317677823,NG +1317677824,1317677831,AO +1317677832,1317677839,A2 +1317677840,1317677847,LR +1317677848,1317677855,NG +1317677856,1317677895,A2 +1317677896,1317677903,GN +1317677904,1317677959,A2 +1317677960,1317677967,NG +1317677968,1317678007,A2 +1317678008,1317678015,NG +1317678016,1317678047,A2 +1317678048,1317678055,IQ +1317678056,1317678143,A2 +1317678144,1317678151,CD +1317678152,1317678167,A2 +1317678168,1317678175,NG +1317678176,1317678207,A2 +1317678208,1317678215,NG +1317678216,1317678231,A2 +1317678232,1317678239,BF +1317678240,1317678335,A2 +1317678336,1317678343,NG +1317678344,1317678375,A2 +1317678376,1317678383,NG +1317678384,1317678439,A2 +1317678440,1317678447,CD +1317678448,1317678455,A2 +1317678456,1317678463,CD +1317678464,1317678471,A2 +1317678472,1317678479,AO +1317678480,1317678487,A2 +1317678488,1317678495,NG +1317678496,1317679615,A2 +1317679616,1317679631,AO +1317679632,1317679639,A2 +1317679640,1317679647,ZW +1317679648,1317679663,A2 +1317679664,1317679671,AO +1317679672,1317679679,NG +1317679680,1317679695,A2 +1317679696,1317679703,LU +1317679704,1317679711,A2 +1317679712,1317679719,NG +1317679720,1317679727,A2 +1317679728,1317679735,GN +1317679736,1317679743,A2 +1317679744,1317679751,AO +1317679752,1317679767,NG +1317679768,1317679783,A2 +1317679784,1317679799,NG +1317679800,1317679831,A2 +1317679832,1317679839,CD +1317679840,1317679847,NG +1317679848,1317683199,A2 1317683200,1317683839,DE 1317683840,1317683855,CH 1317683856,1317683863,DE @@ -27476,14 +28368,15 @@ 1317839680,1317839695,CZ 1317839696,1317841407,NL 1317841408,1317841439,SC -1317841440,1317841727,NL +1317841440,1317841663,NL +1317841664,1317841727,HK 1317841728,1317841855,CY 1317841856,1317842943,NL 1317842944,1317843071,CY 1317843072,1317843135,HK 1317843136,1317843199,CY -1317843200,1317843327,US -1317843328,1317847039,NL +1317843200,1317843391,US +1317843392,1317847039,NL 1317847040,1317863423,RU 1317863424,1317879807,GB 1317879808,1317896191,SK @@ -27509,7 +28402,9 @@ 1318006272,1318006783,NL 1318006784,1318007999,DE 1318008000,1318008031,NL -1318008032,1318009423,DE +1318008032,1318008703,DE +1318008704,1318008767,NL +1318008768,1318009423,DE 1318009424,1318009471,NL 1318009472,1318010527,DE 1318010528,1318010879,NL @@ -27549,8 +28444,8 @@ 1318708524,1318708527,GB 1318708528,1318708599,FR 1318708600,1318708607,GB -1318708608,1318708631,FR -1318708632,1318708731,GB +1318708608,1318708639,FR +1318708640,1318708731,GB 1318708732,1318708735,FR 1318708736,1318708991,GB 1318708992,1318711647,FR @@ -27681,7 +28576,6 @@ 1331881984,1331883007,GB 1331883008,1331883263,SE 1331883264,1331886079,GB -1331886080,1331888127,ES 1331888128,1331890175,SE 1331890176,1331892223,IT 1331892224,1331894271,RU @@ -27713,13 +28607,19 @@ 1331937584,1331937599,ZA 1331937600,1331938111,GB 1331938112,1331938127,AE -1331938128,1331938191,GB +1331938128,1331938135,SA +1331938136,1331938191,GB 1331938192,1331938207,AE 1331938208,1331938375,GB 1331938376,1331938383,AE -1331938384,1331938823,GB +1331938384,1331938399,IE +1331938400,1331938823,GB 1331938824,1331938831,US -1331938832,1331939327,GB +1331938832,1331938839,NG +1331938840,1331938847,IE +1331938848,1331938879,GB +1331938880,1331938895,NG +1331938896,1331939327,GB 1331939328,1331941375,BE 1331941376,1331943423,ES 1331943424,1331945471,RU @@ -27781,9 +28681,7 @@ 1334083584,1334091775,DE 1334091776,1334099967,LT 1334099968,1334108159,IR -1334108160,1334109807,BE -1334109808,1334109811,NL -1334109812,1334113527,BE +1334108160,1334113527,BE 1334113528,1334113535,NL 1334113536,1334116351,BE 1334116352,1334124543,AX @@ -27792,6 +28690,7 @@ 1334165504,1334173695,PL 1334173696,1334181887,LT 1334181888,1334190079,RU +1334190080,1334198271,BG 1334198272,1334206463,RU 1334206464,1334214655,FI 1334214656,1334222847,JO @@ -27806,9 +28705,7 @@ 1334288384,1334296575,PL 1334296576,1334304767,UA 1334304768,1334312959,RU -1334312960,1334316031,SE -1334316032,1334316543,NO -1334316544,1334343047,SE +1334312960,1334343047,SE 1334343048,1334343055,NO 1334343056,1334345727,SE 1334345728,1334378495,RU @@ -27824,9 +28721,7 @@ 1334542336,1334575103,RU 1334575104,1334579199,UA 1334579200,1334583295,RU -1334583296,1334583311,DE -1334583312,1334583319,US -1334583320,1334583535,DE +1334583296,1334583535,DE 1334583536,1334583543,US 1334583544,1334583807,DE 1334583808,1334584063,CH @@ -27838,7 +28733,9 @@ 1334585000,1334585007,US 1334585008,1334585111,DE 1334585112,1334585119,AT -1334585120,1334591487,DE +1334585120,1334585471,DE +1334585472,1334585503,AT +1334585504,1334591487,DE 1334591488,1334595583,RU 1334595584,1334596351,IT 1334596352,1334596607,GR @@ -27869,7 +28766,9 @@ 1334640640,1334644735,FR 1334644736,1334644991,LU 1334644992,1334645247,A2 -1334645248,1334648319,IQ +1334645248,1334647807,IQ +1334647808,1334648063,LB +1334648064,1334648319,IQ 1334648320,1334648831,A2 1334648832,1334650959,GB 1334650960,1334650975,NL @@ -27928,6 +28827,7 @@ 1334730744,1334734847,RU 1334734848,1334738943,LT 1334738944,1334743039,CH +1334743040,1334747135,CZ 1334747136,1334751231,RU 1334751232,1334755327,BH 1334755328,1334759423,UA @@ -28042,7 +28942,9 @@ 1336885248,1336901631,RS 1336901632,1336911103,IR 1336911104,1336911359,SE -1336911360,1336918015,IR +1336911360,1336911749,IR +1336911750,1336911759,AE +1336911760,1336918015,IR 1336918016,1336934399,PL 1336934400,1337458687,IL 1337458688,1337982975,PL @@ -28164,25 +29066,29 @@ 1346501152,1346501247,IM 1346501248,1346501343,GB 1346501344,1346501375,IM -1346501376,1346501743,GB -1346501744,1346501751,IM -1346501752,1346501795,GB +1346501376,1346501695,GB +1346501696,1346501727,IM +1346501728,1346501743,GB +1346501744,1346501775,IM +1346501776,1346501795,GB 1346501796,1346501823,IM -1346501824,1346501848,GB -1346501849,1346501879,IM -1346501880,1346502319,GB +1346501824,1346501847,GB +1346501848,1346501879,IM +1346501880,1346502223,GB +1346502224,1346502239,IM +1346502240,1346502319,GB 1346502320,1346502323,IM -1346502324,1346502463,GB -1346502464,1346502527,IM -1346502528,1346502559,GB -1346502560,1346502591,IM -1346502592,1346502655,GB +1346502324,1346502399,GB +1346502400,1346502527,IM +1346502528,1346502655,GB 1346502656,1346510847,DE 1346510848,1346519039,AT 1346519040,1346527231,RU 1346527232,1346531327,DE 1346531328,1346535423,ES -1346535424,1346537983,BE +1346535424,1346537335,BE +1346537336,1346537343,GB +1346537344,1346537983,BE 1346537984,1346537988,AT 1346537989,1346537991,BE 1346537992,1346537999,AT @@ -28353,11 +29259,14 @@ 1347133440,1347141631,EG 1347141632,1347145727,CH 1347145728,1347146239,GB -1347146240,1347147263,FR +1347146240,1347147007,FR +1347147008,1347147263,DE 1347147264,1347147775,GB 1347147776,1347148287,DE 1347148288,1347148543,GB -1347148544,1347149823,FR +1347148544,1347148799,FR +1347148800,1347149055,NO +1347149056,1347149823,FR 1347149824,1347153919,HU 1347153920,1347158015,AT 1347158016,1347162111,CH @@ -28380,7 +29289,6 @@ 1347211112,1347211119,IE 1347211120,1347215359,GB 1347215360,1347219455,RU -1347219456,1347223551,KW 1347223552,1347223807,EG 1347223808,1347224063,HK 1347224064,1347224183,US @@ -28391,15 +29299,21 @@ 1347226624,1347227135,EG 1347227136,1347227391,HK 1347227392,1347227647,EG -1347227648,1347229311,DE +1347227648,1347228055,DE +1347228056,1347228063,GR +1347228064,1347229311,DE 1347229312,1347229343,AT -1347229344,1347231071,DE +1347229344,1347229895,DE +1347229896,1347229903,GR +1347229904,1347231071,DE 1347231072,1347231087,AT 1347231088,1347231095,GR 1347231096,1347231743,DE 1347231744,1347235839,UA 1347235840,1347239935,GE -1347239936,1347244031,DK +1347239936,1347240943,DK +1347240944,1347240959,GB +1347240960,1347244031,DK 1347244032,1347247359,GB 1347247360,1347247871,RU 1347247872,1347248127,US @@ -28501,9 +29415,7 @@ 1347293928,1347293935,US 1347293936,1347293943,NG 1347293944,1347293951,A2 -1347293952,1347293959,NG -1347293960,1347293967,GN -1347293968,1347293975,NG +1347293952,1347293975,NG 1347293976,1347293983,GN 1347293984,1347293991,US 1347293992,1347293999,NG @@ -28605,13 +29517,16 @@ 1347342336,1347346431,SE 1347346432,1347350527,BG 1347350528,1347354623,RU +1347354624,1347358719,GR 1347358720,1347362815,CZ 1347362816,1347366911,NL 1347366912,1347371007,IT 1347371008,1347375103,RU 1347375104,1347379199,GB 1347379200,1347383295,NL -1347383296,1347387391,EE +1347383296,1347386751,EE +1347386752,1347386815,MY +1347386816,1347387391,EE 1347387392,1347391487,GB 1347391488,1347395583,LB 1347395584,1347399679,SE @@ -28691,7 +29606,9 @@ 1347571712,1347575807,RU 1347575808,1347579903,DK 1347579904,1347588095,GB -1347588096,1347592191,CZ +1347588096,1347590911,CZ +1347590912,1347591167,SK +1347591168,1347592191,CZ 1347592192,1347600383,RU 1347600384,1347604479,IT 1347604480,1347608575,DE @@ -28774,7 +29691,9 @@ 1347756032,1347760127,NL 1347760128,1347764223,HU 1347764224,1347772415,GB -1347772416,1347776511,MT +1347772416,1347775953,MT +1347775954,1347775954,GB +1347775955,1347776511,MT 1347776512,1347780607,SE 1347780608,1347784703,NL 1347784704,1347788799,RU @@ -28812,14 +29731,12 @@ 1347855960,1347855967,DE 1347855968,1347855999,EU 1347856000,1347856063,DE -1347856064,1347856079,EU -1347856080,1347856239,DE +1347856064,1347856095,EU +1347856096,1347856239,DE 1347856240,1347856255,EU 1347856256,1347856383,DE 1347856384,1347856391,EU -1347856392,1347856415,DE -1347856416,1347856423,EU -1347856424,1347856431,DE +1347856392,1347856431,DE 1347856432,1347856447,EU 1347856448,1347856639,DE 1347856640,1347856895,AT @@ -28852,9 +29769,7 @@ 1347861944,1347861951,DE 1347861952,1347862111,EU 1347862112,1347862143,DE -1347862144,1347862279,EU -1347862280,1347862287,DE -1347862288,1347862303,EU +1347862144,1347862303,EU 1347862304,1347862431,DE 1347862432,1347862463,EU 1347862464,1347862527,DE @@ -28888,8 +29803,8 @@ 1347977600,1347977607,NG 1347977608,1347978007,A2 1347978008,1347978015,NG -1347978016,1347978023,A2 -1347978024,1347978039,NG +1347978016,1347978031,A2 +1347978032,1347978039,NG 1347978040,1347978191,A2 1347978192,1347978199,NG 1347978200,1347978263,A2 @@ -28905,8 +29820,10 @@ 1347978408,1347978447,A2 1347978448,1347978463,NG 1347978464,1347978575,A2 -1347978576,1347978655,NG -1347978656,1347978727,A2 +1347978576,1347978623,NG +1347978624,1347978631,A2 +1347978632,1347978647,NG +1347978648,1347978727,A2 1347978728,1347978735,NG 1347978736,1347978775,A2 1347978776,1347978783,NG @@ -28932,16 +29849,14 @@ 1347979584,1347979591,NG 1347979592,1347979743,A2 1347979744,1347979751,NG -1347979752,1347980079,A2 -1347980080,1347980095,GH -1347980096,1347980111,NG +1347979752,1347980111,A2 1347980112,1347980127,GN 1347980128,1347980167,A2 1347980168,1347980175,NG 1347980176,1347980223,A2 1347980224,1347980271,NG -1347980272,1347980287,DK -1347980288,1347980415,A2 +1347980272,1347980279,DK +1347980280,1347980415,A2 1347980416,1347980479,NG 1347980480,1347980543,A2 1347980544,1347980559,DK @@ -28949,9 +29864,7 @@ 1347981008,1347981015,NG 1347981016,1347981023,A2 1347981024,1347981031,NG -1347981032,1347981183,A2 -1347981184,1347981191,NG -1347981192,1347981239,A2 +1347981032,1347981239,A2 1347981240,1347981247,NG 1347981248,1347981255,A2 1347981256,1347981263,DK @@ -28963,9 +29876,7 @@ 1347982224,1347982231,NG 1347982232,1347982279,A2 1347982280,1347982287,NG -1347982288,1347982887,A2 -1347982888,1347982895,NG -1347982896,1347982911,A2 +1347982288,1347982911,A2 1347982912,1347982919,NG 1347982920,1347982927,A2 1347982928,1347982943,NG @@ -28981,9 +29892,7 @@ 1347983304,1347983311,NG 1347983312,1347983423,A2 1347983424,1347983487,NG -1347983488,1347983527,A2 -1347983528,1347983535,NG -1347983536,1347983567,A2 +1347983488,1347983567,A2 1347983568,1347983575,NG 1347983576,1347983903,A2 1347983904,1347983911,NG @@ -29034,9 +29943,7 @@ 1348076032,1348076287,LV 1348076288,1348076543,RU 1348076544,1348083711,LV -1348083712,1348086535,LU -1348086536,1348086543,NL -1348086544,1348091903,LU +1348083712,1348091903,LU 1348091904,1348095999,RU 1348096000,1348100095,AL 1348100096,1348104191,DE @@ -29103,8 +30010,7 @@ 1348274800,1348274815,IL 1348274816,1348274927,IE 1348274928,1348274935,IL -1348274936,1348274943,IE -1348274944,1348275199,CH +1348274936,1348275199,CH 1348275200,1348275711,GB 1348275712,1348275967,CH 1348275968,1348280319,IE @@ -29227,7 +30133,9 @@ 1352011448,1352011455,IT 1352011456,1352038695,DE 1352038696,1352038699,US -1352038700,1352139671,DE +1352038700,1352041471,DE +1352041472,1352041727,US +1352041728,1352139671,DE 1352139672,1352139679,IT 1352139680,1352144519,DE 1352144520,1352144527,IT @@ -29256,7 +30164,9 @@ 1352149456,1352149487,FR 1352149488,1352277535,DE 1352277536,1352277567,IT -1352277568,1352402791,DE +1352277568,1352287399,DE +1352287400,1352287407,NL +1352287408,1352402791,DE 1352402792,1352402799,BE 1352402800,1352404599,DE 1352404600,1352404607,NL @@ -29264,7 +30174,9 @@ 1352445688,1352445703,NL 1352445704,1352663039,DE 1352663040,1353187327,DK -1353187328,1353253663,GB +1353187328,1353252991,GB +1353252992,1353253023,FR +1353253024,1353253663,GB 1353253664,1353253671,NL 1353253672,1353253791,GB 1353253792,1353253823,FR @@ -29288,94 +30200,74 @@ 1353258504,1353258639,SE 1353258640,1353258783,GB 1353258784,1353258807,SE -1353258808,1353265943,GB +1353258808,1353259271,GB +1353259272,1353259279,DE +1353259280,1353264167,GB +1353264168,1353264175,FR +1353264176,1353265375,GB +1353265376,1353265383,IE +1353265384,1353265943,GB 1353265944,1353265951,IE 1353265952,1353266959,GB 1353266960,1353266975,IE 1353266976,1353267455,GB 1353267456,1353268223,IE 1353268224,1353268479,GB -1353268480,1353268551,BE -1353268552,1353268559,GB -1353268560,1353269247,BE +1353268480,1353269247,BE 1353269248,1353270527,GB 1353270528,1353270783,IE 1353270784,1353271295,GB 1353271296,1353271423,IE -1353271424,1353271807,GB -1353271808,1353271831,ES +1353271424,1353271815,GB +1353271816,1353271831,ES 1353271832,1353271839,GB -1353271840,1353271847,ES -1353271848,1353271895,GB -1353271896,1353271919,ES -1353271920,1353271927,GB -1353271928,1353272031,ES +1353271840,1353272031,ES 1353272032,1353272039,FR 1353272040,1353272047,GB 1353272048,1353272055,ES 1353272056,1353272063,GB 1353272064,1353272245,ES -1353272246,1353272255,GB -1353272256,1353272647,ES -1353272648,1353272655,GB -1353272656,1353272691,ES +1353272246,1353272247,GB +1353272248,1353272691,ES 1353272692,1353272695,GB -1353272696,1353272727,ES -1353272728,1353272735,GB -1353272736,1353272783,ES -1353272784,1353272799,GB -1353272800,1353272807,ES +1353272696,1353272807,ES 1353272808,1353272815,GB -1353272816,1353272847,ES -1353272848,1353272879,GB -1353272880,1353273047,ES -1353273048,1353273055,GB -1353273056,1353273343,ES +1353272816,1353273343,ES 1353273344,1353273631,BE 1353273632,1353273639,ES 1353273640,1353273711,BE 1353273712,1353273719,GB 1353273720,1353274367,BE -1353274368,1353274671,ES -1353274672,1353274679,GB -1353274680,1353274687,ES -1353274688,1353274703,GB -1353274704,1353274759,ES +1353274368,1353274759,ES 1353274760,1353274767,GB 1353274768,1353274791,ES 1353274792,1353274799,GB -1353274800,1353274831,ES -1353274832,1353274839,GB -1353274840,1353274863,ES -1353274864,1353274879,GB -1353274880,1353274895,ES +1353274800,1353274895,ES 1353274896,1353274911,GB -1353274912,1353274919,ES -1353274920,1353274927,GB -1353274928,1353275023,ES -1353275024,1353275039,GB -1353275040,1353275087,ES -1353275088,1353275103,GB -1353275104,1353275231,ES -1353275232,1353275255,GB -1353275256,1353275263,ES -1353275264,1353275279,GB -1353275280,1353275335,ES -1353275336,1353275343,GB -1353275344,1353275391,ES +1353274912,1353275007,ES +1353275008,1353275015,GB +1353275016,1353275111,ES +1353275112,1353275119,GB +1353275120,1353275391,ES 1353275392,1353277439,GB 1353277440,1353279487,CH 1353279488,1353279743,IT 1353279744,1353279751,GB 1353279752,1353279759,IT 1353279760,1353279763,GB -1353279764,1353280119,IT +1353279764,1353280079,IT +1353280080,1353280087,GB +1353280088,1353280119,IT 1353280120,1353280127,GB 1353280128,1353280143,IT 1353280144,1353280151,GB -1353280152,1353280559,IT -1353280560,1353280575,GB -1353280576,1353281023,IT +1353280152,1353280279,IT +1353280280,1353280287,GB +1353280288,1353280567,IT +1353280568,1353280575,GB +1353280576,1353280663,IT +1353280664,1353280671,GB +1353280672,1353281023,IT 1353281024,1353281535,BE 1353281536,1353282047,GB 1353282048,1353282559,IT @@ -29384,7 +30276,9 @@ 1353283328,1353287327,GB 1353287328,1353287359,IE 1353287360,1353287679,GB -1353287680,1353288031,IE +1353287680,1353287935,IE +1353287936,1353287943,GB +1353287944,1353288031,IE 1353288032,1353288063,GB 1353288064,1353288151,IE 1353288152,1353288159,GB @@ -29400,16 +30294,16 @@ 1353288520,1353288527,GB 1353288528,1353288607,IE 1353288608,1353288639,GB -1353288640,1353288663,IE -1353288664,1353288671,GB -1353288672,1353288831,IE +1353288640,1353288831,IE 1353288832,1353288839,GB 1353288840,1353288847,IE 1353288848,1353288855,GB 1353288856,1353288879,IE 1353288880,1353288895,GB 1353288896,1353288959,IE -1353288960,1353289087,GB +1353288960,1353288975,GB +1353288976,1353288991,IE +1353288992,1353289087,GB 1353289088,1353289247,IE 1353289248,1353289255,GB 1353289256,1353289279,IE @@ -29439,7 +30333,8 @@ 1353298720,1353298751,DE 1353298752,1353298815,SE 1353298816,1353298831,PT -1353298832,1353298879,GB +1353298832,1353298839,SE +1353298840,1353298879,GB 1353298880,1353298881,SE 1353298882,1353298887,GB 1353298888,1353299647,SE @@ -29460,15 +30355,10 @@ 1353301096,1353301103,US 1353301104,1353306111,GB 1353306112,1353306623,ES -1353306624,1353306624,BE -1353306625,1353306687,GB -1353306688,1353306695,BE -1353306696,1353306703,GB -1353306704,1353306735,BE +1353306624,1353306687,GB +1353306688,1353306735,BE 1353306736,1353306751,GB -1353306752,1353306831,BE -1353306832,1353306847,GB -1353306848,1353307135,BE +1353306752,1353307135,BE 1353307136,1353307143,IT 1353307144,1353308159,GB 1353308160,1353309183,FR @@ -29478,12 +30368,14 @@ 1353310608,1353310719,ES 1353310720,1353311175,IT 1353311176,1353311183,ES -1353311184,1353311207,IT -1353311208,1353311215,GB +1353311184,1353311199,IT +1353311200,1353311215,GB 1353311216,1353311231,IT 1353311232,1353312255,GB 1353312256,1353312767,CH -1353312768,1353313111,IT +1353312768,1353312815,IT +1353312816,1353312823,GB +1353312824,1353313111,IT 1353313112,1353313119,GB 1353313120,1353313191,IT 1353313192,1353313199,GB @@ -29614,9 +30506,7 @@ 1354682772,1354682775,RS 1354682776,1354682895,DE 1354682896,1354682911,AE -1354682912,1354682939,DE -1354682940,1354682943,MC -1354682944,1354683095,DE +1354682912,1354683095,DE 1354683096,1354683103,IT 1354683104,1354683391,DE 1354683392,1354683903,PL @@ -29702,7 +30592,7 @@ 1357332480,1357333247,DE 1357333248,1357333503,GB 1357333504,1357333759,IR -1357333760,1357333823,EU +1357333760,1357333823,FR 1357333824,1357333855,GB 1357333856,1357334015,ES 1357334016,1357334271,TZ @@ -29728,19 +30618,18 @@ 1357342720,1357348863,EU 1357348864,1357349119,DE 1357349120,1357349375,LU -1357349376,1357349887,EU +1357349376,1357349887,GB 1357349888,1357350399,ES 1357350400,1357350911,QA 1357350912,1357351167,GB 1357351168,1357351423,PL -1357351424,1357351935,EU -1357351936,1357352959,GB +1357351424,1357352959,GB 1357352960,1357355007,EU 1357355008,1357355263,NL 1357355264,1357355775,FR 1357355776,1357356031,GB 1357356032,1357356543,ES -1357356544,1357357055,EU +1357356544,1357357055,PT 1357357056,1357357567,ES 1357357568,1357358079,DE 1357358080,1357358335,ES @@ -29776,7 +30665,8 @@ 1357366880,1357366911,GB 1357366912,1357367039,EU 1357367040,1357367295,GB -1357367296,1357367807,EU +1357367296,1357367551,FR +1357367552,1357367807,EU 1357367808,1357368063,GB 1357368064,1357368831,GN 1357368832,1357369343,ES @@ -29787,7 +30677,7 @@ 1357370368,1357370879,EU 1357370880,1357371391,LY 1357371392,1357371647,GB -1357371648,1357371903,EU +1357371648,1357371903,FR 1357371904,1357372159,RU 1357372160,1357372415,GB 1357372416,1357372927,EU @@ -29876,8 +30766,10 @@ 1357883552,1357883583,EU 1357883584,1357883727,FR 1357883728,1357883759,EU -1357883760,1357883935,FR -1357883936,1357883999,EU +1357883760,1357883775,FR +1357883776,1357883807,EU +1357883808,1357883903,FR +1357883904,1357883999,EU 1357884000,1357884031,FR 1357884032,1357884095,RU 1357884096,1357884159,EU @@ -29934,8 +30826,8 @@ 1357899016,1357899023,EU 1357899024,1357899039,DE 1357899040,1357899047,EU -1357899048,1357899055,DE -1357899056,1357899071,EU +1357899048,1357899063,DE +1357899064,1357899071,EU 1357899072,1357899199,DE 1357899200,1357899279,EU 1357899280,1357899287,RU @@ -30028,7 +30920,6 @@ 1358012416,1358016511,IT 1358016512,1358020607,GE 1358020608,1358024703,DE -1358024704,1358028799,EE 1358028800,1358032895,IT 1358032896,1358036991,GE 1358036992,1358041087,IR @@ -30083,22 +30974,25 @@ 1358223360,1358223631,GB 1358223632,1358223663,DE 1358223664,1358223671,GB -1358223672,1358223727,DE -1358223728,1358223775,GB +1358223672,1358223719,DE +1358223720,1358223775,GB 1358223776,1358223843,DE 1358223844,1358223871,GB -1358223872,1358223911,DE +1358223872,1358223887,NL +1358223888,1358223911,DE 1358223912,1358223927,NL -1358223928,1358223967,DE -1358223968,1358224055,NL -1358224056,1358224511,DE +1358223928,1358223975,DE +1358223976,1358223991,NL +1358223992,1358223999,DE +1358224000,1358224079,NL +1358224080,1358224511,DE 1358224512,1358224519,BE 1358224520,1358224611,DE 1358224612,1358224651,BE 1358224652,1358224655,DE 1358224656,1358224719,BE -1358224720,1358224927,DE -1358224928,1358225127,IT +1358224720,1358224959,DE +1358224960,1358225127,IT 1358225128,1358225407,DE 1358225408,1358229503,RU 1358229504,1358229631,DE @@ -30142,9 +31036,7 @@ 1358295040,1358299135,RU 1358299136,1358303231,DZ 1358303232,1358307327,RU -1358307328,1358313215,DE -1358313216,1358313727,ES -1358313728,1358315519,DE +1358307328,1358315519,DE 1358315520,1358323711,RU 1358323712,1358327807,LU 1358327808,1358328671,DE @@ -30275,7 +31167,7 @@ 1358524416,1358528511,DE 1358528512,1358536703,RU 1358536704,1358540799,HU -1358540800,1358544895,RU +1358540800,1358548991,RU 1358548992,1358553087,JO 1358553088,1358557183,UA 1358557184,1358559503,IE @@ -30303,7 +31195,7 @@ 1358667776,1358668067,PT 1358668068,1358668071,GB 1358668072,1358668271,PT -1358668272,1358668279,GB +1358668272,1358668279,ES 1358668280,1358668359,PT 1358668360,1358668367,GB 1358668368,1358668463,PT @@ -30317,23 +31209,23 @@ 1358668928,1358668959,ES 1358668960,1358669351,PT 1358669352,1358669359,GB -1358669360,1358669431,PT -1358669432,1358669439,GB -1358669440,1358669455,PT -1358669456,1358669471,GB +1358669360,1358669463,PT +1358669464,1358669471,GB 1358669472,1358669503,PT 1358669504,1358669519,GB 1358669520,1358669543,PT 1358669544,1358669551,GB 1358669552,1358669975,PT -1358669976,1358669999,GB +1358669976,1358669983,GB +1358669984,1358669991,PT +1358669992,1358669999,GB 1358670000,1358670015,PT 1358670016,1358670023,GB 1358670024,1358670071,PT 1358670072,1358670079,GB 1358670080,1358670183,PT -1358670184,1358670207,GB -1358670208,1358671415,PT +1358670184,1358670191,GB +1358670192,1358671415,PT 1358671416,1358671423,GB 1358671424,1358671431,PT 1358671432,1358671439,GB @@ -30435,9 +31327,7 @@ 1358785088,1358785151,NL 1358785152,1358786559,GB 1358786560,1358787071,NL -1358787072,1358789167,GB -1358789168,1358789183,IE -1358789184,1358790655,GB +1358787072,1358790655,GB 1358790656,1358798847,IR 1358798848,1358799359,DE 1358799360,1358802943,HR @@ -30457,12 +31347,9 @@ 1358860288,1358861311,GB 1358861312,1358861823,DE 1358861824,1358862335,FR -1358862336,1358862591,US -1358862592,1358862847,GB -1358862848,1358863103,DK -1358863104,1358863359,GB -1358863360,1358863615,US -1358863616,1358864383,GB +1358862336,1358862847,US +1358862848,1358863359,DK +1358863360,1358864383,US 1358864384,1358864399,CH 1358864400,1358864407,IN 1358864408,1358864535,CH @@ -30693,7 +31580,9 @@ 1359467776,1359467815,US 1359467816,1359467903,DE 1359467904,1359468031,US -1359468032,1359468639,DE +1359468032,1359468575,DE +1359468576,1359468583,SG +1359468584,1359468639,DE 1359468640,1359468655,SG 1359468656,1359468671,JP 1359468672,1359468695,SG @@ -30863,7 +31752,7 @@ 1360351232,1360355327,AZ 1360355328,1360359423,EG 1360359424,1360363519,AT -1360363520,1360367615,IT +1360363520,1360365567,IT 1360367616,1360371711,IE 1360371712,1360375807,TR 1360375808,1360379903,NL @@ -30913,6 +31802,7 @@ 1360556032,1360564223,RU 1360564224,1360568319,AT 1360568320,1360572415,ES +1360572416,1360576511,RU 1360576512,1360580607,GB 1360580608,1360584703,UA 1360584704,1360588799,IT @@ -30924,7 +31814,9 @@ 1360613376,1360617471,SE 1360617472,1360621567,IT 1360621568,1360625663,ES -1360625664,1360627455,DE +1360625664,1360626687,DE +1360626688,1360627199,LB +1360627200,1360627455,DE 1360627456,1360627743,LB 1360627744,1360627967,DE 1360627968,1360628095,IQ @@ -31432,6 +32324,7 @@ 1361038312,1361038319,NL 1361038320,1361038335,US 1361038336,1361039359,NL +1361039360,1361043455,PL 1361043456,1361051647,NO 1361051648,1362100223,ES 1362100224,1362395135,FR @@ -31642,9 +32535,13 @@ 1365042048,1365042055,GB 1365042056,1365042175,LU 1365042176,1365044479,FR -1365044480,1365044655,LU +1365044480,1365044607,LU +1365044608,1365044639,BE +1365044640,1365044655,LU 1365044656,1365044719,FR -1365044720,1365044895,LU +1365044720,1365044815,LU +1365044816,1365044831,BE +1365044832,1365044895,LU 1365044896,1365044911,FR 1365044912,1365044959,LU 1365044960,1365044975,BE @@ -31742,7 +32639,9 @@ 1365159936,1365164031,HU 1365164032,1365166255,GB 1365166256,1365166271,IE -1365166272,1365172223,GB +1365166272,1365166303,GB +1365166304,1365166311,BD +1365166312,1365172223,GB 1365172224,1365176319,LV 1365176320,1365180415,HU 1365180416,1365183231,DE @@ -31755,9 +32654,27 @@ 1365204992,1365209087,CZ 1365209088,1365213183,BE 1365213184,1365217279,RU -1365217280,1365217791,GB -1365217792,1365217823,US -1365217824,1365218047,GB +1365217280,1365217567,GB +1365217568,1365217575,PT +1365217576,1365217591,GB +1365217592,1365217599,EG +1365217600,1365217631,GB +1365217632,1365217671,US +1365217672,1365217687,IL +1365217688,1365217695,KW +1365217696,1365217703,GB +1365217704,1365217711,AU +1365217712,1365217791,GB +1365217792,1365217807,BD +1365217808,1365217815,US +1365217816,1365217831,GB +1365217832,1365217839,TR +1365217840,1365217879,GB +1365217880,1365217919,US +1365217920,1365217975,GB +1365217976,1365218031,US +1365218032,1365218039,CA +1365218040,1365218047,GB 1365218048,1365218303,US 1365218304,1365218311,CA 1365218312,1365218319,AR @@ -31770,11 +32687,11 @@ 1365218408,1365218415,IN 1365218416,1365218431,GB 1365218432,1365218439,EG -1365218440,1365218447,GB +1365218440,1365218447,ZA 1365218448,1365218455,CA 1365218456,1365218459,GB 1365218460,1365218463,US -1365218464,1365218471,EG +1365218464,1365218471,HK 1365218472,1365218479,GB 1365218480,1365218511,GR 1365218512,1365218519,AU @@ -31791,8 +32708,7 @@ 1365218928,1365218943,BR 1365218944,1365218951,IN 1365218952,1365218959,NL -1365218960,1365218967,GB -1365218968,1365218975,US +1365218960,1365218975,US 1365218976,1365219007,CN 1365219008,1365219023,US 1365219024,1365219031,DK @@ -31858,8 +32774,7 @@ 1365219984,1365219991,IT 1365219992,1365220007,EE 1365220008,1365220015,ES -1365220016,1365220023,GB -1365220024,1365220031,US +1365220016,1365220031,US 1365220032,1365220127,CN 1365220128,1365220143,TR 1365220144,1365220151,IL @@ -31885,10 +32800,7 @@ 1365220440,1365220471,GB 1365220472,1365220479,US 1365220480,1365220487,AU -1365220488,1365220495,GB -1365220496,1365220503,US -1365220504,1365220511,GB -1365220512,1365220523,US +1365220488,1365220523,US 1365220524,1365220527,GB 1365220528,1365220535,IS 1365220536,1365220551,GB @@ -31898,7 +32810,8 @@ 1365220584,1365220599,TR 1365220600,1365220607,GR 1365220608,1365220615,TR -1365220616,1365220631,US +1365220616,1365220623,US +1365220624,1365220631,KW 1365220632,1365220639,GR 1365220640,1365220663,GB 1365220664,1365220679,US @@ -31907,35 +32820,35 @@ 1365220728,1365220735,JO 1365220736,1365220767,US 1365220768,1365220775,GR -1365220776,1365220783,JO +1365220776,1365220783,US 1365220784,1365220791,IN 1365220792,1365220799,KW 1365220800,1365220807,RU -1365220808,1365220815,GB -1365220816,1365220823,IN +1365220808,1365220815,US +1365220816,1365220823,KW 1365220824,1365220831,GB 1365220832,1365220847,IT 1365220848,1365220855,AU -1365220856,1365220895,US -1365220896,1365220903,GR +1365220856,1365220903,US 1365220904,1365220911,CA -1365220912,1365220919,GB +1365220912,1365220919,US 1365220920,1365220927,KW 1365220928,1365220935,IT 1365220936,1365220939,AR 1365220940,1365220943,US -1365220944,1365220975,GB +1365220944,1365220959,GB +1365220960,1365220967,US +1365220968,1365220975,GB 1365220976,1365220979,US 1365220980,1365220983,GB 1365220984,1365220991,BR 1365220992,1365220999,ZA -1365221000,1365221007,TR -1365221008,1365221023,US +1365221000,1365221023,US 1365221024,1365221031,TR 1365221032,1365221047,IL 1365221048,1365221055,GB 1365221056,1365221063,KW -1365221064,1365221071,GB +1365221064,1365221071,MY 1365221072,1365221087,ES 1365221088,1365221119,US 1365221120,1365221375,GB @@ -31956,6 +32869,7 @@ 1369559040,1369563135,RU 1369563136,1369567231,PL 1369567232,1369571327,BG +1369636864,1369702399,DE 1369702400,1369833471,BE 1369833472,1369964543,NO 1369964544,1369997311,GB @@ -32147,21 +33061,29 @@ 1372651520,1372684287,FI 1372684288,1372684415,DE 1372684416,1372684543,EU -1372684544,1372685631,DE -1372685632,1372685655,EU +1372684544,1372685567,DE +1372685568,1372685655,EU 1372685656,1372685663,DE 1372685664,1372685695,EU 1372685696,1372685823,DE 1372685824,1372685887,EU 1372685888,1372686335,DE 1372686336,1372687359,EU -1372687360,1372687711,DE +1372687360,1372687487,DE +1372687488,1372687551,EU +1372687552,1372687615,DE +1372687616,1372687679,EU +1372687680,1372687711,DE 1372687712,1372687719,EU 1372687720,1372687727,DE -1372687728,1372687735,EU -1372687736,1372688199,DE +1372687728,1372687743,EU +1372687744,1372688199,DE 1372688200,1372688223,EU -1372688224,1372689839,DE +1372688224,1372688351,DE +1372688352,1372688383,EU +1372688384,1372689695,DE +1372689696,1372689791,EU +1372689792,1372689839,DE 1372689840,1372689855,EU 1372689856,1372691455,DE 1372691456,1372691711,US @@ -32180,7 +33102,8 @@ 1372694816,1372694831,EU 1372694832,1372695039,DE 1372695040,1372695167,EU -1372695168,1372695551,DE +1372695168,1372695423,DE +1372695424,1372695551,EU 1372695552,1372695807,CZ 1372695808,1372696007,DK 1372696008,1372696063,EU @@ -32217,7 +33140,7 @@ 1372717056,1372749823,PL 1372749824,1372782591,DE 1372782592,1372815359,RU -1372815360,1372848127,IT +1372815360,1372848127,SE 1372848128,1373110271,TR 1373110272,1373175807,SE 1373175808,1373241343,AT @@ -32304,7 +33227,9 @@ 1382154240,1382170623,FR 1382170624,1382171776,DE 1382171777,1382171791,CH -1382171792,1382173663,DE +1382171792,1382172215,DE +1382172216,1382172223,CH +1382172224,1382173663,DE 1382173664,1382173671,GB 1382173672,1382173675,DE 1382173676,1382173679,CH @@ -32314,9 +33239,7 @@ 1382177984,1382178303,LI 1382178304,1382179247,DE 1382179248,1382179279,GB -1382179280,1382179839,DE -1382179840,1382180863,CN -1382180864,1382182327,DE +1382179280,1382182327,DE 1382182328,1382182335,GB 1382182336,1382182547,DE 1382182548,1382182551,CH @@ -32350,12 +33273,13 @@ 1382212224,1382212239,FR 1382212240,1382212287,EU 1382212288,1382212351,NL -1382212352,1382212479,FR -1382212480,1382212607,EU +1382212352,1382212607,EU 1382212608,1382212863,FR 1382212864,1382213183,NL 1382213184,1382213199,EU -1382213200,1382214079,NL +1382213200,1382213375,NL +1382213376,1382213631,EU +1382213632,1382214079,NL 1382214080,1382214111,GB 1382214112,1382214879,NL 1382214880,1382214895,GB @@ -32363,9 +33287,7 @@ 1382216832,1382216895,GB 1382216896,1382216959,NL 1382216960,1382217215,GB -1382217216,1382217727,NL -1382217728,1382217983,GB -1382217984,1382218399,NL +1382217216,1382218399,NL 1382218400,1382218447,GB 1382218448,1382218455,NL 1382218456,1382218495,GB @@ -32376,7 +33298,9 @@ 1382218912,1382218959,NL 1382218960,1382218991,GB 1382218992,1382219775,NL -1382219776,1382223551,SE +1382219776,1382223327,SE +1382223328,1382223359,FI +1382223360,1382223551,SE 1382223552,1382223615,NO 1382223616,1382224287,SE 1382224288,1382224319,NO @@ -32441,9 +33365,10 @@ 1383098112,1383098367,DE 1383098368,1383099391,GB 1383099392,1383099903,DE -1383099904,1383100159,GB -1383100160,1383100287,FR -1383100288,1383100831,GB +1383099904,1383099967,FR +1383099968,1383100159,GB +1383100160,1383100415,FR +1383100416,1383100831,GB 1383100832,1383100847,IE 1383100848,1383100879,GB 1383100880,1383100895,IE @@ -32455,9 +33380,7 @@ 1383104016,1383104023,ES 1383104024,1383104255,GB 1383104256,1383104511,FR -1383104512,1383111695,JE -1383111696,1383111727,GB -1383111728,1383112703,JE +1383104512,1383112703,JE 1383112704,1383120895,GE 1383120896,1383129031,IT 1383129032,1383129039,ES @@ -32477,38 +33400,20 @@ 1383202816,1383211007,RU 1383211008,1383219199,CY 1383219200,1383220223,AL -1383220224,1383222415,RS -1383222416,1383222431,AL -1383222432,1383222440,RS -1383222441,1383222455,AL -1383222456,1383222459,RS -1383222460,1383222471,AL -1383222472,1383222479,RS -1383222480,1383222487,AL -1383222488,1383223119,RS -1383223120,1383223123,AL -1383223124,1383223131,RS -1383223132,1383223135,AL -1383223136,1383223191,RS -1383223192,1383223199,AL -1383223200,1383223208,RS -1383223209,1383223215,AL -1383223216,1383223231,RS -1383223232,1383223239,AL -1383223240,1383223551,RS -1383223552,1383223567,AL -1383223568,1383223583,RS -1383223584,1383223615,AL -1383223616,1383223631,RS -1383223632,1383223663,AL -1383223664,1383223695,RS +1383220224,1383222447,RS +1383222448,1383222455,AL +1383222456,1383223695,RS 1383223696,1383223703,AL -1383223704,1383223711,RS -1383223712,1383223727,AL -1383223728,1383223759,RS -1383223760,1383223807,AL -1383223808,1383225599,RS -1383225600,1383226623,AL +1383223704,1383225759,RS +1383225760,1383225771,AL +1383225772,1383225807,RS +1383225808,1383225808,AL +1383225809,1383225819,RS +1383225820,1383225827,AL +1383225828,1383226091,RS +1383226092,1383226095,AL +1383226096,1383226271,RS +1383226272,1383226623,AL 1383226624,1383226751,RS 1383226752,1383226815,AL 1383226816,1383227391,RS @@ -32818,6 +33723,8 @@ 1385259008,1385267199,IT 1385267200,1385275391,SE 1385275392,1385283583,IT +1385287680,1385289727,IS +1385289728,1385291775,NO 1385291776,1385299967,TR 1385299968,1385308159,BG 1385308160,1385309439,BE @@ -32940,8 +33847,8 @@ 1386348544,1386414079,RU 1386414080,1386479615,GB 1386479616,1386545151,NO -1386545152,1386582015,DE -1386582016,1386594303,US +1386545152,1386586111,DE +1386586112,1386594303,US 1386594304,1386602495,DE 1386602496,1386610687,US 1386610688,1386676223,IL @@ -32979,18 +33886,16 @@ 1388371968,1388380159,CH 1388380160,1388388895,IT 1388388896,1388388927,NG -1388388928,1388388935,IT -1388388936,1388388991,NG -1388388992,1388389119,IT -1388389120,1388389135,NG -1388389136,1388389447,IT -1388389448,1388389471,NG -1388389472,1388389567,IT +1388388928,1388388943,IT +1388388944,1388388959,NG +1388388960,1388388967,IT +1388388968,1388388991,NG +1388388992,1388389447,IT +1388389448,1388389455,NG +1388389456,1388389567,IT 1388389568,1388389631,NG -1388389632,1388389903,IT -1388389904,1388389911,NG -1388389912,1388389919,IT -1388389920,1388390015,NG +1388389632,1388389927,IT +1388389928,1388390015,NG 1388390016,1388390143,IT 1388390144,1388394495,NG 1388394496,1388395519,IT @@ -33079,6 +33984,7 @@ 1388642304,1388650495,FI 1388650496,1388658687,PL 1388658688,1388666879,GB +1388666880,1388675071,FR 1388675072,1388675327,NL 1388675328,1388675583,EU 1388675584,1388676863,DE @@ -33102,12 +34008,13 @@ 1388691456,1388699647,NL 1388699648,1388707839,SE 1388707840,1388708863,RU -1388708864,1388709119,LB +1388708864,1388709119,LT 1388709120,1388712191,RU 1388712192,1388712703,LT 1388712704,1388713215,LB -1388713216,1388713727,TJ -1388713728,1388714239,LB +1388713216,1388713727,RU +1388713728,1388713983,LT +1388713984,1388714239,LB 1388714240,1388714495,LT 1388714496,1388714751,RU 1388714752,1388715007,IQ @@ -33140,18 +34047,26 @@ 1388740608,1388740623,GB 1388740624,1388740719,IE 1388740720,1388740735,GB -1388740736,1388741745,IE +1388740736,1388741375,IE +1388741376,1388741443,GB +1388741444,1388741535,IE +1388741536,1388741631,GB +1388741632,1388741659,IE +1388741660,1388741723,GB +1388741724,1388741745,IE 1388741746,1388741747,GB 1388741748,1388741751,IE 1388741752,1388741759,GB -1388741760,1388741767,IE -1388741768,1388741787,GB -1388741788,1388741795,IE -1388741796,1388741819,GB -1388741820,1388741859,IE +1388741760,1388741775,IE +1388741776,1388741787,GB +1388741788,1388741799,IE +1388741800,1388741800,GB +1388741801,1388741807,IE +1388741808,1388741815,GB +1388741816,1388741859,IE 1388741860,1388741863,GB -1388741864,1388742007,IE -1388742008,1388742015,GB +1388741864,1388742011,IE +1388742012,1388742015,GB 1388742016,1388742019,IE 1388742020,1388742023,GB 1388742024,1388742024,IE @@ -33159,12 +34074,14 @@ 1388742032,1388742655,IE 1388742656,1388742719,GB 1388742720,1388742731,IE -1388742732,1388742739,GB -1388742740,1388743043,IE +1388742732,1388742735,IR +1388742736,1388743043,IE 1388743044,1388743055,GB -1388743056,1388743435,IE -1388743436,1388743439,GB -1388743440,1388744087,IE +1388743056,1388743439,IE +1388743440,1388743451,GB +1388743452,1388743919,IE +1388743920,1388743935,GB +1388743936,1388744087,IE 1388744088,1388744095,GB 1388744096,1388744117,IE 1388744118,1388744127,GB @@ -33178,27 +34095,27 @@ 1388745216,1388745343,GB 1388745344,1388745499,IE 1388745500,1388745503,GB -1388745504,1388745651,IE +1388745504,1388745559,IE +1388745560,1388745563,GB +1388745564,1388745651,IE 1388745652,1388745663,GB 1388745664,1388745683,IE 1388745684,1388745727,GB -1388745728,1388745915,IE -1388745916,1388745919,GB +1388745728,1388745911,IE +1388745912,1388745919,GB 1388745920,1388745927,IE 1388745928,1388745935,GB -1388745936,1388745971,IE -1388745972,1388745975,GB -1388745976,1388746155,IE +1388745936,1388746155,IE 1388746156,1388746159,GB -1388746160,1388746171,IE -1388746172,1388746239,GB +1388746160,1388746175,IE +1388746176,1388746239,GB 1388746240,1388746659,IE 1388746660,1388746671,GB -1388746672,1388746703,IE +1388746672,1388746675,IE +1388746676,1388746695,GB +1388746696,1388746703,IE 1388746704,1388746719,GB -1388746720,1388746859,IE -1388746860,1388746863,GB -1388746864,1388746895,IE +1388746720,1388746895,IE 1388746896,1388746903,GB 1388746904,1388746959,IE 1388746960,1388746975,GB @@ -33215,16 +34132,18 @@ 1388747792,1388747835,IE 1388747836,1388747839,GB 1388747840,1388747859,IE -1388747860,1388747863,GB -1388747864,1388747891,IE +1388747860,1388747875,GB +1388747876,1388747891,IE 1388747892,1388747895,GB 1388747896,1388747983,IE -1388747984,1388748031,GB -1388748032,1388748179,IE -1388748180,1388748183,GB -1388748184,1388748223,IE -1388748224,1388748319,GB -1388748320,1388748349,IE +1388747984,1388747987,GB +1388747988,1388747999,IE +1388748000,1388748031,GB +1388748032,1388748223,IE +1388748224,1388748255,GB +1388748256,1388748287,IE +1388748288,1388748295,GB +1388748296,1388748349,IE 1388748350,1388748351,GB 1388748352,1388748799,IE 1388748800,1388756991,RU @@ -33232,12 +34151,16 @@ 1388765184,1388773375,GB 1388773376,1388781567,NO 1388781568,1388789759,ES -1388789760,1388789887,NL -1388789888,1388789951,GB -1388789952,1388797951,NL +1388789760,1388797951,NL 1388797952,1388806143,RU -1388806144,1388814335,DE -1388814336,1388821119,AX +1388806144,1388807679,DE +1388807680,1388807711,BZ +1388807712,1388814335,DE +1388814336,1388815103,AX +1388815104,1388815231,FI +1388815232,1388818687,AX +1388818688,1388818815,FI +1388818816,1388821119,AX 1388821120,1388821150,SE 1388821151,1388821247,AX 1388821248,1388822527,SE @@ -33345,7 +34268,8 @@ 1389213208,1389213215,LY 1389213216,1389213311,A2 1389213312,1389213343,LY -1389213344,1389215743,A2 +1389213344,1389214719,A2 +1389214720,1389215743,LY 1389215744,1389217791,AF 1389217792,1389218303,A2 1389218304,1389219839,AF @@ -33658,13 +34582,8 @@ 1389562880,1389563135,IT 1389563136,1389563391,DE 1389563392,1389563647,IT -1389563648,1389564159,DE -1389564160,1389564415,BR -1389564416,1389576191,DE +1389563648,1389576191,DE 1389576192,1389592575,GB -1389592576,1389592831,A2 -1389592832,1389593087,CY -1389593088,1389608959,A2 1389608960,1389625343,DK 1389625344,1389641727,DE 1389641728,1389658111,JO @@ -33676,7 +34595,9 @@ 1389756416,1389772799,SE 1389772800,1389780991,SI 1389780992,1389782527,HR -1389782528,1389783039,SI +1389782528,1389782543,SI +1389782544,1389782559,HR +1389782560,1389783039,SI 1389783040,1389784063,BA 1389784064,1389788671,SI 1389788672,1389789183,RS @@ -33744,7 +34665,9 @@ 1398896640,1398898687,CH 1398898688,1398931455,ES 1398931456,1398964223,GB -1398964224,1398965503,NL +1398964224,1398964543,NL +1398964544,1398964559,US +1398964560,1398965503,NL 1398965504,1398965759,US 1398965760,1398966015,DE 1398966016,1398966839,NL @@ -33789,13 +34712,17 @@ 1399717888,1399848959,AE 1399848960,1400111103,FR 1400111104,1400373247,NL -1400373248,1400705279,DE +1400373248,1400635391,DE +1400635392,1400700927,EU +1400700928,1400705279,DE 1400705280,1400706047,EU 1400706048,1400707071,DE 1400707072,1400709119,EU 1400709120,1400710143,DE 1400710144,1400710399,EU -1400710400,1400712703,DE +1400710400,1400712191,DE +1400712192,1400712447,EU +1400712448,1400712703,DE 1400712704,1400712959,EU 1400712960,1400716287,DE 1400716288,1400717311,EU @@ -33917,15 +34844,15 @@ 1401565184,1401567231,RU 1401567232,1401569279,GB 1401569280,1401585663,DE -1401585664,1401599167,GB -1401599168,1401599231,IE -1401599232,1401602047,GB +1401585664,1401602047,GB 1401602048,1401618431,ES 1401618432,1401634815,AM 1401634816,1401651199,HR 1401651200,1401667583,RU 1401667584,1401683967,IT -1401683968,1401684479,SE +1401683968,1401684067,SE +1401684068,1401684071,NO +1401684072,1401684479,SE 1401684480,1401684511,DK 1401684512,1401684543,SE 1401684544,1401684607,DK @@ -33961,7 +34888,9 @@ 1401709312,1401709567,GB 1401709568,1401714047,SE 1401714048,1401714063,FR -1401714064,1401717759,SE +1401714064,1401715455,SE +1401715456,1401715459,US +1401715460,1401717759,SE 1401717760,1401718015,NL 1401718016,1401719935,SE 1401719936,1401719951,DK @@ -33990,7 +34919,8 @@ 1401743344,1401743359,GB 1401743360,1401745439,SE 1401745440,1401745443,GB -1401745444,1401745487,SE +1401745444,1401745447,US +1401745448,1401745487,SE 1401745488,1401745503,ES 1401745504,1401745919,SE 1401745920,1401745935,IT @@ -34321,7 +35251,8 @@ 1404198912,1404200959,SE 1404200960,1404203007,NL 1404203008,1404204800,HR -1404204801,1404207103,SE +1404204801,1404205055,SE +1404205056,1404207103,HR 1404207104,1404210175,NO 1404210176,1404212223,LV 1404212224,1404215295,SE @@ -34351,10 +35282,14 @@ 1404645376,1404645887,HR 1404645888,1404764159,SE 1404764160,1404768511,NL -1404768512,1404802047,SE +1404768512,1404768767,SE +1404768768,1404769279,NL +1404769280,1404770303,SE +1404770304,1404772351,NL +1404772352,1404802047,SE 1404802048,1404803071,EE -1404803072,1404803583,LV -1404803584,1404805119,SE +1404803072,1404804095,LV +1404804096,1404805119,SE 1404805120,1404813311,AT 1404813312,1404829695,SE 1404829696,1404870655,RU @@ -34389,7 +35324,10 @@ 1406705664,1406708735,IT 1406708736,1406709759,A2 1406709760,1406710015,IT -1406710016,1406713855,A2 +1406710016,1406711295,A2 +1406711296,1406712063,IT +1406712064,1406713343,A2 +1406713344,1406713855,IT 1406713856,1406714879,AT 1406714880,1406715391,NL 1406715392,1406715519,AT @@ -34463,7 +35401,7 @@ 1406935040,1406951423,RU 1406951424,1406959615,PL 1406959616,1406964287,DE -1406964288,1406964319,CH +1406964288,1406964319,NL 1406964320,1406964327,DE 1406964328,1406964351,NL 1406964352,1406964735,DE @@ -34540,9 +35478,10 @@ 1407517384,1407517391,CD 1407517392,1407517415,A2 1407517416,1407517423,NG -1407517424,1407517431,A2 +1407517424,1407517431,ZW 1407517432,1407517439,NG -1407517440,1407517887,A2 +1407517440,1407517695,A2 +1407517696,1407517887,NG 1407517888,1407517919,CD 1407517920,1407517951,A2 1407517952,1407518015,SL @@ -34551,10 +35490,9 @@ 1407518040,1407518047,CD 1407518048,1407518063,NG 1407518064,1407518079,A2 -1407518080,1407518111,FR -1407518112,1407518119,A2 -1407518120,1407518127,NG -1407518128,1407518135,KE +1407518080,1407518111,LR +1407518112,1407518127,NG +1407518128,1407518135,ZW 1407518136,1407518143,GH 1407518144,1407518151,A2 1407518152,1407518159,ZA @@ -34565,9 +35503,10 @@ 1407518192,1407518199,A2 1407518200,1407518207,AE 1407518208,1407518215,ZW -1407518216,1407518231,A2 -1407518232,1407518247,NG -1407518248,1407518263,A2 +1407518216,1407518239,A2 +1407518240,1407518247,NG +1407518248,1407518255,A2 +1407518256,1407518263,CD 1407518264,1407518269,GH 1407518270,1407518335,A2 1407518336,1407518343,CG @@ -34575,11 +35514,12 @@ 1407518352,1407518359,A2 1407518360,1407518367,NG 1407518368,1407518375,ZA -1407518376,1407518783,A2 +1407518376,1407518383,CD +1407518384,1407518783,A2 1407518784,1407518815,CD 1407518816,1407518831,A2 1407518832,1407518847,NG -1407518848,1407518911,A2 +1407518848,1407518911,FR 1407518912,1407518943,NG 1407518944,1407518975,A2 1407518976,1407518983,NG @@ -34587,7 +35527,7 @@ 1407518992,1407518999,NG 1407519000,1407519015,A2 1407519016,1407519023,AO -1407519024,1407519031,NG +1407519024,1407519031,A2 1407519032,1407519039,AO 1407519040,1407519047,NG 1407519048,1407519055,A2 @@ -34613,13 +35553,49 @@ 1407519232,1407519615,NG 1407519616,1407519751,A2 1407519752,1407519767,NG -1407519768,1407519783,A2 -1407519784,1407519791,NG -1407519792,1407519839,A2 +1407519768,1407519775,GN +1407519776,1407519783,A2 +1407519784,1407519823,NG +1407519824,1407519831,A2 +1407519832,1407519839,SD 1407519840,1407519855,NG -1407519856,1407519863,A2 +1407519856,1407519863,GN 1407519864,1407519871,NG -1407519872,1407520271,A2 +1407519872,1407519879,A2 +1407519880,1407519895,NG +1407519896,1407519903,GN +1407519904,1407519911,NG +1407519912,1407519919,GN +1407519920,1407519943,A2 +1407519944,1407519951,NG +1407519952,1407519959,A2 +1407519960,1407519983,NG +1407519984,1407519991,A2 +1407519992,1407519999,NG +1407520000,1407520007,CD +1407520008,1407520023,NG +1407520024,1407520031,A2 +1407520032,1407520039,GN +1407520040,1407520047,A2 +1407520048,1407520063,ZW +1407520064,1407520071,A2 +1407520072,1407520079,CM +1407520080,1407520087,NG +1407520088,1407520103,GN +1407520104,1407520111,SD +1407520112,1407520119,GN +1407520120,1407520127,NE +1407520128,1407520151,GN +1407520152,1407520152,A2 +1407520153,1407520159,GN +1407520160,1407520167,IL +1407520168,1407520175,GN +1407520176,1407520207,A2 +1407520208,1407520215,NG +1407520216,1407520223,NE +1407520224,1407520231,SD +1407520232,1407520239,NG +1407520240,1407520271,A2 1407520272,1407520279,NG 1407520280,1407520303,A2 1407520304,1407520327,NG @@ -34629,7 +35605,9 @@ 1407520360,1407520367,CD 1407520368,1407520375,A2 1407520376,1407520397,NG -1407520398,1407520439,A2 +1407520398,1407520415,A2 +1407520416,1407520423,AO +1407520424,1407520439,A2 1407520440,1407520447,CD 1407520448,1407520463,NG 1407520464,1407520519,A2 @@ -34638,8 +35616,10 @@ 1407520544,1407520551,A2 1407520552,1407520559,NG 1407520560,1407520567,SL -1407520568,1407520575,NG -1407520576,1407520607,A2 +1407520568,1407520583,NG +1407520584,1407520591,A2 +1407520592,1407520599,NG +1407520600,1407520607,A2 1407520608,1407520615,AO 1407520616,1407520623,A2 1407520624,1407520631,NG @@ -34650,85 +35630,146 @@ 1407520688,1407520695,NG 1407520696,1407520711,A2 1407520712,1407520719,NG -1407520720,1407520759,A2 +1407520720,1407520735,A2 +1407520736,1407520743,LR +1407520744,1407520751,NG +1407520752,1407520759,A2 1407520760,1407520767,CD 1407520768,1407520775,ZW -1407520776,1407520783,A2 +1407520776,1407520783,CD 1407520784,1407520791,SD -1407520792,1407520847,A2 +1407520792,1407520807,A2 +1407520808,1407520815,CI +1407520816,1407520823,GQ +1407520824,1407520831,CI +1407520832,1407520839,NG +1407520840,1407520847,A2 1407520848,1407520855,ZM 1407520856,1407520863,A2 -1407520864,1407520871,NG -1407520872,1407520895,A2 +1407520864,1407520871,TZ +1407520872,1407520879,CD +1407520880,1407520887,ZM +1407520888,1407520895,CD 1407520896,1407520903,AO 1407520904,1407520911,NG 1407520912,1407520919,ZW 1407520920,1407520927,IQ -1407520928,1407520951,A2 -1407520952,1407520959,ZW +1407520928,1407520935,A2 +1407520936,1407520943,CD +1407520944,1407520951,A2 +1407520952,1407520959,ZM 1407520960,1407520967,TZ -1407520968,1407520975,CD -1407520976,1407520983,A2 -1407520984,1407520991,ZM -1407520992,1407521023,A2 -1407521024,1407521031,ZW -1407521032,1407521055,A2 +1407520968,1407520975,A2 +1407520976,1407520991,ZM +1407520992,1407520999,IQ +1407521000,1407521023,CD +1407521024,1407521031,ZM +1407521032,1407521047,A2 +1407521048,1407521055,NG 1407521056,1407521063,KE -1407521064,1407521127,A2 +1407521064,1407521071,A2 +1407521072,1407521079,NG +1407521080,1407521087,UG +1407521088,1407521095,NG +1407521096,1407521103,A2 +1407521104,1407521111,MZ +1407521112,1407521119,SL +1407521120,1407521127,A2 1407521128,1407521135,NG -1407521136,1407521215,A2 +1407521136,1407521143,CD +1407521144,1407521151,ZM +1407521152,1407521159,NG +1407521160,1407521167,ZW +1407521168,1407521175,SD +1407521176,1407521183,IQ +1407521184,1407521199,CD +1407521200,1407521207,A2 +1407521208,1407521215,IQ 1407521216,1407521223,NG -1407521224,1407521415,A2 +1407521224,1407521231,TZ +1407521232,1407521239,LR +1407521240,1407521247,A2 +1407521248,1407521279,GH +1407521280,1407521415,A2 1407521416,1407521423,LR 1407521424,1407522319,A2 -1407522320,1407522327,BF +1407522320,1407522327,TG 1407522328,1407522335,NG 1407522336,1407522351,SO 1407522352,1407522359,CD 1407522360,1407522367,NG -1407522368,1407522375,A2 -1407522376,1407522383,LR -1407522384,1407522407,A2 -1407522408,1407522415,LR -1407522416,1407522431,A2 +1407522368,1407522383,GQ +1407522384,1407522391,A2 +1407522392,1407522407,NG +1407522408,1407522415,ZW +1407522416,1407522423,NG +1407522424,1407522431,A2 1407522432,1407522439,IQ 1407522440,1407522440,NG -1407522441,1407522463,A2 +1407522441,1407522447,A2 +1407522448,1407522455,UG +1407522456,1407522463,ML 1407522464,1407522479,NG -1407522480,1407522495,A2 +1407522480,1407522487,TZ +1407522488,1407522495,ZW 1407522496,1407522503,NG -1407522504,1407522535,A2 -1407522536,1407522559,NG -1407522560,1407522567,A2 +1407522504,1407522527,A2 +1407522528,1407522535,ZM +1407522536,1407522551,NG +1407522552,1407522559,UG +1407522560,1407522567,MZ 1407522568,1407522575,NG 1407522576,1407522583,A2 1407522584,1407522591,NG -1407522592,1407522615,A2 -1407522616,1407522623,NG -1407522624,1407522639,A2 +1407522592,1407522599,A2 +1407522600,1407522607,ZM +1407522608,1407522615,A2 +1407522616,1407522631,NG +1407522632,1407522639,MW 1407522640,1407522647,GQ 1407522648,1407522655,NG -1407522656,1407522671,A2 +1407522656,1407522663,CI +1407522664,1407522671,A2 1407522672,1407522679,ZM 1407522680,1407522687,IQ -1407522688,1407522695,LR -1407522696,1407522703,A2 -1407522704,1407522711,NG -1407522712,1407522727,A2 -1407522728,1407522735,CD -1407522736,1407522775,A2 +1407522688,1407522711,NG +1407522712,1407522719,BJ +1407522720,1407522727,A2 +1407522728,1407522735,ZW +1407522736,1407522751,NG +1407522752,1407522767,ZM +1407522768,1407522775,A2 1407522776,1407522791,NG 1407522792,1407522799,A2 1407522800,1407522807,ZM -1407522808,1407522815,A2 -1407522816,1407523071,ZW -1407523072,1407523279,A2 +1407522808,1407522815,NG +1407522816,1407522831,A2 +1407522832,1407522839,IQ +1407522840,1407522871,A2 +1407522872,1407522879,IQ +1407522880,1407522991,A2 +1407522992,1407522999,CD +1407523000,1407523071,A2 +1407523072,1407523088,NG +1407523089,1407523095,A2 +1407523096,1407523103,NG +1407523104,1407523111,UG +1407523112,1407523119,ZW +1407523120,1407523127,CD +1407523128,1407523135,A2 +1407523136,1407523143,BJ +1407523144,1407523159,A2 +1407523160,1407523167,LR +1407523168,1407523183,UG +1407523184,1407523215,NG +1407523216,1407523223,BI +1407523224,1407523247,AO +1407523248,1407523279,NG 1407523280,1407523287,MZ -1407523288,1407523295,NG -1407523296,1407523327,A2 +1407523288,1407523311,NG +1407523312,1407523327,BJ 1407523328,1407523335,MW -1407523336,1407523343,A2 -1407523344,1407523351,NG +1407523336,1407523351,A2 1407523352,1407523359,LU 1407523360,1407523367,ZW 1407523368,1407523391,A2 @@ -34738,54 +35779,130 @@ 1407523536,1407523551,NG 1407523552,1407523559,CM 1407523560,1407523567,KE -1407523568,1407523575,A2 -1407523576,1407523583,MW -1407523584,1407523839,A2 +1407523568,1407523839,A2 1407523840,1407524351,MW 1407524352,1407524607,GB 1407524608,1407524615,ZW 1407524616,1407524623,CM -1407524624,1407524631,NG -1407524632,1407524639,A2 -1407524640,1407524647,NG +1407524624,1407524631,A2 +1407524632,1407524647,NG 1407524648,1407524655,CD -1407524656,1407524663,NG -1407524664,1407524687,A2 +1407524656,1407524671,NG +1407524672,1407524679,A2 +1407524680,1407524687,LR 1407524688,1407524703,MZ -1407524704,1407524735,A2 -1407524736,1407524743,NG -1407524744,1407524783,A2 +1407524704,1407524711,A2 +1407524712,1407524719,CD +1407524720,1407524727,A2 +1407524728,1407524751,NG +1407524752,1407524759,A2 +1407524760,1407524767,CM +1407524768,1407524775,BW +1407524776,1407524783,A2 1407524784,1407524791,ZW -1407524792,1407524967,A2 +1407524792,1407524799,LR +1407524800,1407524839,A2 +1407524840,1407524847,LR +1407524848,1407524855,A2 +1407524856,1407524863,CD +1407524864,1407524879,A2 +1407524880,1407524887,NG +1407524888,1407524895,A2 +1407524896,1407524903,LR +1407524904,1407524927,NG +1407524928,1407524935,A2 +1407524936,1407524951,NG +1407524952,1407524959,CM +1407524960,1407524967,TZ 1407524968,1407524975,NG -1407524976,1407525071,A2 -1407525072,1407525079,NG -1407525080,1407525247,A2 -1407525248,1407525255,CD +1407524976,1407524991,A2 +1407524992,1407524999,TZ +1407525000,1407525007,A2 +1407525008,1407525015,TZ +1407525016,1407525023,BI +1407525024,1407525031,NG +1407525032,1407525039,A2 +1407525040,1407525047,ZA +1407525048,1407525055,NG +1407525056,1407525063,A2 +1407525064,1407525079,NG +1407525080,1407525087,A2 +1407525088,1407525095,MW +1407525096,1407525111,NG +1407525112,1407525119,ZA +1407525120,1407525127,NG +1407525128,1407525135,SD +1407525136,1407525143,CD +1407525144,1407525151,A2 +1407525152,1407525167,CD +1407525168,1407525175,A2 +1407525176,1407525183,CD +1407525184,1407525191,ZW +1407525192,1407525207,A2 +1407525208,1407525215,CD +1407525216,1407525231,A2 +1407525232,1407525255,CD 1407525256,1407525263,NG -1407525264,1407529023,A2 +1407525264,1407525287,CD +1407525288,1407525303,A2 +1407525304,1407525319,CD +1407525320,1407525327,A2 +1407525328,1407525343,CD +1407525344,1407525471,A2 +1407525472,1407525479,UG +1407525480,1407526711,A2 +1407526712,1407526719,GN +1407526720,1407529023,A2 1407529024,1407529087,NG 1407529088,1407529095,A2 1407529096,1407529103,ZW 1407529104,1407529111,NG 1407529112,1407529127,A2 1407529128,1407529135,ZW -1407529136,1407529143,US +1407529136,1407529143,A2 1407529144,1407529151,ZW 1407529152,1407529183,A2 1407529184,1407529191,NG -1407529192,1407529207,A2 +1407529192,1407529199,A2 +1407529200,1407529207,IQ 1407529208,1407529215,NG 1407529216,1407531007,A2 1407531008,1407531519,NG -1407531520,1407532543,A2 +1407531520,1407531551,CD +1407531552,1407531559,SD +1407531560,1407531567,NG +1407531568,1407531575,CD +1407531576,1407531583,UG +1407531584,1407531591,CD +1407531592,1407531599,A2 +1407531600,1407531607,NG +1407531608,1407531631,CD +1407531632,1407531639,ZM +1407531640,1407531647,CD +1407531648,1407531655,A2 +1407531656,1407531663,CD +1407531664,1407531671,MZ +1407531672,1407531687,CD +1407531688,1407531695,A2 +1407531696,1407531703,CD +1407531704,1407531711,IQ +1407531712,1407531719,A2 +1407531720,1407531735,CD +1407531736,1407531743,ZW +1407531744,1407531751,A2 +1407531752,1407531759,GQ +1407531760,1407531767,ZW +1407531768,1407531775,SD +1407531776,1407532543,A2 1407532544,1407532551,UG 1407532552,1407532559,AO 1407532560,1407532583,A2 1407532584,1407532591,ZW 1407532592,1407532615,A2 1407532616,1407532623,KG -1407532624,1407532663,A2 +1407532624,1407532639,A2 +1407532640,1407532647,NG +1407532648,1407532663,A2 1407532664,1407532671,TZ 1407532672,1407532799,A2 1407532800,1407532927,SO @@ -34818,14 +35935,15 @@ 1407533816,1407533823,NG 1407533824,1407534079,A2 1407534080,1407534335,AE -1407534336,1407534359,A2 +1407534336,1407534343,CM +1407534344,1407534359,A2 1407534360,1407534383,NG 1407534384,1407534391,A2 1407534392,1407534399,AO 1407534400,1407534407,NG 1407534408,1407534415,CI -1407534416,1407534447,A2 -1407534448,1407534463,NG +1407534416,1407534455,A2 +1407534456,1407534463,NG 1407534464,1407534543,A2 1407534544,1407534559,GH 1407534560,1407534567,NG @@ -34840,11 +35958,26 @@ 1407534792,1407534847,A2 1407534848,1407535103,CM 1407535104,1407535615,GA -1407535616,1407535711,A2 +1407535616,1407535623,CD +1407535624,1407535631,IQ +1407535632,1407535639,SD +1407535640,1407535647,A2 +1407535648,1407535663,NG +1407535664,1407535671,A2 +1407535672,1407535679,SD +1407535680,1407535687,GN +1407535688,1407535711,A2 1407535712,1407535719,GB 1407535720,1407535735,A2 1407535736,1407535743,NG -1407535744,1407536127,A2 +1407535744,1407535775,A2 +1407535776,1407535783,GN +1407535784,1407535815,A2 +1407535816,1407535823,NG +1407535824,1407535831,A2 +1407535832,1407535839,GB +1407535840,1407535847,NG +1407535848,1407536127,A2 1407536128,1407536639,GA 1407536640,1407536895,CD 1407536896,1407536903,A2 @@ -34871,34 +36004,43 @@ 1407537184,1407537191,NG 1407537192,1407537199,A2 1407537200,1407537207,NG -1407537208,1407537231,A2 +1407537208,1407537215,BE +1407537216,1407537231,A2 1407537232,1407537255,NG 1407537256,1407537263,A2 1407537264,1407537279,NG 1407537280,1407537287,A2 1407537288,1407537295,NG -1407537296,1407537335,A2 +1407537296,1407537303,UG +1407537304,1407537335,A2 1407537336,1407537351,NG 1407537352,1407537367,A2 1407537368,1407537383,NG -1407537384,1407537431,A2 +1407537384,1407537399,A2 +1407537400,1407537407,BF +1407537408,1407537415,A2 +1407537416,1407537423,GH +1407537424,1407537431,A2 1407537432,1407537455,NG -1407537456,1407537479,A2 +1407537456,1407537463,AO +1407537464,1407537479,A2 1407537480,1407537487,CM 1407537488,1407537495,GH -1407537496,1407537511,NG +1407537496,1407537503,A2 +1407537504,1407537511,NG 1407537512,1407537519,LR 1407537520,1407537535,A2 1407537536,1407537543,LR -1407537544,1407537559,A2 +1407537544,1407537551,AO +1407537552,1407537559,A2 1407537560,1407537567,NG 1407537568,1407537575,A2 1407537576,1407537599,NG -1407537600,1407537623,A2 +1407537600,1407537607,A2 +1407537608,1407537615,CM +1407537616,1407537623,A2 1407537624,1407537639,NG -1407537640,1407537663,A2 -1407537664,1407537671,AO -1407537672,1407537679,A2 +1407537640,1407537679,A2 1407537680,1407537687,IQ 1407537688,1407537703,A2 1407537704,1407537735,NG @@ -34906,35 +36048,61 @@ 1407537752,1407537847,NG 1407537848,1407537855,A2 1407537856,1407537863,NG -1407537864,1407537871,A2 +1407537864,1407537871,TG 1407537872,1407537879,IQ -1407537880,1407537887,A2 -1407537888,1407537895,NG +1407537880,1407537895,A2 1407537896,1407537903,IQ -1407537904,1407537935,A2 +1407537904,1407537911,TG +1407537912,1407537927,A2 +1407537928,1407537935,SL 1407537936,1407537943,GH -1407537944,1407537951,A2 -1407537952,1407537959,NG -1407537960,1407537967,A2 -1407537968,1407537991,NG +1407537944,1407537951,TG +1407537952,1407537959,A2 +1407537960,1407537967,TG +1407537968,1407537975,NG +1407537976,1407537983,A2 +1407537984,1407537991,NG 1407537992,1407537999,IQ 1407538000,1407538023,NG -1407538024,1407538047,A2 +1407538024,1407538031,A2 +1407538032,1407538039,NG +1407538040,1407538047,CD 1407538048,1407538055,NG 1407538056,1407538071,LU 1407538072,1407538079,NG -1407538080,1407538087,A2 +1407538080,1407538087,LR 1407538088,1407538095,AO -1407538096,1407538111,A2 +1407538096,1407538103,CD +1407538104,1407538111,A2 1407538112,1407538119,LR -1407538120,1407538127,NG -1407538128,1407538143,A2 +1407538120,1407538135,NG +1407538136,1407538143,A2 1407538144,1407538151,GN 1407538152,1407538167,A2 1407538168,1407538175,IQ -1407538176,1407538295,A2 +1407538176,1407538183,A2 +1407538184,1407538191,NG +1407538192,1407538199,A2 +1407538200,1407538207,NG +1407538208,1407538208,A2 +1407538209,1407538271,NG +1407538272,1407538279,CO +1407538280,1407538287,A2 +1407538288,1407538295,NG 1407538296,1407538303,AO -1407538304,1407538439,A2 +1407538304,1407538311,NG +1407538312,1407538319,CD +1407538320,1407538327,NG +1407538328,1407538335,CD +1407538336,1407538343,A2 +1407538344,1407538351,CD +1407538352,1407538383,A2 +1407538384,1407538391,CM +1407538392,1407538407,A2 +1407538408,1407538415,NG +1407538416,1407538423,A2 +1407538424,1407538431,NG +1407538432,1407538439,A2 1407538440,1407538447,NG 1407538448,1407538463,A2 1407538464,1407538471,ZM @@ -34943,8 +36111,7 @@ 1407538664,1407538679,NG 1407538680,1407538751,A2 1407538752,1407538783,NG -1407538784,1407538847,A2 -1407538848,1407538863,NG +1407538784,1407538863,A2 1407538864,1407538879,GE 1407538880,1407538887,A2 1407538888,1407538895,NG @@ -34969,9 +36136,25 @@ 1407539176,1407539183,GH 1407539184,1407539199,NG 1407539200,1407539455,GE -1407539456,1407540119,A2 +1407539456,1407539967,A2 +1407539968,1407539975,CD +1407539976,1407540007,A2 +1407540008,1407540015,NG +1407540016,1407540055,A2 +1407540056,1407540063,NG +1407540064,1407540071,A2 +1407540072,1407540079,NG +1407540080,1407540111,A2 +1407540112,1407540119,TG 1407540120,1407540127,NG -1407540128,1407541471,A2 +1407540128,1407540135,A2 +1407540136,1407540143,NG +1407540144,1407540159,A2 +1407540160,1407540167,CD +1407540168,1407540183,A2 +1407540184,1407540199,NG +1407540200,1407540215,CD +1407540216,1407541471,A2 1407541472,1407541495,NG 1407541496,1407541535,A2 1407541536,1407541543,CM @@ -35024,7 +36207,10 @@ 1407543280,1407543287,NG 1407543288,1407546367,A2 1407546368,1407546495,AE -1407546496,1407546879,A2 +1407546496,1407546799,A2 +1407546800,1407546815,GH +1407546816,1407546863,A2 +1407546864,1407546879,LR 1407546880,1407547135,ZW 1407547136,1407547143,A2 1407547144,1407547151,GH @@ -35065,7 +36251,9 @@ 1407548144,1407548151,A2 1407548152,1407548415,NG 1407548416,1407548543,GE -1407548544,1407549183,A2 +1407548544,1407548711,A2 +1407548712,1407548719,CD +1407548720,1407549183,A2 1407549184,1407549439,GE 1407549440,1407582207,RU 1407582208,1407614975,PL @@ -35112,21 +36300,21 @@ 1407705760,1407705791,FR 1407705792,1407706367,GB 1407706368,1407706423,FR -1407706424,1407707703,GB +1407706424,1407706431,GB +1407706432,1407706463,FR +1407706464,1407707703,GB 1407707704,1407707839,CH 1407707840,1407707903,GB 1407707904,1407707935,CH 1407707936,1407709183,GB -1407709184,1407709631,DE -1407709632,1407710207,GB +1407709184,1407709695,DE +1407709696,1407710207,GB 1407710208,1407710239,ES 1407710240,1407710975,GB 1407710976,1407711319,FR 1407711320,1407711327,GB -1407711328,1407711623,FR -1407711624,1407711631,GB -1407711632,1407711727,FR -1407711728,1407712207,GB +1407711328,1407711743,FR +1407711744,1407712207,GB 1407712208,1407712223,FR 1407712224,1407712767,GB 1407712768,1407712831,DE @@ -35228,11 +36416,10 @@ 1410010824,1410010831,IR 1410010832,1410010879,DE 1410010880,1410011135,IR -1410011136,1410011903,DE -1410011904,1410011919,US -1410011920,1410012159,DE +1410011136,1410012159,DE 1410012160,1410012415,IQ -1410012416,1410013183,DE +1410012416,1410012447,AF +1410012448,1410013183,DE 1410013184,1410013439,ES 1410013440,1410013471,IR 1410013472,1410013535,AE @@ -35302,8 +36489,8 @@ 1410017120,1410017279,DE 1410017280,1410017407,IR 1410017408,1410017791,DE -1410017792,1410018079,IR -1410018080,1410018303,DE +1410017792,1410018047,IR +1410018048,1410018303,DE 1410018304,1410018559,AE 1410018560,1410018591,DE 1410018592,1410018607,IR @@ -35323,9 +36510,7 @@ 1410022592,1410022655,IR 1410022656,1410022911,DE 1410022912,1410023423,IR -1410023424,1410024191,DE -1410024192,1410024223,AE -1410024224,1410024287,DE +1410023424,1410024287,DE 1410024288,1410024319,IR 1410024320,1410024447,DE 1410024448,1410025087,IR @@ -35382,7 +36567,9 @@ 1410036192,1410036207,PA 1410036208,1410036735,DE 1410036736,1410036751,PA -1410036752,1410037759,DE +1410036752,1410036991,DE +1410036992,1410037247,LB +1410037248,1410037759,DE 1410037760,1410038015,US 1410038016,1410039807,DE 1410039808,1410041855,AE @@ -35392,7 +36579,9 @@ 1410043904,1410044415,JO 1410044416,1410044927,DE 1410044928,1410045183,VG -1410045184,1410072319,DE +1410045184,1410045439,DE +1410045440,1410045695,LB +1410045696,1410072319,DE 1410072320,1410072575,AE 1410072576,1410203647,GB 1410203648,1410204439,FR @@ -35405,11 +36594,15 @@ 1410212864,1410213119,GB 1410213120,1410221663,FR 1410221664,1410221671,GB -1410221672,1410250551,FR +1410221672,1410234839,FR +1410234840,1410234847,A2 +1410234848,1410250551,FR 1410250552,1410250559,GB 1410250560,1410261007,FR 1410261008,1410261015,GB -1410261016,1410262799,FR +1410261016,1410261663,FR +1410261664,1410261671,GB +1410261672,1410262799,FR 1410262800,1410262815,DE 1410262816,1410267039,FR 1410267040,1410267055,ES @@ -35475,9 +36668,14 @@ 1410573408,1410573439,RU 1410573440,1410573695,DE 1410573696,1410573711,RU -1410573712,1410573815,DE +1410573712,1410573759,DE +1410573760,1410573775,BA +1410573776,1410573807,DE +1410573808,1410573815,IT 1410573816,1410573823,RU -1410573824,1410574559,DE +1410573824,1410574527,DE +1410574528,1410574543,IT +1410574544,1410574559,DE 1410574560,1410574575,RU 1410574576,1410574583,DE 1410574584,1410574591,RU @@ -35571,7 +36769,9 @@ 1410756736,1410756863,DE 1410756864,1410757119,AQ 1410757120,1410758655,DE -1410758656,1410760191,AQ +1410758656,1410759423,AQ +1410759424,1410759679,GB +1410759680,1410760191,AQ 1410760192,1410760455,DE 1410760456,1410760471,AQ 1410760472,1410760479,SC @@ -35691,13 +36891,15 @@ 1411919872,1411923967,DE 1411923968,1411940351,BG 1411940352,1411973119,PL -1411973120,1411999767,SI +1411973120,1411999743,SI +1411999744,1411999759,BA +1411999760,1411999767,SI 1411999768,1411999783,BA 1411999784,1411999791,SI 1411999792,1411999799,BA 1411999800,1411999807,SI -1411999808,1411999839,BA -1411999840,1411999871,SI +1411999808,1411999847,BA +1411999848,1411999871,SI 1411999872,1412000767,BA 1412000768,1412000783,SI 1412000784,1412000791,BA @@ -35705,7 +36907,9 @@ 1412000864,1412000879,BA 1412000880,1412000903,SI 1412000904,1412000911,BA -1412000912,1412001311,SI +1412000912,1412001023,SI +1412001024,1412001279,BA +1412001280,1412001311,SI 1412001312,1412001319,DE 1412001320,1412001807,SI 1412001808,1412001855,RO @@ -35744,12 +36948,17 @@ 1412003528,1412003535,SI 1412003536,1412003551,BA 1412003552,1412003583,SI -1412003584,1412003839,BA +1412003584,1412003599,BA +1412003600,1412003623,SI +1412003624,1412003631,BA +1412003632,1412003639,SI +1412003640,1412003839,BA 1412003840,1412003855,SI 1412003856,1412003903,BG 1412003904,1412003935,SI -1412003936,1412004607,BG -1412004608,1412005887,SI +1412003936,1412004351,BG +1412004352,1412004863,BA +1412004864,1412005887,SI 1412005888,1412038655,NL 1412038656,1412071423,RU 1412071424,1412104191,CZ @@ -35779,8 +36988,7 @@ 1412628480,1412641791,TR 1412641792,1412642815,DE 1412642816,1412644863,TR -1412644864,1412653055,UA -1412653056,1412661247,RU +1412644864,1412661247,RU 1412661248,1412677631,GB 1412677632,1412685823,RU 1412685824,1412686239,IE @@ -35833,21 +37041,20 @@ 1422393344,1422393599,DE 1422393600,1422393855,IT 1422393856,1422399103,DE -1422399104,1422399231,IT -1422399232,1422399999,DE +1422399104,1422399135,IT +1422399136,1422399999,DE 1422400000,1422400255,IT 1422400256,1422400511,DE 1422400512,1422400767,BR -1422400768,1422401087,DE -1422401088,1422401151,GB -1422401152,1422462207,DE +1422400768,1422406399,DE +1422406400,1422406463,GB +1422406464,1422462207,DE 1422462208,1422462463,TR 1422462464,1422468671,DE 1422468672,1422468735,IT 1422468736,1422479615,DE 1422479616,1422479871,BE 1422479872,1422491647,DE -1422491648,1422508031,GB 1422508032,1422512127,BG 1422512128,1422516223,PL 1422516224,1422520319,BY @@ -35869,7 +37076,9 @@ 1422853920,1422854143,EU 1422854144,1422854151,FR 1422854152,1422856319,EU -1422856320,1422856575,FR +1422856320,1422856447,FR +1422856448,1422856511,EU +1422856512,1422856575,FR 1422856576,1422856703,EU 1422856704,1422857855,FR 1422857856,1422857919,EU @@ -36039,9 +37248,7 @@ 1424609272,1424609279,DE 1424609280,1424609395,CH 1424609396,1424609399,GB -1424609400,1424609727,CH -1424609728,1424609743,GB -1424609744,1424609791,CH +1424609400,1424609791,CH 1424609792,1424610303,GB 1424610304,1424610559,TZ 1424610560,1424610815,PL @@ -36105,9 +37312,7 @@ 1424618016,1424618239,IT 1424618240,1424618495,NL 1424618496,1424618751,GB -1424618752,1424618943,FR -1424618944,1424618951,GB -1424618952,1424619007,FR +1424618752,1424619007,FR 1424619008,1424619775,IT 1424619776,1424619807,BE 1424619808,1424619815,GB @@ -36115,7 +37320,9 @@ 1424619824,1424619839,GB 1424619840,1424619915,BE 1424619916,1424619919,GB -1424619920,1424620031,BE +1424619920,1424619951,BE +1424619952,1424619967,GB +1424619968,1424620031,BE 1424620032,1424621055,GB 1424621056,1424621567,IT 1424621568,1424625663,PL @@ -36227,6 +37434,7 @@ 1425426432,1425428479,KW 1425428480,1425430527,GB 1425430528,1425432575,SE +1425432576,1425434623,HR 1425434624,1425436671,FR 1425436672,1425438719,GB 1425438720,1425439271,DE @@ -36314,9 +37522,7 @@ 1425966721,1425966728,BJ 1425966729,1425966735,A2 1425966736,1425966751,BJ -1425966752,1425966784,A2 -1425966785,1425966808,BJ -1425966809,1425966815,A2 +1425966752,1425966815,A2 1425966816,1425966847,BJ 1425966848,1425966852,A2 1425966853,1425966896,DE @@ -36521,7 +37727,11 @@ 1426685952,1426702335,TJ 1426702336,1426703103,LV 1426703104,1426703167,RU -1426703168,1426718719,LV +1426703168,1426703214,LV +1426703215,1426703217,RU +1426703218,1426716159,LV +1426716160,1426716415,RU +1426716416,1426718719,LV 1426718720,1426731007,SI 1426731008,1426735103,HR 1426735104,1426751487,BE @@ -36638,9 +37848,7 @@ 1427668992,1427701759,SE 1427701760,1427723391,DE 1427723392,1427723519,LI -1427723520,1427728383,DE -1427728384,1427728415,US -1427728416,1427728479,DE +1427723520,1427728479,DE 1427728480,1427728511,CY 1427728512,1427728543,BR 1427728544,1427728671,DE @@ -36651,8 +37859,7 @@ 1427728896,1427728927,DE 1427728928,1427728959,IL 1427728960,1427728991,RU -1427728992,1427729023,DE -1427729024,1427729055,AT +1427728992,1427729055,DE 1427729056,1427729087,CA 1427729088,1427729119,DE 1427729120,1427729151,RO @@ -36660,9 +37867,7 @@ 1427729312,1427729343,GR 1427729344,1427742719,DE 1427742720,1427742751,IO -1427742752,1427742847,DE -1427742848,1427742879,CZ -1427742880,1427743231,DE +1427742752,1427743231,DE 1427743232,1427743263,GR 1427743264,1427743327,DE 1427743328,1427743359,NL @@ -36672,16 +37877,18 @@ 1427743616,1427743647,DK 1427743648,1427743775,DE 1427743776,1427743807,ZA -1427743808,1427744159,DE +1427743808,1427743839,DE +1427743840,1427743871,RU +1427743872,1427743935,DE +1427743936,1427743967,RU +1427743968,1427744159,DE 1427744160,1427744191,RU 1427744192,1427744255,DE 1427744256,1427744287,US 1427744288,1427744319,TR 1427744320,1427744351,DE 1427744352,1427744383,UA -1427744384,1427744511,DE -1427744512,1427744543,BE -1427744544,1427744639,DE +1427744384,1427744639,DE 1427744640,1427744671,TR 1427744672,1427744703,DE 1427744704,1427744735,CA @@ -36713,7 +37920,11 @@ 1427746368,1427746399,SE 1427746400,1427747839,DE 1427747840,1427747871,FI -1427747872,1427748543,DE +1427747872,1427748063,DE +1427748064,1427748095,NL +1427748096,1427748479,DE +1427748480,1427748511,TR +1427748512,1427748543,DE 1427748544,1427748575,MX 1427748576,1427749503,DE 1427749504,1427749535,UA @@ -36723,9 +37934,7 @@ 1427749632,1427749663,US 1427749664,1427749951,DE 1427749952,1427749983,RU -1427749984,1427750143,DE -1427750144,1427750175,TR -1427750176,1427750239,DE +1427749984,1427750239,DE 1427750240,1427750271,NL 1427750272,1427750303,DE 1427750304,1427750335,GB @@ -36737,7 +37946,8 @@ 1427760192,1427760223,TR 1427760224,1427760255,US 1427760256,1427760319,BR -1427760320,1427760383,DE +1427760320,1427760351,DE +1427760352,1427760383,RU 1427760384,1427760415,TR 1427760416,1427760799,DE 1427760800,1427760831,NL @@ -36757,7 +37967,8 @@ 1427761504,1427761535,PL 1427761536,1427761567,US 1427761568,1427761599,RU -1427761600,1427767295,DE +1427761600,1427761631,EG +1427761632,1427767295,DE 1427767296,1427800063,BE 1427800064,1427823615,RU 1427823616,1427824639,KG @@ -36773,6 +37984,7 @@ 1427980288,1427996671,FI 1427996672,1428013055,KZ 1428013056,1428029439,EE +1428029440,1428045823,SE 1428045824,1428062207,MK 1428062208,1428078591,SE 1428078592,1428094975,RU @@ -36783,7 +37995,7 @@ 1428111360,1428119551,A2 1428119552,1428121599,LV 1428121600,1428123647,FR -1428123648,1428126975,RU +1428125696,1428126975,RU 1428126976,1428127231,TR 1428127232,1428127743,RU 1428127744,1428129791,ES @@ -36802,19 +38014,16 @@ 1428147596,1428147711,GB 1428147712,1428147855,FR 1428147856,1428147871,US -1428147872,1428147895,FR -1428147896,1428147903,GB -1428147904,1428148039,FR +1428147872,1428148039,FR 1428148040,1428148047,GB 1428148048,1428148175,FR 1428148176,1428148191,CH -1428148192,1428148223,GB -1428148224,1428150735,FR +1428148192,1428150735,FR 1428150736,1428150751,GB 1428150752,1428151007,FR 1428151008,1428151039,GB 1428151040,1428151231,FR -1428151232,1428151295,GB +1428151232,1428151295,CH 1428151296,1428152127,FR 1428152128,1428152319,GB 1428152320,1428160511,PL @@ -36897,16 +38106,14 @@ 1432133632,1432150015,GB 1432150016,1432158207,BA 1432158208,1432159042,DE -1432159043,1432159046,IR +1432159043,1432159046,US 1432159047,1432159311,DE -1432159312,1432159321,IR +1432159312,1432159321,US 1432159322,1432159743,DE 1432159744,1432159871,PL 1432159872,1432160255,DE 1432160256,1432160511,CH -1432160512,1432162907,DE -1432162908,1432162914,IR -1432162915,1432165247,DE +1432160512,1432165247,DE 1432165248,1432165375,PL 1432165376,1432166399,DE 1432166400,1432174591,RU @@ -36940,8 +38147,7 @@ 1433410560,1433411071,ES 1433411072,1433411327,US 1433411328,1433411343,ES -1433411344,1433411359,TR -1433411360,1433411375,ES +1433411344,1433411375,TR 1433411376,1433411407,US 1433411408,1433411455,TR 1433411456,1433411519,US @@ -37027,7 +38233,9 @@ 1433860096,1433862143,DE 1433862144,1433862751,CH 1433862752,1433862783,MC -1433862784,1433863423,CH +1433862784,1433862975,CH +1433862976,1433862991,GB +1433862992,1433863423,CH 1433863424,1433863487,US 1433863488,1433864191,CH 1433864192,1433866239,HU @@ -37063,8 +38271,8 @@ 1433911296,1433913343,ES 1433913344,1433913875,NL 1433913876,1433913879,DE -1433913880,1433914111,NL -1433914112,1433915135,DE +1433913880,1433914047,NL +1433914048,1433915135,DE 1433915136,1433915391,NL 1433915392,1433917439,DE 1433917440,1433919487,BE @@ -37086,17 +38294,21 @@ 1434681856,1434682111,MY 1434682112,1434682303,DE 1434682304,1434682367,NL -1434682368,1434683103,DE -1434683104,1434683135,NL -1434683136,1434683263,DE -1434683264,1434683391,NL -1434683392,1434684415,DE -1434684416,1434684671,NL -1434684672,1434685439,DE +1434682368,1434683119,DE +1434683120,1434683135,NL +1434683136,1434683327,DE +1434683328,1434683391,MY +1434683392,1434685439,DE 1434685440,1434687231,NL 1434687232,1434687359,DE 1434687360,1434687487,NL -1434687488,1434694655,DE +1434687488,1434688207,DE +1434688208,1434688223,NL +1434688224,1434689887,DE +1434689888,1434689919,NL +1434689920,1434692607,DE +1434692608,1434692671,NL +1434692672,1434694655,DE 1434694656,1434694719,NL 1434694720,1434702463,DE 1434702464,1434702591,NL @@ -37258,9 +38470,7 @@ 1438869648,1438869651,LV 1438869652,1438869655,US 1438869656,1438869663,UA -1438869664,1438869671,DE -1438869672,1438869679,CY -1438869680,1438873119,DE +1438869664,1438873119,DE 1438873120,1438873127,PA 1438873128,1438873671,DE 1438873672,1438873679,PA @@ -37281,7 +38491,7 @@ 1438875256,1438875257,CH 1438875258,1438875647,DE 1438875648,1438876159,RU -1438876160,1438876415,LB +1438876160,1438876415,LT 1438876416,1438876927,RU 1438876928,1438877183,IQ 1438877184,1438877439,LT @@ -37299,8 +38509,7 @@ 1438884352,1438884607,LB 1438884608,1438884863,IQ 1438884864,1438885887,RU -1438885888,1438889983,LT -1438889984,1438890239,LB +1438885888,1438890239,LT 1438890240,1438890495,RU 1438890496,1438890751,IQ 1438890752,1438892031,RU @@ -37465,7 +38674,11 @@ 1441388672,1441388799,CA 1441388800,1441389055,FR 1441389056,1441389119,IE -1441389120,1441390591,FR +1441389120,1441389223,FR +1441389224,1441389231,LU +1441389232,1441389567,FR +1441389568,1441389599,LU +1441389600,1441390591,FR 1441390592,1441398783,DK 1441398784,1441415167,RU 1441415168,1441423359,GB @@ -37513,10 +38726,7 @@ 1441583104,1441587199,DE 1441587200,1441594879,AT 1441594880,1441595135,DE -1441595136,1441596415,AT -1441596416,1441602815,SK -1441602816,1441603071,AT -1441603072,1441603583,SK +1441595136,1441603583,AT 1441603584,1441611775,RU 1441611776,1441619967,DE 1441619968,1441620271,FR @@ -37669,25 +38879,1019 @@ 1446862080,1446862591,HR 1446862592,1446871039,SI 1446871040,1446903807,CZ -1446903808,1446904071,A2 -1446904072,1446904079,CY +1446903808,1446904063,A2 +1446904064,1446904071,CY +1446904072,1446904079,IQ 1446904080,1446904095,BH -1446904096,1446904111,SA -1446904112,1446904119,BH -1446904120,1446904127,A2 +1446904096,1446904103,SD +1446904104,1446904111,SA +1446904112,1446904119,LY +1446904120,1446904127,SD 1446904128,1446904135,SA 1446904136,1446904143,IQ -1446904144,1446904151,SA +1446904144,1446904151,ER 1446904152,1446904159,IR 1446904160,1446904167,ES 1446904168,1446904175,IQ -1446904176,1446904831,A2 -1446904832,1446904835,LY -1446904836,1446904931,A2 +1446904176,1446904183,A2 +1446904184,1446904191,IQ +1446904192,1446904215,A2 +1446904216,1446904223,IQ +1446904224,1446904231,LY +1446904232,1446904247,A2 +1446904248,1446904255,AF +1446904256,1446904263,CY +1446904264,1446904279,A2 +1446904280,1446904287,IQ +1446904288,1446904295,AF +1446904296,1446904303,IQ +1446904304,1446904311,A2 +1446904312,1446904319,AF +1446904320,1446904335,AE +1446904336,1446904351,A2 +1446904352,1446904367,AE +1446904368,1446904527,A2 +1446904528,1446904543,ZM +1446904544,1446904575,A2 +1446904576,1446904591,SD +1446904592,1446904599,NG +1446904600,1446904607,A2 +1446904608,1446904623,SD +1446904624,1446904631,IQ +1446904632,1446904751,A2 +1446904752,1446904759,NG +1446904760,1446904799,A2 +1446904800,1446904807,SD +1446904808,1446904815,A2 +1446904816,1446904823,ZM +1446904824,1446904831,A2 +1446904832,1446904839,IQ +1446904840,1446904843,A2 +1446904844,1446904847,CG +1446904848,1446904851,A2 +1446904852,1446904859,IQ +1446904860,1446904871,A2 +1446904872,1446904875,IQ +1446904876,1446904879,ZM +1446904880,1446904887,IQ +1446904888,1446904895,A2 +1446904896,1446904907,IQ +1446904908,1446904915,A2 +1446904916,1446904919,ZM +1446904920,1446904927,IQ +1446904928,1446904931,A2 1446904932,1446904935,ZM -1446904936,1446908539,A2 +1446904936,1446904939,LY +1446904940,1446904947,IQ +1446904948,1446904951,A2 +1446904952,1446904955,AF +1446904956,1446904959,A2 +1446904960,1446904963,IQ +1446904964,1446904975,A2 +1446904976,1446904979,CG +1446904980,1446904987,IQ +1446904988,1446904991,A2 +1446904992,1446905007,IQ +1446905008,1446905011,CG +1446905012,1446905015,A2 +1446905016,1446905019,NG +1446905020,1446905023,LY +1446905024,1446905031,IQ +1446905032,1446905035,A2 +1446905036,1446905039,IQ +1446905040,1446905043,AF +1446905044,1446905051,IQ +1446905052,1446905055,LY +1446905056,1446905063,IQ +1446905064,1446905067,NG +1446905068,1446905071,IQ +1446905072,1446905083,A2 +1446905084,1446905095,AF +1446905096,1446905103,BJ +1446905104,1446905107,IQ +1446905108,1446905111,A2 +1446905112,1446905115,BJ +1446905116,1446905119,A2 +1446905120,1446905123,GN +1446905124,1446905127,AF +1446905128,1446905135,A2 +1446905136,1446905143,IQ +1446905144,1446905147,A2 +1446905148,1446905151,LY +1446905152,1446905155,AF +1446905156,1446905167,IQ +1446905168,1446905171,A2 +1446905172,1446905175,IQ +1446905176,1446905179,AF +1446905180,1446905191,LY +1446905192,1446905195,A2 +1446905196,1446905199,AF +1446905200,1446905203,NG +1446905204,1446905207,AF +1446905208,1446905211,ER +1446905212,1446905215,IQ +1446905216,1446905223,A2 +1446905224,1446905227,IQ +1446905228,1446905235,NG +1446905236,1446905251,A2 +1446905252,1446905255,IQ +1446905256,1446905259,A2 +1446905260,1446905263,IQ +1446905264,1446905267,LY +1446905268,1446905271,NG +1446905272,1446905275,IQ +1446905276,1446905279,A2 +1446905280,1446905283,IQ +1446905284,1446905287,A2 +1446905288,1446905295,IQ +1446905296,1446905303,ZM +1446905304,1446905307,CF +1446905308,1446905315,A2 +1446905316,1446905319,NG +1446905320,1446905323,A2 +1446905324,1446905327,IQ +1446905328,1446905331,A2 +1446905332,1446905339,IQ +1446905340,1446905343,A2 +1446905344,1446905351,LY +1446905352,1446905367,A2 +1446905368,1446905375,LY +1446905376,1446905383,A2 +1446905384,1446905391,SD +1446905392,1446905583,A2 +1446905584,1446905591,AF +1446905592,1446905599,A2 +1446905600,1446905603,ZM +1446905604,1446905615,IQ +1446905616,1446905619,A2 +1446905620,1446905623,ZM +1446905624,1446905627,A2 +1446905628,1446905631,AF +1446905632,1446905635,LY +1446905636,1446905639,IQ +1446905640,1446905643,A2 +1446905644,1446905655,IQ +1446905656,1446905659,AF +1446905660,1446905663,ER +1446905664,1446905667,LY +1446905668,1446905671,A2 +1446905672,1446905675,AF +1446905676,1446905679,LY +1446905680,1446905683,ZM +1446905684,1446905691,A2 +1446905692,1446905695,ZM +1446905696,1446905699,LY +1446905700,1446905703,ZM +1446905704,1446905719,A2 +1446905720,1446905723,AF +1446905724,1446905727,A2 +1446905728,1446905731,IQ +1446905732,1446905735,AF +1446905736,1446905743,A2 +1446905744,1446905747,LY +1446905748,1446905751,A2 +1446905752,1446905755,IQ +1446905756,1446905759,A2 +1446905760,1446905763,ML +1446905764,1446905767,LY +1446905768,1446905779,A2 +1446905780,1446905783,LY +1446905784,1446905787,A2 +1446905788,1446905791,LY +1446905792,1446905795,TD +1446905796,1446905803,A2 +1446905804,1446905807,IQ +1446905808,1446905815,A2 +1446905816,1446905823,LY +1446905824,1446905827,A2 +1446905828,1446905831,LY +1446905832,1446905835,NG +1446905836,1446905839,A2 +1446905840,1446905843,IQ +1446905844,1446905847,A2 +1446905848,1446905851,IQ +1446905852,1446905855,AF +1446905856,1446905856,A2 +1446905857,1446905863,LY +1446905864,1446905871,SD +1446905872,1446905911,A2 +1446905912,1446905943,SD +1446905944,1446906023,A2 +1446906024,1446906031,SD +1446906032,1446906039,A2 +1446906040,1446906047,SD +1446906048,1446906071,A2 +1446906072,1446906079,CY +1446906080,1446906115,A2 +1446906116,1446906119,ZM +1446906120,1446906123,SD +1446906124,1446906131,IQ +1446906132,1446906135,LY +1446906136,1446906139,IQ +1446906140,1446906143,A2 +1446906144,1446906151,ZM +1446906152,1446906167,AF +1446906168,1446906171,A2 +1446906172,1446906179,AF +1446906180,1446906187,A2 +1446906188,1446906191,AF +1446906192,1446906195,A2 +1446906196,1446906203,IQ +1446906204,1446906211,A2 +1446906212,1446906215,AF +1446906216,1446906219,A2 +1446906220,1446906223,BG +1446906224,1446906231,IQ +1446906232,1446906239,AF +1446906240,1446906243,IQ +1446906244,1446906247,A2 +1446906248,1446906259,IQ +1446906260,1446906263,AF +1446906264,1446906283,A2 +1446906284,1446906303,IQ +1446906304,1446906307,ZM +1446906308,1446906311,A2 +1446906312,1446906327,IQ +1446906328,1446906331,A2 +1446906332,1446906335,IQ +1446906336,1446906339,ZM +1446906340,1446906343,A2 +1446906344,1446906347,NG +1446906348,1446906351,ZM +1446906352,1446906359,A2 +1446906360,1446906363,SD +1446906364,1446906367,IQ +1446906368,1446906391,A2 +1446906392,1446906399,CY +1446906400,1446906567,A2 +1446906568,1446906591,KW +1446906592,1446906599,IQ +1446906600,1446906615,KW +1446906616,1446906623,A2 +1446906624,1446906631,LY +1446906632,1446906639,A2 +1446906640,1446906655,LY +1446906656,1446906663,NG +1446906664,1446906863,A2 +1446906864,1446906871,ZM +1446906872,1446906879,A2 +1446906880,1446906883,IQ +1446906884,1446906887,AF +1446906888,1446906891,IQ +1446906892,1446906895,A2 +1446906896,1446906899,IQ +1446906900,1446906907,A2 +1446906908,1446906919,IQ +1446906920,1446906923,A2 +1446906924,1446906927,IQ +1446906928,1446906931,SA +1446906932,1446906935,IQ +1446906936,1446906943,LY +1446906944,1446906947,IQ +1446906948,1446906951,A2 +1446906952,1446906955,IQ +1446906956,1446906963,A2 +1446906964,1446906967,AF +1446906968,1446906971,A2 +1446906972,1446906983,IQ +1446906984,1446906987,NG +1446906988,1446906995,IQ +1446906996,1446906999,AF +1446907000,1446907007,A2 +1446907008,1446907011,AF +1446907012,1446907015,IQ +1446907016,1446907019,ZM +1446907020,1446907023,AF +1446907024,1446907027,IQ +1446907028,1446907031,ZM +1446907032,1446907039,A2 +1446907040,1446907043,ZM +1446907044,1446907047,CG +1446907048,1446907055,IQ +1446907056,1446907067,A2 +1446907068,1446907071,AF +1446907072,1446907075,A2 +1446907076,1446907079,IQ +1446907080,1446907083,AF +1446907084,1446907087,IQ +1446907088,1446907091,LY +1446907092,1446907095,IQ +1446907096,1446907099,NG +1446907100,1446907103,IQ +1446907104,1446907123,A2 +1446907124,1446907131,IQ +1446907132,1446907135,AF +1446907136,1446907147,A2 +1446907148,1446907151,IQ +1446907152,1446907155,A2 +1446907156,1446907159,LY +1446907160,1446907163,AF +1446907164,1446907167,IQ +1446907168,1446907171,LY +1446907172,1446907175,IQ +1446907176,1446907187,LY +1446907188,1446907191,CG +1446907192,1446907199,IQ +1446907200,1446907203,A2 +1446907204,1446907207,IQ +1446907208,1446907211,A2 +1446907212,1446907215,IQ +1446907216,1446907223,A2 +1446907224,1446907227,ZM +1446907228,1446907231,A2 +1446907232,1446907243,IQ +1446907244,1446907247,NG +1446907248,1446907255,A2 +1446907256,1446907259,GA +1446907260,1446907279,IQ +1446907280,1446907283,GA +1446907284,1446907287,A2 +1446907288,1446907291,AF +1446907292,1446907303,A2 +1446907304,1446907307,IQ +1446907308,1446907311,AF +1446907312,1446907315,A2 +1446907316,1446907319,IQ +1446907320,1446907323,AF +1446907324,1446907327,A2 +1446907328,1446907331,IQ +1446907332,1446907335,A2 +1446907336,1446907339,IQ +1446907340,1446907347,LY +1446907348,1446907355,ZM +1446907356,1446907371,A2 +1446907372,1446907375,AF +1446907376,1446907379,ZM +1446907380,1446907383,IQ +1446907384,1446907387,CI +1446907388,1446907391,A2 +1446907392,1446907395,AF +1446907396,1446907399,IQ +1446907400,1446907403,A2 +1446907404,1446907407,IQ +1446907408,1446907411,A2 +1446907412,1446907419,IQ +1446907420,1446907423,A2 +1446907424,1446907427,ZM +1446907428,1446907439,A2 +1446907440,1446907443,AF +1446907444,1446907451,A2 +1446907452,1446907463,IQ +1446907464,1446907475,A2 +1446907476,1446907479,LY +1446907480,1446907483,A2 +1446907484,1446907487,IQ +1446907488,1446907491,A2 +1446907492,1446907495,TD +1446907496,1446907503,IQ +1446907504,1446907507,LY +1446907508,1446907511,IQ +1446907512,1446907523,A2 +1446907524,1446907527,LY +1446907528,1446907531,A2 +1446907532,1446907539,IQ +1446907540,1446907543,LY +1446907544,1446907547,IQ +1446907548,1446907551,A2 +1446907552,1446907559,IQ +1446907560,1446907571,A2 +1446907572,1446907575,AF +1446907576,1446907579,A2 +1446907580,1446907583,GH +1446907584,1446907615,A2 +1446907616,1446907619,TD +1446907620,1446907631,A2 +1446907632,1446907635,LY +1446907636,1446907647,IQ +1446907648,1446907659,A2 +1446907660,1446907663,ZM +1446907664,1446907667,NG +1446907668,1446907671,A2 +1446907672,1446907675,IQ +1446907676,1446907679,LY +1446907680,1446907691,A2 +1446907692,1446907695,IQ +1446907696,1446907699,LY +1446907700,1446907703,IQ +1446907704,1446907715,A2 +1446907716,1446907719,AF +1446907720,1446907723,A2 +1446907724,1446907731,IQ +1446907732,1446907735,LY +1446907736,1446907739,A2 +1446907740,1446907743,IQ +1446907744,1446907747,A2 +1446907748,1446907755,AF +1446907756,1446907759,A2 +1446907760,1446907763,IQ +1446907764,1446907767,A2 +1446907768,1446907771,IQ +1446907772,1446907775,A2 +1446907776,1446907779,LY +1446907780,1446907783,IQ +1446907784,1446907787,A2 +1446907788,1446907791,IQ +1446907792,1446907799,A2 +1446907800,1446907803,ZM +1446907804,1446907807,IQ +1446907808,1446907823,A2 +1446907824,1446907827,LY +1446907828,1446907831,A2 +1446907832,1446907839,LY +1446907840,1446907855,A2 +1446907856,1446907859,AF +1446907860,1446907863,A2 +1446907864,1446907871,LY +1446907872,1446907875,A2 +1446907876,1446907883,IQ +1446907884,1446907887,A2 +1446907888,1446907891,SD +1446907892,1446907895,AF +1446907896,1446907899,IQ +1446907900,1446907903,LY +1446907904,1446907911,IQ +1446907912,1446907919,A2 +1446907920,1446907927,LY +1446907928,1446908103,A2 +1446908104,1446908111,NG +1446908112,1446908143,A2 +1446908144,1446908151,AE +1446908152,1446908159,SD +1446908160,1446908163,AF +1446908164,1446908167,A2 +1446908168,1446908175,IQ +1446908176,1446908187,A2 +1446908188,1446908191,GH +1446908192,1446908235,A2 +1446908236,1446908243,IQ +1446908244,1446908247,A2 +1446908248,1446908251,AF +1446908252,1446908255,A2 +1446908256,1446908259,SZ +1446908260,1446908267,A2 +1446908268,1446908271,AF +1446908272,1446908275,LY +1446908276,1446908279,A2 +1446908280,1446908283,IQ +1446908284,1446908287,AF +1446908288,1446908299,A2 +1446908300,1446908303,IQ +1446908304,1446908307,AF +1446908308,1446908311,A2 +1446908312,1446908315,LY +1446908316,1446908323,A2 +1446908324,1446908327,ZM +1446908328,1446908331,A2 +1446908332,1446908335,NG +1446908336,1446908359,A2 +1446908360,1446908363,LY +1446908364,1446908367,A2 +1446908368,1446908371,IQ +1446908372,1446908383,A2 +1446908384,1446908391,IQ +1446908392,1446908419,A2 +1446908420,1446908423,IQ +1446908424,1446908427,A2 +1446908428,1446908431,IQ +1446908432,1446908435,A2 +1446908436,1446908443,AF +1446908444,1446908447,A2 +1446908448,1446908451,ZM +1446908452,1446908455,A2 +1446908456,1446908459,LB +1446908460,1446908479,A2 +1446908480,1446908483,IQ +1446908484,1446908487,A2 +1446908488,1446908491,IQ +1446908492,1446908515,A2 +1446908516,1446908519,IQ +1446908520,1446908531,A2 +1446908532,1446908535,IQ +1446908536,1446908539,A2 1446908540,1446908543,ZM -1446908544,1446920191,A2 +1446908544,1446908591,A2 +1446908592,1446908595,IQ +1446908596,1446908599,A2 +1446908600,1446908603,ZM +1446908604,1446908607,CG +1446908608,1446908631,A2 +1446908632,1446908635,IQ +1446908636,1446908651,A2 +1446908652,1446908663,IQ +1446908664,1446908683,A2 +1446908684,1446908687,SD +1446908688,1446908691,IQ +1446908692,1446908707,A2 +1446908708,1446908711,IQ +1446908712,1446908715,A2 +1446908716,1446908719,CM +1446908720,1446908727,A2 +1446908728,1446908731,AF +1446908732,1446908735,A2 +1446908736,1446908739,IQ +1446908740,1446908743,A2 +1446908744,1446908747,GN +1446908748,1446908751,A2 +1446908752,1446908759,IQ +1446908760,1446908775,A2 +1446908776,1446908779,IQ +1446908780,1446908787,A2 +1446908788,1446908791,NG +1446908792,1446908811,A2 +1446908812,1446908815,IQ +1446908816,1446908835,A2 +1446908836,1446908843,IQ +1446908844,1446908855,A2 +1446908856,1446908859,ZM +1446908860,1446908863,A2 +1446908864,1446908871,AF +1446908872,1446908875,A2 +1446908876,1446908879,AF +1446908880,1446908907,A2 +1446908908,1446908911,IQ +1446908912,1446908919,A2 +1446908920,1446908923,IQ +1446908924,1446908927,A2 +1446908928,1446908931,IQ +1446908932,1446908935,ZM +1446908936,1446908951,A2 +1446908952,1446908955,IQ +1446908956,1446908959,LY +1446908960,1446908971,A2 +1446908972,1446908975,AF +1446908976,1446908979,GA +1446908980,1446908983,AF +1446908984,1446908987,LY +1446908988,1446908999,A2 +1446909000,1446909003,IQ +1446909004,1446909007,LY +1446909008,1446909019,IQ +1446909020,1446909083,A2 +1446909084,1446909087,CG +1446909088,1446909091,IQ +1446909092,1446909095,A2 +1446909096,1446909099,TD +1446909100,1446909111,A2 +1446909112,1446909115,IQ +1446909116,1446909163,A2 +1446909164,1446909167,IQ +1446909168,1446909171,A2 +1446909172,1446909173,IQ +1446909174,1446909195,A2 +1446909196,1446909199,IQ +1446909200,1446909203,A2 +1446909204,1446909207,IQ +1446909208,1446909211,LY +1446909212,1446909215,A2 +1446909216,1446909219,LY +1446909220,1446909223,IQ +1446909224,1446909271,A2 +1446909272,1446909275,IQ +1446909276,1446909295,A2 +1446909296,1446909299,IQ +1446909300,1446909303,A2 +1446909304,1446909319,IQ +1446909320,1446909327,A2 +1446909328,1446909331,IQ +1446909332,1446909335,A2 +1446909336,1446909339,GH +1446909340,1446909351,A2 +1446909352,1446909359,IQ +1446909360,1446909363,A2 +1446909364,1446909367,IQ +1446909368,1446909391,A2 +1446909392,1446909395,ZM +1446909396,1446909401,NG +1446909402,1446909423,A2 +1446909424,1446909435,AF +1446909436,1446909443,A2 +1446909444,1446909447,NG +1446909448,1446909471,A2 +1446909472,1446909475,IQ +1446909476,1446909491,A2 +1446909492,1446909495,IQ +1446909496,1446909499,A2 +1446909500,1446909507,IQ +1446909508,1446909519,A2 +1446909520,1446909523,CG +1446909524,1446909539,A2 +1446909540,1446909543,IQ +1446909544,1446909555,A2 +1446909556,1446909559,IQ +1446909560,1446909563,A2 +1446909564,1446909567,NG +1446909568,1446909575,A2 +1446909576,1446909579,AF +1446909580,1446909599,A2 +1446909600,1446909603,AF +1446909604,1446909615,A2 +1446909616,1446909623,IQ +1446909624,1446909647,A2 +1446909648,1446909651,NG +1446909652,1446909655,A2 +1446909656,1446909659,AF +1446909660,1446909667,A2 +1446909668,1446909671,IQ +1446909672,1446909683,A2 +1446909684,1446909687,IQ +1446909688,1446909691,AF +1446909692,1446909699,A2 +1446909700,1446909703,IQ +1446909704,1446909731,A2 +1446909732,1446909735,IQ +1446909736,1446909739,ZM +1446909740,1446909743,AF +1446909744,1446909755,A2 +1446909756,1446909763,ZM +1446909764,1446909787,A2 +1446909788,1446909791,IQ +1446909792,1446909803,A2 +1446909804,1446909807,AF +1446909808,1446909815,A2 +1446909816,1446909819,AF +1446909820,1446909827,IQ +1446909828,1446909851,A2 +1446909852,1446909855,LY +1446909856,1446909859,A2 +1446909860,1446909863,IQ +1446909864,1446909867,A2 +1446909868,1446909871,LY +1446909872,1446909879,A2 +1446909880,1446909883,LY +1446909884,1446909887,A2 +1446909888,1446909891,LY +1446909892,1446909907,A2 +1446909908,1446909911,IQ +1446909912,1446909955,A2 +1446909956,1446909959,IQ +1446909960,1446909967,A2 +1446909968,1446909971,LY +1446909972,1446909975,A2 +1446909976,1446909991,LY +1446909992,1446909999,IQ +1446910000,1446910003,AF +1446910004,1446910011,A2 +1446910012,1446910015,IQ +1446910016,1446910019,A2 +1446910020,1446910027,IQ +1446910028,1446910031,A2 +1446910032,1446910035,LY +1446910036,1446910039,A2 +1446910040,1446910043,IQ +1446910044,1446910055,A2 +1446910056,1446910059,ZM +1446910060,1446910063,IQ +1446910064,1446910071,A2 +1446910072,1446910075,IQ +1446910076,1446910083,A2 +1446910084,1446910095,IQ +1446910096,1446910103,A2 +1446910104,1446910107,IQ +1446910108,1446910111,A2 +1446910112,1446910115,IQ +1446910116,1446910119,A2 +1446910120,1446910123,IQ +1446910124,1446910159,A2 +1446910160,1446910163,ZM +1446910164,1446910167,NG +1446910168,1446910175,A2 +1446910176,1446910179,ZM +1446910180,1446910191,IQ +1446910192,1446910195,A2 +1446910196,1446910199,AF +1446910200,1446910203,A2 +1446910204,1446910207,ZM +1446910208,1446910211,A2 +1446910212,1446910220,IQ +1446910221,1446910223,A2 +1446910224,1446910227,IQ +1446910228,1446910231,A2 +1446910232,1446910239,IQ +1446910240,1446910247,A2 +1446910248,1446910251,LY +1446910252,1446910255,IQ +1446910256,1446910263,A2 +1446910264,1446910267,IQ +1446910268,1446910271,AF +1446910272,1446910275,A2 +1446910276,1446910279,IQ +1446910280,1446910283,A2 +1446910284,1446910291,IQ +1446910292,1446910295,A2 +1446910296,1446910307,IQ +1446910308,1446910311,AF +1446910312,1446910323,A2 +1446910324,1446910327,IQ +1446910328,1446910331,A2 +1446910332,1446910335,IQ +1446910336,1446910339,AF +1446910340,1446910343,IQ +1446910344,1446910347,LY +1446910348,1446910351,GA +1446910352,1446910355,A2 +1446910356,1446910359,IQ +1446910360,1446910363,AF +1446910364,1446910371,A2 +1446910372,1446910379,AF +1446910380,1446910427,A2 +1446910428,1446910431,IQ +1446910432,1446910439,A2 +1446910440,1446910443,IQ +1446910444,1446910455,A2 +1446910456,1446910459,IQ +1446910460,1446910463,A2 +1446910464,1446910479,LY +1446910480,1446910495,A2 +1446910496,1446910503,NG +1446910504,1446910527,A2 +1446910528,1446910535,AF +1446910536,1446910599,A2 +1446910600,1446910615,NG +1446910616,1446910623,A2 +1446910624,1446910631,AF +1446910632,1446910695,A2 +1446910696,1446910711,SD +1446910712,1446910719,AE +1446910720,1446910723,A2 +1446910724,1446910727,IQ +1446910728,1446910731,AF +1446910732,1446910739,A2 +1446910740,1446910747,AF +1446910748,1446910751,A2 +1446910752,1446910755,LY +1446910756,1446910767,IQ +1446910768,1446910771,A2 +1446910772,1446910775,AF +1446910776,1446910779,IQ +1446910780,1446910787,A2 +1446910788,1446910791,IQ +1446910792,1446910799,A2 +1446910800,1446910807,IQ +1446910808,1446910815,A2 +1446910816,1446910819,IQ +1446910820,1446910823,AF +1446910824,1446910835,A2 +1446910836,1446910839,AF +1446910840,1446910843,A2 +1446910844,1446910847,NG +1446910848,1446910855,IQ +1446910856,1446910883,A2 +1446910884,1446910887,IQ +1446910888,1446910899,A2 +1446910900,1446910903,IQ +1446910904,1446910907,A2 +1446910908,1446910911,IQ +1446910912,1446910927,A2 +1446910928,1446910931,NG +1446910932,1446910935,A2 +1446910936,1446910943,IQ +1446910944,1446910947,A2 +1446910948,1446910955,IQ +1446910956,1446910963,A2 +1446910964,1446910967,AF +1446910968,1446910971,IQ +1446910972,1446910975,AF +1446910976,1446910979,IQ +1446910980,1446910991,AF +1446910992,1446910999,IQ +1446911000,1446911003,A2 +1446911004,1446911007,IQ +1446911008,1446911011,LY +1446911012,1446911015,A2 +1446911016,1446911023,IQ +1446911024,1446911027,LY +1446911028,1446911035,AF +1446911036,1446911039,LY +1446911040,1446911043,A2 +1446911044,1446911047,IQ +1446911048,1446911051,LY +1446911052,1446911055,AF +1446911056,1446911059,A2 +1446911060,1446911067,IQ +1446911068,1446911075,A2 +1446911076,1446911079,IQ +1446911080,1446911087,LY +1446911088,1446911091,A2 +1446911092,1446911095,IQ +1446911096,1446911099,NG +1446911100,1446911103,IQ +1446911104,1446911111,SD +1446911112,1446911115,A2 +1446911116,1446911135,SD +1446911136,1446911143,A2 +1446911144,1446911147,TD +1446911148,1446911163,A2 +1446911164,1446911171,IQ +1446911172,1446911175,A2 +1446911176,1446911179,IQ +1446911180,1446911191,A2 +1446911192,1446911203,IQ +1446911204,1446911207,A2 +1446911208,1446911219,IQ +1446911220,1446911223,A2 +1446911224,1446911227,AF +1446911228,1446911231,LY +1446911232,1446911239,IQ +1446911240,1446911243,A2 +1446911244,1446911247,LY +1446911248,1446911251,A2 +1446911252,1446911255,IQ +1446911256,1446911259,A2 +1446911260,1446911263,AF +1446911264,1446911267,IQ +1446911268,1446911271,AF +1446911272,1446911283,A2 +1446911284,1446911287,IQ +1446911288,1446911291,LY +1446911292,1446911295,IQ +1446911296,1446911299,GH +1446911300,1446911303,IQ +1446911304,1446911311,A2 +1446911312,1446911315,LY +1446911316,1446911319,IQ +1446911320,1446911323,A2 +1446911324,1446911327,IQ +1446911328,1446911331,NG +1446911332,1446911335,ZM +1446911336,1446911339,IQ +1446911340,1446911343,AF +1446911344,1446911347,A2 +1446911348,1446911351,LY +1446911352,1446911355,IQ +1446911356,1446911359,A2 +1446911360,1446911363,IQ +1446911364,1446911367,A2 +1446911368,1446911371,LY +1446911372,1446911375,A2 +1446911376,1446911379,LY +1446911380,1446911387,A2 +1446911388,1446911395,LY +1446911396,1446911399,A2 +1446911400,1446911403,LY +1446911404,1446911407,AF +1446911408,1446911415,A2 +1446911416,1446911423,IQ +1446911424,1446911427,AF +1446911428,1446911435,A2 +1446911436,1446911439,SD +1446911440,1446911447,A2 +1446911448,1446911459,IQ +1446911460,1446911463,A2 +1446911464,1446911467,IQ +1446911468,1446911475,A2 +1446911476,1446911479,ER +1446911480,1446911483,CG +1446911484,1446911503,A2 +1446911504,1446911507,IQ +1446911508,1446911515,A2 +1446911516,1446911523,IQ +1446911524,1446911527,A2 +1446911528,1446911531,IQ +1446911532,1446911539,A2 +1446911540,1446911543,IQ +1446911544,1446911547,AF +1446911548,1446911551,LY +1446911552,1446911559,AF +1446911560,1446911567,A2 +1446911568,1446911571,IQ +1446911572,1446911575,LY +1446911576,1446911579,IQ +1446911580,1446911587,A2 +1446911588,1446911591,IQ +1446911592,1446911595,A2 +1446911596,1446911597,LY +1446911598,1446911615,A2 +1446911616,1446911619,LY +1446911620,1446911623,GH +1446911624,1446911627,IQ +1446911628,1446911631,AF +1446911632,1446911635,A2 +1446911636,1446911639,IQ +1446911640,1446911647,A2 +1446911648,1446911651,ZM +1446911652,1446911655,A2 +1446911656,1446911659,IQ +1446911660,1446911671,A2 +1446911672,1446911675,LY +1446911676,1446911679,IQ +1446911680,1446911683,SD +1446911684,1446911687,A2 +1446911688,1446911691,LY +1446911692,1446911695,AF +1446911696,1446911699,A2 +1446911700,1446911707,LY +1446911708,1446911711,IQ +1446911712,1446911715,LY +1446911716,1446911719,IQ +1446911720,1446911723,LY +1446911724,1446911727,IQ +1446911728,1446911739,LY +1446911740,1446911747,A2 +1446911748,1446911751,IQ +1446911752,1446911759,LY +1446911760,1446911763,IQ +1446911764,1446911767,A2 +1446911768,1446911771,AF +1446911772,1446911779,IQ +1446911780,1446911783,AF +1446911784,1446911787,LY +1446911788,1446911791,AF +1446911792,1446911795,LY +1446911796,1446911803,A2 +1446911804,1446911811,LY +1446911812,1446911815,IQ +1446911816,1446911819,LY +1446911820,1446911827,IQ +1446911828,1446911835,A2 +1446911836,1446911843,IQ +1446911844,1446911847,A2 +1446911848,1446911851,IQ +1446911852,1446911855,A2 +1446911856,1446911859,AF +1446911860,1446911863,A2 +1446911864,1446911867,IQ +1446911868,1446911871,LY +1446911872,1446911879,A2 +1446911880,1446911883,IQ +1446911884,1446911887,NG +1446911888,1446911891,IQ +1446911892,1446911895,A2 +1446911896,1446911899,IQ +1446911900,1446911903,A2 +1446911904,1446911907,AF +1446911908,1446911911,IQ +1446911912,1446911923,A2 +1446911924,1446911927,IQ +1446911928,1446911935,A2 +1446911936,1446911939,IQ +1446911940,1446911943,A2 +1446911944,1446911955,IQ +1446911956,1446911959,A2 +1446911960,1446911967,IQ +1446911968,1446911975,A2 +1446911976,1446911987,IQ +1446911988,1446911991,AF +1446911992,1446911995,A2 +1446911996,1446911999,IQ +1446912000,1446912003,BJ +1446912004,1446912007,AF +1446912008,1446912011,IQ +1446912012,1446912015,A2 +1446912016,1446912019,BJ +1446912020,1446912023,ZM +1446912024,1446912027,A2 +1446912028,1446912031,AF +1446912032,1446912035,IQ +1446912036,1446912039,AF +1446912040,1446912047,A2 +1446912048,1446912051,IQ +1446912052,1446912055,ER +1446912056,1446912059,A2 +1446912060,1446912063,NG +1446912064,1446912067,AF +1446912068,1446912071,IQ +1446912072,1446912075,AE +1446912076,1446912079,A2 +1446912080,1446912083,IQ +1446912084,1446912087,A2 +1446912088,1446912091,IQ +1446912092,1446912095,LY +1446912096,1446912099,AF +1446912100,1446912107,IQ +1446912108,1446912111,A2 +1446912112,1446912115,IQ +1446912116,1446912119,LY +1446912120,1446912123,A2 +1446912124,1446912127,LY +1446912128,1446912139,A2 +1446912140,1446912143,IQ +1446912144,1446912147,AF +1446912148,1446912151,IQ +1446912152,1446912163,A2 +1446912164,1446912167,IQ +1446912168,1446912179,A2 +1446912180,1446912183,ZM +1446912184,1446912187,AF +1446912188,1446912195,IQ +1446912196,1446912211,A2 +1446912212,1446912219,IQ +1446912220,1446912223,LY +1446912224,1446912235,IQ +1446912236,1446912243,A2 +1446912244,1446912247,IQ +1446912248,1446912251,AF +1446912252,1446912255,A2 +1446912256,1446912263,AF +1446912264,1446912295,IQ +1446912296,1446912303,AF +1446912304,1446912319,A2 +1446912320,1446912335,IQ +1446912336,1446912343,KW +1446912344,1446912367,IQ +1446912368,1446912375,A2 +1446912376,1446912391,AF +1446912392,1446912399,GA +1446912400,1446920191,A2 1446920192,1446936575,RU 1446936576,1446952959,NO 1446952960,1446969343,QA @@ -37706,9 +39910,7 @@ 1449459712,1449525247,HU 1449525248,1449590783,RU 1449590784,1449656319,DE -1449656320,1449717759,RO -1449717760,1449718783,MD -1449718784,1449808639,RO +1449656320,1449808639,RO 1449808640,1449808895,UA 1449808896,1449840639,RO 1449840640,1449852927,MD @@ -37727,17 +39929,9 @@ 1450057728,1450065919,EE 1450065920,1450074111,DE 1450074112,1450082303,RU -1450082304,1450083327,IT -1450083328,1450083583,A2 -1450083584,1450083839,IT -1450083840,1450084351,A2 -1450084352,1450085375,IT -1450085376,1450085383,A2 -1450085384,1450085549,IT -1450085550,1450085551,A2 -1450085552,1450085679,IT -1450085680,1450085751,A2 -1450085752,1450090495,IT +1450082304,1450084351,IT +1450084352,1450085119,A2 +1450085120,1450090495,IT 1450090496,1450106879,RU 1450106880,1450115071,SK 1450115072,1450123263,RU @@ -37801,7 +39995,9 @@ 1466265600,1466269695,HU 1466269696,1466302463,SA 1466302464,1466335231,GB -1466335232,1466367999,CH +1466335232,1466367631,CH +1466367632,1466367639,AT +1466367640,1466367999,CH 1466368000,1466400767,PT 1466400768,1466433535,RU 1466433536,1466499071,DK @@ -37812,7 +40008,9 @@ 1466592256,1466592511,FR 1466592512,1466592767,GB 1466592768,1466593279,FR -1466593280,1466606847,DE +1466593280,1466604799,DE +1466604800,1466605055,ES +1466605056,1466606847,DE 1466606848,1466607103,FR 1466607104,1466613759,DE 1466613760,1466615807,ES @@ -37839,9 +40037,7 @@ 1467318272,1467334655,RU 1467334656,1467340959,GB 1467340960,1467340991,TR -1467340992,1467344127,GB -1467344128,1467344383,CA -1467344384,1467344639,GB +1467340992,1467344639,GB 1467344640,1467344895,ZA 1467344896,1467347903,GB 1467347904,1467347935,SE @@ -37857,7 +40053,9 @@ 1467367904,1467367935,DE 1467367936,1467368191,SI 1467368192,1467368319,DK -1467368320,1467369519,DE +1467368320,1467368447,DE +1467368448,1467368703,DK +1467368704,1467369519,DE 1467369520,1467369535,RU 1467369536,1467369599,DE 1467369600,1467369663,IT @@ -38000,11 +40198,14 @@ 1475175056,1475176447,NL 1475176448,1475178495,RO 1475178496,1475180543,RU -1475180544,1475181455,DE +1475180544,1475181343,DE +1475181344,1475181375,LU +1475181376,1475181455,DE 1475181456,1475181471,SC 1475181472,1475181519,DE 1475181520,1475181535,GB -1475181536,1475184639,DE +1475181536,1475181551,ES +1475181552,1475184639,DE 1475184640,1475186687,RU 1475186688,1475188735,ES 1475188736,1475190783,SE @@ -38053,10 +40254,8 @@ 1475223552,1475229695,NO 1475229696,1475229759,SE 1475229760,1475229951,NO -1475229952,1475230003,SE -1475230004,1475230015,NO -1475230016,1475230047,SE -1475230048,1475233791,NO +1475229952,1475230071,SE +1475230072,1475233791,NO 1475233792,1475234303,GB 1475234304,1475234559,IE 1475234560,1475235839,GB @@ -38179,9 +40378,7 @@ 1475636400,1475636415,JE 1475636416,1475636431,GB 1475636432,1475636447,JE -1475636448,1475637287,GB -1475637288,1475637295,JE -1475637296,1475637479,GB +1475636448,1475637479,GB 1475637480,1475637487,JE 1475637488,1475637503,GB 1475637504,1475638783,JE @@ -38196,8 +40393,8 @@ 1475639272,1475639295,JE 1475639296,1475639343,GB 1475639344,1475639351,JE -1475639352,1475639367,GB -1475639368,1475639383,JE +1475639352,1475639375,GB +1475639376,1475639383,JE 1475639384,1475639527,GB 1475639528,1475639543,JE 1475639544,1475639595,GB @@ -38217,11 +40414,14 @@ 1475706880,1475723263,RU 1475723264,1475725311,CY 1475725312,1475725951,RU -1475725952,1475727103,GB +1475725952,1475726591,GB +1475726592,1475726719,RU +1475726720,1475727103,GB 1475727104,1475727167,RU 1475727168,1475727343,GB 1475727344,1475727359,RU -1475727360,1475729407,GB +1475727360,1475727391,FI +1475727392,1475729407,GB 1475729408,1475731455,UA 1475731456,1475739647,GB 1475739648,1475756031,BG @@ -38279,8 +40479,8 @@ 1476075520,1476077911,NL 1476077912,1476077919,DE 1476077920,1476079551,NL -1476079552,1476079567,DE -1476079568,1476083711,NL +1476079552,1476079571,DE +1476079572,1476083711,NL 1476083712,1476116479,RU 1476116480,1476124671,SE 1476124672,1476132863,PL @@ -38289,7 +40489,26 @@ 1476135168,1476141055,FR 1476141056,1476149247,GB 1476149248,1476157439,NO -1476157440,1476165375,BH +1476157440,1476157535,BH +1476157536,1476157631,BR +1476157632,1476157695,BH +1476157696,1476157823,BR +1476157824,1476157855,BH +1476157856,1476157887,BR +1476157888,1476157951,BH +1476157952,1476157983,BR +1476157984,1476158079,BH +1476158080,1476158399,BR +1476158400,1476158463,BH +1476158464,1476158975,BR +1476158976,1476159231,BH +1476159232,1476159487,JO +1476159488,1476159695,GB +1476159696,1476159727,BH +1476159728,1476159951,GB +1476159952,1476159983,BH +1476159984,1476165119,GB +1476165120,1476165375,BH 1476165376,1476165631,JO 1476165632,1476173823,HR 1476173824,1476182015,BG @@ -38332,9 +40551,7 @@ 1481679776,1481680639,SE 1481680640,1481680643,GB 1481680644,1481687039,SE -1481687040,1481691071,DE -1481691072,1481691135,ES -1481691136,1481695231,DE +1481687040,1481695231,DE 1481695232,1481703423,SK 1481703424,1481711615,SA 1481711616,1481719807,RU @@ -38402,9 +40619,7 @@ 1482060920,1482060927,SK 1482060928,1482063871,CZ 1482063872,1482072063,FI -1482072064,1482076159,IT -1482076160,1482076223,CH -1482076224,1482076383,IT +1482072064,1482076383,IT 1482076384,1482076415,MT 1482076416,1482080255,IT 1482080256,1482088447,RU @@ -38476,9 +40691,7 @@ 1486295040,1486297087,ES 1486297088,1486299135,IE 1486299136,1486301183,NL -1486301184,1486301951,DK -1486301952,1486302719,SE -1486302720,1486302863,DK +1486301184,1486302863,DK 1486302864,1486302879,SE 1486302880,1486303231,DK 1486303232,1486305023,IS @@ -38497,7 +40710,7 @@ 1486321856,1486321887,NL 1486321888,1486321919,US 1486321920,1486323199,EU -1486323200,1486323215,GU +1486323200,1486323215,US 1486323216,1486323231,NL 1486323232,1486323239,GB 1486323240,1486323447,EU @@ -38559,8 +40772,8 @@ 1489646848,1489647103,IT 1489647104,1489647359,A2 1489647360,1489648639,IT -1489648640,1489649407,A2 -1489649408,1489650687,FR +1489648640,1489649663,A2 +1489649664,1489650687,FR 1489650688,1489651199,A2 1489651200,1489653759,IT 1489653760,1489657855,A2 @@ -38587,7 +40800,8 @@ 1490028544,1490029055,UA 1490029056,1490040839,NL 1490040840,1490041855,UA -1490041856,1490049879,CZ +1490041856,1490042879,NL +1490042880,1490049879,CZ 1490049880,1490049887,AT 1490049888,1490049919,CZ 1490049920,1490049983,PL @@ -38618,13 +40832,9 @@ 1490196960,1490197247,IE 1490197248,1490206719,GB 1490206720,1490223103,GE -1490223104,1490226047,GB -1490226048,1490226175,FR -1490226176,1490230719,GB +1490223104,1490230719,GB 1490230720,1490230751,FR -1490230752,1490235263,GB -1490235264,1490235391,FR -1490235392,1490255871,GB +1490230752,1490255871,GB 1490255872,1490272255,NL 1490272256,1490288639,GB 1490288640,1490305023,SK @@ -38769,7 +40979,9 @@ 1495070720,1495072767,RU 1495072768,1495105535,CZ 1495105536,1495138303,ES -1495138304,1495139327,FR +1495138304,1495139095,FR +1495139096,1495139103,IT +1495139104,1495139327,FR 1495139328,1495139583,EU 1495139584,1495139591,GB 1495139592,1495139711,EU @@ -38870,7 +41082,9 @@ 1495326720,1495330815,MD 1495330816,1495334911,RO 1495334912,1495335935,MD -1495335936,1495399935,RO +1495335936,1495339007,RO +1495339008,1495343103,MD +1495343104,1495399935,RO 1495399936,1495400191,MD 1495400192,1495623679,RO 1495623680,1495623935,MD @@ -38918,9 +41132,13 @@ 1500106528,1500106559,DE 1500106560,1500107415,NL 1500107416,1500107423,DE -1500107424,1500107775,NL +1500107424,1500107439,NL +1500107440,1500107455,DE +1500107456,1500107775,NL 1500107776,1500107903,DE -1500107904,1500110847,NL +1500107904,1500107943,NL +1500107944,1500107951,DE +1500107952,1500110847,NL 1500110848,1500119039,UA 1500119040,1500127231,TR 1500127232,1500135423,FI @@ -39001,9 +41219,13 @@ 1500231680,1500233727,DE 1500233728,1500237823,RU 1500237824,1500241919,SE -1500241920,1500242483,TR +1500241920,1500241960,TR +1500241961,1500241966,US +1500241967,1500242483,TR 1500242484,1500242485,US -1500242486,1500242801,TR +1500242486,1500242784,TR +1500242785,1500242793,GB +1500242794,1500242801,TR 1500242802,1500242814,US 1500242815,1500243008,TR 1500243009,1500243038,GB @@ -39090,8 +41312,8 @@ 1502975744,1502975775,IE 1502975776,1502975999,FR 1502976000,1502977055,US -1502977056,1502977279,FR -1502977280,1502979071,US +1502977056,1502977151,FR +1502977152,1502979071,US 1502979072,1502979103,FR 1502979104,1502979111,ES 1502979112,1502979119,FR @@ -39151,13 +41373,13 @@ 1503789056,1503821823,NO 1503821824,1503854591,UA 1503854592,1503887359,RU -1503887360,1503895607,DE -1503895608,1503895615,NL -1503895616,1503895631,DE +1503887360,1503895631,DE 1503895632,1503895639,AT -1503895640,1503895671,DE +1503895640,1503895647,GR +1503895648,1503895671,DE 1503895672,1503895679,PL -1503895680,1503895767,DE +1503895680,1503895687,IT +1503895688,1503895767,DE 1503895768,1503895783,IT 1503895784,1503895799,DE 1503895800,1503895807,CA @@ -39168,14 +41390,11 @@ 1503896360,1503896367,CH 1503896368,1503896375,DE 1503896376,1503896383,CH -1503896384,1503896415,DE -1503896416,1503896423,GR -1503896424,1503896439,DE +1503896384,1503896439,DE 1503896440,1503896447,NO 1503896448,1503896543,DE 1503896544,1503896551,FR -1503896552,1503896559,AT -1503896560,1503897303,DE +1503896552,1503897303,DE 1503897304,1503897311,BE 1503897312,1503897367,DE 1503897368,1503897375,BE @@ -39211,7 +41430,9 @@ 1503898360,1503898415,DE 1503898416,1503898423,BE 1503898424,1503898431,CH -1503898432,1503908351,DE +1503898432,1503898567,DE +1503898568,1503898575,NL +1503898576,1503908351,DE 1503908352,1503909375,IT 1503909376,1503920127,DE 1503920128,1503985663,HR @@ -39269,29 +41490,23 @@ 1505273088,1505273095,NZ 1505273096,1505279999,NL 1505280000,1505280007,IR -1505280008,1505280255,AE -1505280256,1505280271,IR -1505280272,1505284095,AE +1505280008,1505284095,AE 1505284096,1505284607,IR 1505284608,1505284863,AE 1505284864,1505288191,IR 1505288192,1505296383,RU 1505296384,1505304575,UA -1505304576,1505305198,FR -1505305199,1505305199,DK -1505305200,1505305200,BE -1505305201,1505305201,NL -1505305202,1505305202,GB -1505305203,1505305203,CA -1505305204,1505305204,FR -1505305205,1505305205,CH -1505305206,1505305206,DE -1505305207,1505305207,AT -1505305208,1505305208,IT -1505305209,1505305209,ES -1505305210,1505305210,SE -1505305211,1505305211,NO -1505305212,1505305878,FR +1505304576,1505305351,FR +1505305352,1505305359,GB +1505305360,1505305367,BE +1505305368,1505305375,ES +1505305376,1505305383,NL +1505305384,1505305391,DE +1505305392,1505305399,IT +1505305400,1505305407,PT +1505305408,1505305415,US +1505305416,1505305423,CH +1505305424,1505305878,FR 1505305879,1505305879,US 1505305880,1505305880,ES 1505305881,1505305899,FR @@ -39318,7 +41533,11 @@ 1505321984,1505322287,AT 1505322288,1505322415,DE 1505322416,1505322879,AT -1505322880,1505325055,DE +1505322880,1505324335,DE +1505324336,1505324351,AT +1505324352,1505324791,DE +1505324792,1505324799,AT +1505324800,1505325055,DE 1505325056,1505329151,AT 1505329152,1505329215,GB 1505329216,1505329375,IE @@ -39327,7 +41546,9 @@ 1505332992,1505332999,GB 1505333000,1505333623,IE 1505333624,1505333631,GB -1505333632,1505336063,IE +1505333632,1505333887,IE +1505333888,1505333951,GB +1505333952,1505336063,IE 1505336064,1505336071,GB 1505336072,1505336576,IE 1505336577,1505336639,GB @@ -39382,7 +41603,10 @@ 1505456640,1505456895,US 1505456896,1505456927,GB 1505456928,1505456935,US -1505456936,1505458175,GB +1505456936,1505456983,GB +1505456984,1505456987,IL +1505456988,1505456991,US +1505456992,1505458175,GB 1505458176,1505458431,US 1505458432,1505458463,GB 1505458464,1505458495,US @@ -39444,7 +41668,14 @@ 1506342912,1506344959,UA 1506344960,1506377727,LV 1506377728,1506410495,HR -1506410496,1506427663,DE +1506410496,1506418687,DE +1506418688,1506418695,CY +1506418696,1506418703,DE +1506418704,1506418719,CA +1506418720,1506422655,DE +1506422656,1506422687,CY +1506422688,1506422703,CA +1506422704,1506427663,DE 1506427664,1506427679,GB 1506427680,1506428223,DE 1506428224,1506428239,US @@ -39548,26 +41779,22 @@ 1506444288,1506445311,DE 1506445312,1506445337,FR 1506445338,1506445343,GB -1506445344,1506445375,FR -1506445376,1506445407,GB -1506445408,1506445519,FR +1506445344,1506445519,FR 1506445520,1506445527,GB 1506445528,1506445703,FR 1506445704,1506445711,NL 1506445712,1506445719,GB 1506445720,1506445759,FR 1506445760,1506445767,GB -1506445768,1506445775,FR -1506445776,1506445791,GB -1506445792,1506445807,FR -1506445808,1506445823,GB -1506445824,1506446159,FR -1506446160,1506446175,GB -1506446176,1506446335,FR +1506445768,1506445815,FR +1506445816,1506445823,GB +1506445824,1506446335,FR 1506446336,1506447359,NL 1506447360,1506447423,IT 1506447424,1506447455,GB -1506447456,1506448383,IT +1506447456,1506448255,IT +1506448256,1506448287,GB +1506448288,1506448383,IT 1506448384,1506448639,AT 1506448640,1506448647,GB 1506448648,1506448663,AT @@ -39606,7 +41833,8 @@ 1506453424,1506453439,SE 1506453440,1506453447,GB 1506453448,1506453471,SE -1506453472,1506453503,GB +1506453472,1506453487,GB +1506453488,1506453503,SE 1506453504,1506453759,DE 1506453760,1506454015,FR 1506454016,1506454271,AT @@ -39654,9 +41882,7 @@ 1506462624,1506462719,FR 1506462720,1506463231,IT 1506463232,1506463487,SE -1506463488,1506463527,DE -1506463528,1506463535,GB -1506463536,1506463999,DE +1506463488,1506463999,DE 1506464000,1506464767,GB 1506464768,1506465279,NL 1506465280,1506465791,GB @@ -39683,13 +41909,15 @@ 1506472448,1506472703,GB 1506472704,1506473215,IT 1506473216,1506473471,GB -1506473472,1506474271,IT +1506473472,1506473783,IT +1506473784,1506473791,GB +1506473792,1506474271,IT 1506474272,1506474303,SE 1506474304,1506474495,IT 1506474496,1506474751,FR 1506474752,1506474887,IT -1506474888,1506475007,GB -1506475008,1506475519,IT +1506474888,1506474911,GB +1506474912,1506475519,IT 1506475520,1506475527,AT 1506475528,1506476031,GB 1506476032,1506508799,KW @@ -39730,6 +41958,7 @@ 1506781888,1506781951,AU 1506781952,1506783231,GB 1506783232,1506785279,RU +1506785280,1506787327,BE 1506787328,1506789375,ME 1506789376,1506791423,DE 1506791424,1506793471,GB @@ -39829,12 +42058,12 @@ 1508642816,1508646911,SE 1508646912,1508646927,DK 1508646928,1508646935,SE -1508646936,1508647031,DK -1508647032,1508648447,SE +1508646936,1508647039,DK +1508647040,1508648447,SE 1508648448,1508648703,DK 1508648704,1508650751,SE -1508650752,1508650815,DK -1508650816,1508650879,SE +1508650752,1508650823,DK +1508650824,1508650879,SE 1508650880,1508651263,DK 1508651264,1508652543,SE 1508652544,1508654079,DK @@ -39980,8 +42209,10 @@ 1515468288,1515468415,NL 1515468416,1515486975,FR 1515486976,1515487231,CD -1515487232,1515487359,HK -1515487360,1515487999,FR +1515487232,1515487495,HK +1515487496,1515487739,FR +1515487740,1515487775,HK +1515487776,1515487999,FR 1515488000,1515488255,HK 1515488256,1515519743,FR 1515519744,1515519999,ES @@ -39992,8 +42223,8 @@ 1518452736,1518460927,AT 1518460928,1518501887,SE 1518501888,1518503935,EE -1518503936,1518508543,LT -1518508544,1518510079,SE +1518503936,1518508799,LT +1518508800,1518510079,SE 1518510080,1518516479,LV 1518516480,1518665727,SE 1518665728,1518727167,RU @@ -40007,8 +42238,8 @@ 1518962688,1518964735,NO 1518964736,1518966783,HR 1518966784,1518967807,SE -1518967808,1518969855,HR -1518969856,1518993407,SE +1518967808,1518970367,HR +1518970368,1518993407,SE 1518993408,1519190015,RU 1519190016,1519321087,SE 1519321088,1519386623,RU @@ -40163,19 +42394,21 @@ 1519976448,1520009215,DE 1520009216,1520041983,SY 1520041984,1520074751,RU -1520074752,1520099327,BG -1520099328,1520099583,A2 -1520099584,1520107519,BG +1520074752,1520107519,BG 1520107520,1520138167,GB 1520138168,1520138175,IE -1520138176,1520140287,GB +1520138176,1520138611,GB +1520138612,1520138615,IE +1520138616,1520139399,GB +1520139400,1520139407,IE +1520139408,1520140287,GB 1520140288,1520173055,RU 1520173056,1520205823,PL 1520205824,1520230399,RU 1520230400,1520230911,NL 1520230912,1520231935,RU -1520231936,1520232191,NL -1520232192,1520232959,RU +1520231936,1520232447,NL +1520232448,1520232959,RU 1520232960,1520233471,NL 1520233472,1520271359,RU 1520271360,1520304127,SI @@ -40319,7 +42552,10 @@ 1534711808,1534712831,BE 1534712832,1534713855,FR 1534713856,1534713887,PL -1534713888,1534713935,FR +1534713888,1534713919,FR +1534713920,1534713927,IT +1534713928,1534713931,GB +1534713932,1534713935,FI 1534713936,1534713943,CH 1534713944,1534713947,DE 1534713948,1534713951,PL @@ -40357,8 +42593,9 @@ 1534714352,1534714367,CH 1534714368,1534714383,GB 1534714384,1534714399,FR -1534714400,1534714415,ES -1534714416,1534714431,GB +1534714400,1534714403,GB +1534714404,1534714407,PL +1534714408,1534714431,GB 1534714432,1534714463,FR 1534714464,1534714495,GB 1534714496,1534714511,FR @@ -40381,8 +42618,8 @@ 1534714848,1534714855,GB 1534714856,1534714863,CH 1534714864,1534714871,FR -1534714872,1534714875,DE -1534714876,1534714879,FR +1534714872,1534714875,ES +1534714876,1534714879,DE 1534714880,1534714895,PL 1534714896,1534714911,FR 1534714912,1534714927,DE @@ -40392,19 +42629,20 @@ 1534715040,1534715055,GB 1534715056,1534715071,PL 1534715072,1534715135,FR -1534715136,1534715139,PL -1534715140,1534715143,GB -1534715144,1534715151,NL -1534715152,1534715167,FR +1534715136,1534715143,PL +1534715144,1534715167,FR 1534715168,1534715183,NL 1534715184,1534715199,FR -1534715200,1534715203,DE +1534715200,1534715203,GB 1534715204,1534715207,FR 1534715208,1534715215,BE 1534715216,1534715263,FR 1534715264,1534715279,ES 1534715280,1534715295,FR -1534715296,1534715311,ES +1534715296,1534715299,ES +1534715300,1534715303,FR +1534715304,1534715307,ES +1534715308,1534715311,DE 1534715312,1534715315,FR 1534715316,1534715319,ES 1534715320,1534715327,PL @@ -40414,29 +42652,37 @@ 1534715372,1534715375,GB 1534715376,1534715391,ES 1534715392,1534715407,PL -1534715408,1534715423,ES +1534715408,1534715423,DE 1534715424,1534715439,PL 1534715440,1534715447,ES 1534715448,1534715451,FR 1534715452,1534715487,PL -1534715488,1534715503,ES +1534715488,1534715495,IT +1534715496,1534715503,CZ 1534715504,1534715519,CH 1534715520,1534715551,FR 1534715552,1534715583,ES 1534715584,1534715599,GB 1534715600,1534715615,BE -1534715616,1534715631,FR -1534715632,1534715647,ES +1534715616,1534715639,FR +1534715640,1534715647,DE 1534715648,1534715663,PL -1534715664,1534715679,ES +1534715664,1534715667,FR +1534715668,1534715675,PL +1534715676,1534715679,GB 1534715680,1534715711,FR 1534715712,1534715727,PT 1534715728,1534715731,FR 1534715732,1534715735,GB 1534715736,1534715759,PL -1534715760,1534715807,ES +1534715760,1534715775,ES +1534715776,1534715783,PL +1534715784,1534715791,BE +1534715792,1534715807,ES 1534715808,1534715871,FR -1534715872,1534715887,DE +1534715872,1534715879,FI +1534715880,1534715883,CH +1534715884,1534715887,PL 1534715888,1534715919,FR 1534715920,1534715935,ES 1534715936,1534715999,FR @@ -40490,7 +42736,8 @@ 1534716992,1534717007,DE 1534717008,1534717023,FR 1534717024,1534717055,PL -1534717056,1534717103,FR +1534717056,1534717071,GB +1534717072,1534717103,FR 1534717104,1534717119,PL 1534717120,1534717135,IT 1534717136,1534717139,CH @@ -40498,8 +42745,8 @@ 1534717144,1534717147,FR 1534717148,1534717151,IT 1534717152,1534717263,FR -1534717264,1534717279,ES -1534717280,1534717315,FR +1534717264,1534717267,PL +1534717268,1534717315,FR 1534717316,1534717319,IE 1534717320,1534717323,GB 1534717324,1534717343,FR @@ -40531,7 +42778,10 @@ 1534717908,1534717911,GB 1534717912,1534717915,FR 1534717916,1534717919,DE -1534717920,1534717935,ES +1534717920,1534717923,PL +1534717924,1534717927,ES +1534717928,1534717931,DE +1534717932,1534717935,FR 1534717936,1534717951,IT 1534717952,1534717967,BE 1534717968,1534717983,IT @@ -40573,8 +42823,7 @@ 1534718832,1534718847,FR 1534718848,1534718911,BE 1534718912,1534718927,IT -1534718928,1534718943,FR -1534718944,1534718959,DE +1534718928,1534718959,FR 1534718960,1534718975,ES 1534718976,1534719039,FR 1534719040,1534719167,BE @@ -40593,7 +42842,7 @@ 1534719424,1534719439,DE 1534719440,1534719455,PL 1534719456,1534719471,FR -1534719472,1534719487,GB +1534719472,1534719487,IE 1534719488,1534719631,FR 1534719632,1534719639,ES 1534719640,1534719643,GB @@ -40617,7 +42866,8 @@ 1534719952,1534719967,DE 1534719968,1534719983,PL 1534719984,1534720003,FR -1534720004,1534720015,PL +1534720004,1534720007,ES +1534720008,1534720015,PL 1534720016,1534720031,GB 1534720032,1534720047,DE 1534720048,1534720063,ES @@ -40625,14 +42875,15 @@ 1534720080,1534720095,GB 1534720096,1534720111,FR 1534720112,1534720127,ES -1534720128,1534720207,FR -1534720208,1534720223,GB +1534720128,1534720211,FR +1534720212,1534720215,PL +1534720216,1534720223,FR 1534720224,1534720239,DE 1534720240,1534720255,BE 1534720256,1534720287,PL 1534720288,1534720351,FR 1534720352,1534720367,ES -1534720368,1534720383,IT +1534720368,1534720383,PL 1534720384,1534720431,FR 1534720432,1534720435,DE 1534720436,1534720439,FR @@ -40650,12 +42901,13 @@ 1534720528,1534720535,FR 1534720536,1534720539,PL 1534720540,1534720543,FI -1534720544,1534720575,FR -1534720576,1534720591,ES +1534720544,1534720559,FR +1534720560,1534720583,IT +1534720584,1534720591,BE 1534720592,1534720607,FR 1534720608,1534720623,GB -1534720624,1534720655,FR -1534720656,1534720671,PL +1534720624,1534720639,FR +1534720640,1534720671,PL 1534720672,1534720739,FR 1534720740,1534720743,PL 1534720744,1534720747,NL @@ -40673,7 +42925,9 @@ 1534720896,1534720899,ES 1534720900,1534720903,GB 1534720904,1534720959,FR -1534720960,1534720975,ES +1534720960,1534720967,IT +1534720968,1534720971,DE +1534720972,1534720975,FR 1534720976,1534720979,NL 1534720980,1534720983,FR 1534720984,1534720991,PL @@ -40730,11 +42984,9 @@ 1534721712,1534721727,ES 1534721728,1534721743,FR 1534721744,1534721747,PL -1534721748,1534721751,IT +1534721748,1534721751,GB 1534721752,1534721755,DE -1534721756,1534721775,FR -1534721776,1534721791,ES -1534721792,1534721823,FR +1534721756,1534721823,FR 1534721824,1534721827,PL 1534721828,1534721831,FR 1534721832,1534721835,PL @@ -40749,19 +43001,19 @@ 1534721956,1534721959,PL 1534721960,1534721963,IE 1534721964,1534721967,CH -1534721968,1534721975,DE +1534721968,1534721971,DE +1534721972,1534721975,PL 1534721976,1534721979,ES 1534721980,1534721983,GB 1534721984,1534722007,PL 1534722008,1534722011,PT -1534722012,1534722015,DE -1534722016,1534722031,FR -1534722032,1534722039,GB +1534722012,1534722015,ES +1534722016,1534722039,FR 1534722040,1534722043,BE 1534722044,1534722047,FR 1534722048,1534787583,RU 1534787584,1534791679,RO -1534791680,1534795775,UA +1534791680,1534795775,RU 1534795776,1534803967,NO 1534803968,1534808063,LV 1534808064,1534812159,RU @@ -40769,7 +43021,7 @@ 1534816256,1534820351,FR 1534820352,1534824447,FI 1534824448,1534828543,UA -1534828544,1534832639,PL +1534828544,1534836735,PL 1534836736,1534840831,SE 1534840832,1534844927,PL 1534844928,1534849023,IE @@ -40929,7 +43181,9 @@ 1536659760,1536659775,BI 1536659776,1536659791,DE 1536659792,1536659823,SD -1536659824,1536659991,DE +1536659824,1536659943,DE +1536659944,1536659951,SD +1536659952,1536659991,DE 1536659992,1536659999,EG 1536660000,1536660003,DE 1536660004,1536660007,SO @@ -40946,9 +43200,7 @@ 1536662320,1536662335,LB 1536662336,1536662351,DE 1536662352,1536662359,TD -1536662360,1536662367,DE -1536662368,1536662399,IQ -1536662400,1536662415,DE +1536662360,1536662415,DE 1536662416,1536662431,GN 1536662432,1536662463,IQ 1536662464,1536662783,DE @@ -40957,8 +43209,8 @@ 1536663296,1536663311,LB 1536663312,1536663319,DE 1536663320,1536663327,LB -1536663328,1536663359,DE -1536663360,1536663391,IQ +1536663328,1536663343,DE +1536663344,1536663391,IQ 1536663392,1536663423,DE 1536663424,1536663551,KW 1536663552,1536667647,SA @@ -41046,10 +43298,7 @@ 1539049312,1539049327,LY 1539049328,1539049335,IT 1539049336,1539049343,LY -1539049344,1539050335,IT -1539050336,1539050351,TR -1539050352,1539050359,IT -1539050360,1539050367,TR +1539049344,1539050367,IT 1539050368,1539050375,FR 1539050376,1539050383,IT 1539050384,1539050399,FR @@ -41110,13 +43359,13 @@ 1539212544,1539213311,CZ 1539213312,1539215359,SE 1539215360,1539219455,DE -1539221504,1539222287,FR -1539222288,1539222303,HK -1539222304,1539222527,FR +1539219456,1539221503,GG +1539221504,1539222527,FR 1539222528,1539222783,HK 1539222784,1539223551,FR 1539223552,1539225599,DE 1539225600,1539227647,HU +1539227648,1539229695,FI 1539229696,1539231743,DE 1539231744,1539233791,BE 1539233792,1539235839,GR @@ -41162,6 +43411,7 @@ 1539336192,1539336703,UA 1539336704,1539337215,EE 1539337216,1539338239,ES +1539338240,1539339263,SE 1539339264,1539340287,NL 1539340288,1539341311,PL 1539341312,1539342335,IT @@ -41240,7 +43490,7 @@ 1539421184,1539422207,GB 1539422208,1539423231,PL 1539423232,1539424255,IE -1539424256,1539425279,UA +1539424256,1539425279,LV 1539425280,1539426303,PL 1539426304,1539427327,BG 1539427328,1539428351,UA @@ -41741,7 +43991,8 @@ 1539744256,1539744511,RO 1539744512,1539744767,DE 1539744768,1539745023,SE -1539745024,1539745535,GB +1539745024,1539745279,GB +1539745280,1539745535,GI 1539745536,1539745791,CH 1539745792,1539746303,DK 1539746304,1539746815,RU @@ -41788,6 +44039,7 @@ 1539757568,1539757823,SI 1539757824,1539758079,UA 1539758080,1539758335,HR +1539758336,1539758591,EU 1539758592,1539758847,NL 1539758848,1539759103,BA 1539759104,1539759359,DK @@ -42159,7 +44411,7 @@ 1539947520,1539948543,UA 1539948544,1539949567,RO 1539949568,1539950591,MD -1539950592,1539951615,KZ +1539950592,1539951103,KZ 1539951616,1539953663,RU 1539953664,1539954687,UA 1539954688,1539956735,RO @@ -42237,7 +44489,7 @@ 1540047872,1540048895,LV 1540048896,1540049919,GB 1540049920,1540050943,UA -1540050944,1540051967,RU +1540050944,1540052991,RU 1540052992,1540054052,UA 1540054053,1540054062,MD 1540054063,1540055039,UA @@ -42357,10 +44609,11 @@ 1540199424,1540200447,CH 1540200448,1540201471,IL 1540201472,1540202495,UA +1540202496,1540203519,RU 1540203520,1540204543,UA 1540204544,1540205567,RU 1540205568,1540206591,DE -1540206592,1540207615,RU +1540206592,1540208639,RU 1540208640,1540209663,NO 1540209664,1540211711,RU 1540211712,1540212735,DE @@ -42508,6 +44761,7 @@ 1540303872,1540304895,UA 1540304896,1540305407,PL 1540305408,1540305919,GB +1540305920,1540306431,PL 1540306432,1540306943,UA 1540306944,1540307455,GB 1540307456,1540307967,RU @@ -42974,6 +45228,7 @@ 1540464384,1540464895,DE 1540464896,1540465407,GB 1540465408,1540465663,ES +1540465664,1540465919,NL 1540465920,1540466175,UA 1540466176,1540466431,DK 1540466432,1540466687,RU @@ -43448,7 +45703,6 @@ 1540701952,1540702207,GB 1540702208,1540702463,PL 1540702464,1540702719,PT -1540702720,1540702975,AT 1540702976,1540703231,RU 1540703232,1540703487,MH 1540703488,1540703743,NL @@ -43500,8 +45754,7 @@ 1540716800,1540717055,UA 1540717056,1540717311,CZ 1540717312,1540717823,PL -1540717824,1540718079,UA -1540718080,1540718335,CR +1540717824,1540718335,UA 1540718336,1540718591,DE 1540718592,1540718847,CH 1540718848,1540719103,IT @@ -43753,6 +46006,7 @@ 1540891136,1540891391,NL 1540891392,1540891647,DE 1540891648,1540891903,CH +1540891904,1540892159,GB 1540892160,1540892415,IT 1540892416,1540892671,UA 1540892672,1540892927,GB @@ -43779,6 +46033,7 @@ 1540898304,1540898559,SE 1540898560,1540898815,ES 1540898816,1540899071,PL +1540899072,1540899327,SE 1540899328,1540899583,RU 1540899584,1540899839,FR 1540899840,1540900351,RU @@ -43999,11 +46254,15 @@ 1540974080,1540974591,RU 1540974592,1540975103,PL 1540975104,1540975615,UA -1540976128,1540976639,RU +1540975616,1540976639,RU 1540976640,1540977151,UA 1540977152,1540977663,PL 1540977664,1540978175,FI 1540978176,1540978687,AT +1540978688,1540979199,RU +1540979200,1540979711,SI +1540979712,1540980223,RU +1540980224,1540980735,SI 1540980736,1540980991,CH 1540980992,1540981247,RU 1540981248,1540981503,RO @@ -44103,7 +46362,6 @@ 1541007616,1541007871,RU 1541007872,1541008127,FR 1541008128,1541008383,NL -1541008384,1541008639,UA 1541008640,1541008895,GB 1541008896,1541009151,TR 1541009152,1541009407,RU @@ -44116,8 +46374,7 @@ 1541010944,1541011199,CY 1541011200,1541011455,CH 1541011456,1541011711,FI -1541011712,1541011967,UA -1541011968,1541012223,RU +1541011712,1541012223,RU 1541012224,1541012479,DE 1541012480,1541012735,FI 1541012736,1541013247,UA @@ -44190,6 +46447,293 @@ 1541093376,1541094399,RU 1541094400,1541095423,UA 1541095424,1541096447,RU +1541096448,1541097471,AT +1541097472,1541098495,RU +1541098496,1541099519,NL +1541099520,1541100543,UA +1541100544,1541101567,HU +1541101568,1541102591,RU +1541102592,1541103615,RO +1541103616,1541105663,RU +1541105664,1541106687,PL +1541106688,1541107711,NL +1541107712,1541108735,PL +1541108736,1541109759,ES +1541109760,1541110783,PL +1541110784,1541111807,RU +1541111808,1541112831,PL +1541112832,1541113855,SK +1541113856,1541115903,RU +1541115904,1541116927,UA +1541116928,1541117951,RU +1541117952,1541118975,DK +1541118976,1541122047,RU +1541123072,1541124095,FI +1541124096,1541126143,RU +1541126144,1541127167,PL +1541127168,1541129215,RU +1541129216,1541130239,UA +1541130240,1541132287,RU +1541132288,1541133311,PL +1541133312,1541134335,RO +1541134336,1541135359,SE +1541135360,1541136383,UA +1541136384,1541138431,RU +1541138432,1541139455,UA +1541139456,1541140479,HU +1541140480,1541142527,CZ +1541142528,1541143551,RU +1541143552,1541144575,UA +1541144576,1541144831,LV +1541144832,1541145087,RU +1541145088,1541145343,AT +1541145344,1541145599,UA +1541145600,1541145855,IT +1541145856,1541146111,RU +1541146112,1541146367,UA +1541146368,1541146623,DK +1541146624,1541146879,AT +1541146880,1541147135,IL +1541147136,1541147391,PL +1541147392,1541147903,RU +1541147904,1541148159,EU +1541148160,1541148415,RO +1541148416,1541148671,GB +1541148672,1541148927,RU +1541148928,1541149439,PL +1541149440,1541149695,SE +1541149696,1541149951,LT +1541149952,1541150207,NL +1541150208,1541150463,IL +1541150464,1541150719,CH +1541150720,1541151231,GB +1541151232,1541151487,RO +1541151488,1541151743,FR +1541151744,1541151999,NL +1541152000,1541152255,HU +1541152256,1541152511,NL +1541152512,1541152767,RU +1541152768,1541153023,PL +1541153024,1541153279,RU +1541153280,1541153535,DE +1541153536,1541153791,UA +1541153792,1541154047,DE +1541154048,1541154303,NL +1541154304,1541154559,RU +1541154560,1541154815,PL +1541154816,1541155071,CH +1541155072,1541155327,CY +1541155328,1541155583,GB +1541155584,1541155839,RU +1541155840,1541156095,PL +1541156096,1541156351,IE +1541156352,1541156607,RU +1541156608,1541156863,SE +1541156864,1541157119,RO +1541157120,1541157375,DE +1541157376,1541157631,TR +1541157632,1541157887,KZ +1541157888,1541158143,GB +1541158144,1541158399,NL +1541158400,1541158655,PL +1541158656,1541158911,SI +1541158912,1541159167,DE +1541159168,1541159423,RU +1541159424,1541159679,SE +1541159680,1541159935,LT +1541159936,1541160447,UA +1541160448,1541160703,RU +1541160704,1541160959,MD +1541160960,1541161215,CH +1541161216,1541161471,TR +1541161472,1541161727,ES +1541161728,1541161983,DE +1541161984,1541162239,BE +1541162240,1541162495,RU +1541162496,1541162751,GB +1541162752,1541163007,DE +1541163008,1541163263,RO +1541163264,1541163519,PL +1541163520,1541163775,DE +1541163776,1541164031,RO +1541164032,1541164287,RU +1541164288,1541164543,HR +1541164544,1541164799,SI +1541164800,1541165055,IR +1541165056,1541165311,UA +1541165312,1541165567,RU +1541165568,1541165823,NL +1541165824,1541166079,GB +1541166080,1541166335,RU +1541166336,1541166591,FR +1541166592,1541166847,RO +1541166848,1541167103,RU +1541167104,1541167359,NL +1541167360,1541167615,AT +1541167616,1541167871,RU +1541167872,1541168127,UA +1541168128,1541168383,RU +1541168640,1541168895,MD +1541168896,1541169151,MK +1541169152,1541169407,RO +1541169408,1541169663,PL +1541169664,1541169919,SE +1541169920,1541170431,CH +1541170432,1541170687,UA +1541170688,1541170943,BE +1541170944,1541171199,PL +1541171200,1541171455,UA +1541171456,1541171711,PL +1541171712,1541171967,UA +1541171968,1541172223,SI +1541172224,1541172479,GR +1541172480,1541172735,RU +1541172736,1541172991,RO +1541172992,1541173247,BE +1541173248,1541173503,RU +1541173504,1541173759,UA +1541173760,1541174015,LT +1541174016,1541174271,DE +1541174272,1541174527,FR +1541174528,1541174783,SE +1541174784,1541175039,GB +1541175040,1541175295,SI +1541175296,1541175551,RU +1541175552,1541175807,RO +1541175808,1541176063,CZ +1541176064,1541176319,NL +1541176320,1541176575,AM +1541176576,1541176831,DE +1541176832,1541177087,RU +1541177088,1541177343,GB +1541177344,1541177599,CH +1541177600,1541177855,DE +1541177856,1541178111,RO +1541178112,1541178367,RU +1541178368,1541178623,GB +1541178624,1541178879,RU +1541178880,1541179135,DE +1541179136,1541179391,RU +1541179392,1541179647,BE +1541179648,1541179903,RU +1541179904,1541180159,IS +1541180160,1541180415,MT +1541180416,1541180671,UA +1541180672,1541180927,GB +1541180928,1541181183,IT +1541181184,1541181439,NO +1541181440,1541181695,MD +1541181696,1541182207,RU +1541182208,1541182463,NL +1541182464,1541182719,DE +1541182720,1541182975,RO +1541182976,1541183231,SE +1541183232,1541183487,UA +1541183488,1541183743,RU +1541183744,1541183999,DE +1541184000,1541184255,BE +1541184256,1541184511,RU +1541184512,1541184767,SI +1541184768,1541185023,DE +1541185024,1541185279,ES +1541185280,1541185535,DE +1541185536,1541185791,GB +1541185792,1541186047,UA +1541186048,1541186303,CH +1541186304,1541186559,UA +1541186560,1541186815,PL +1541186816,1541187071,NO +1541187072,1541187327,RU +1541187328,1541187583,RO +1541187584,1541187839,IT +1541187840,1541188351,RU +1541188352,1541188607,FR +1541188608,1541188863,HU +1541188864,1541189119,RU +1541189120,1541189375,UA +1541189376,1541189631,GB +1541189632,1541189887,BG +1541189888,1541190143,PL +1541190144,1541190399,GB +1541190400,1541190655,AT +1541190656,1541190911,GB +1541190912,1541191167,RU +1541191168,1541191423,TR +1541191424,1541191679,RO +1541191680,1541192191,NL +1541210112,1541210623,RU +1541210624,1541211135,CZ +1541211136,1541211647,SK +1541211648,1541212159,RU +1541212160,1541212671,DE +1541212672,1541213183,MT +1541213184,1541213695,DE +1541213696,1541214207,UA +1541214208,1541215743,RU +1541215744,1541216255,SA +1541216256,1541216767,RU +1541216768,1541217279,PL +1541217280,1541218303,RU +1541218304,1541218815,IT +1541218816,1541219839,RU +1541219840,1541220351,CZ +1541220352,1541221375,RU +1541221376,1541221887,PL +1541221888,1541222399,CZ +1541222400,1541222911,RU +1541222912,1541223423,DK +1541223424,1541223935,UA +1541223936,1541224447,GB +1541224448,1541224959,RU +1541224960,1541225471,DE +1541225472,1541225983,RU +1541225984,1541226495,LV +1541226496,1541227007,UA +1541227008,1541227519,FI +1541227520,1541228031,GB +1541228032,1541228543,RU +1541228544,1541229055,CZ +1541229056,1541229567,UA +1541229568,1541230079,RU +1541230080,1541230591,RO +1541230592,1541231103,RU +1541231104,1541231615,GB +1541231616,1541232127,UA +1541232128,1541232639,RU +1541232640,1541233151,PL +1541233152,1541233663,RU +1541233664,1541234175,SK +1541234176,1541234687,RO +1541234688,1541235199,NL +1541235200,1541235711,LV +1541235712,1541236223,AT +1541236224,1541236735,RU +1541236736,1541237247,DE +1541237248,1541237759,RU +1541237760,1541238271,CZ +1541238272,1541238783,ES +1541238784,1541239295,SK +1541239296,1541239807,PL +1541239808,1541240319,RU +1541240320,1541240831,CH +1541240832,1541241343,DE +1541241344,1541241855,PL +1541241856,1541242367,UA +1541242368,1541242879,PL +1541242880,1541243391,KW +1541243392,1541243903,NO +1541243904,1541244415,UA +1541244416,1541244927,RS +1541275648,1541276671,UA +1541276672,1541277695,RS +1541277696,1541278719,ES +1541278720,1541280767,UA +1541280768,1541281791,BG +1541281792,1541282815,PL +1541282816,1541283839,RU +1541283840,1541286911,UA +1541286912,1541287935,DE +1541287936,1541288959,UA 1543503872,1545601023,GB 1545601024,1545863167,SE 1545863168,1545895935,RU @@ -44253,6 +46797,7 @@ 1546270720,1546272767,GB 1546272768,1546274815,NO 1546274816,1546276863,SE +1546276864,1546278911,IT 1546278912,1546280959,RU 1546280960,1546283007,IT 1546283008,1546285055,CH @@ -44316,17 +46861,13 @@ 1546649600,1546665983,SA 1546665984,1546673823,GB 1546673824,1546673839,RS -1546673840,1546677503,GB -1546677504,1546677551,IN +1546673840,1546677535,GB +1546677536,1546677551,IN 1546677552,1546677555,GB 1546677556,1546677557,IN 1546677558,1546677559,GB 1546677560,1546677561,IN -1546677562,1546677567,GB -1546677568,1546677569,IN -1546677570,1546677571,GB -1546677572,1546677573,IN -1546677574,1546677679,GB +1546677562,1546677679,GB 1546677680,1546677695,IN 1546677696,1546678863,GB 1546678864,1546678871,RS @@ -44351,6 +46892,7 @@ 1546895360,1546911743,IE 1546911744,1546928127,SK 1546928128,1546944511,GB +1546944512,1546960895,UA 1546960896,1546977279,HU 1546977280,1546993663,MK 1546993664,1547010047,RU @@ -44560,8 +47102,8 @@ 1559314432,1559322623,GE 1559322624,1559330815,RU 1559330816,1559339007,BA -1559339008,1559339711,RU -1559339712,1559339775,A1 +1559339008,1559339743,RU +1559339744,1559339775,MH 1559339776,1559341695,RU 1559341696,1559341703,ES 1559341704,1559347199,RU @@ -44640,8 +47182,8 @@ 1566101504,1566105599,RU 1566105600,1566109695,DE 1566109696,1566111231,CH -1566111232,1566111295,FR -1566111296,1566113791,CH +1566111232,1566111487,FR +1566111488,1566113791,CH 1566113792,1566117887,DE 1566117888,1566121983,TR 1566121984,1566126079,NO @@ -44724,7 +47266,6 @@ 1566363648,1566365695,GB 1566365696,1566367743,RU 1566367744,1566371839,ES -1566371840,1566373887,RU 1566373888,1566375935,RS 1566375936,1566377983,DE 1566377984,1566380031,BG @@ -44799,18 +47340,22 @@ 1566468896,1566469391,BE 1566469392,1566469407,HU 1566469408,1566470143,BE -1566470144,1566470320,IE -1566470321,1566470343,GB +1566470144,1566470159,IE +1566470160,1566470171,GB +1566470172,1566470239,IE +1566470240,1566470343,GB 1566470344,1566470351,IE 1566470352,1566470367,GB -1566470368,1566470719,IE +1566470368,1566470511,IE +1566470512,1566470655,GB +1566470656,1566470719,IE 1566470720,1566470727,GB 1566470728,1566470739,IE 1566470740,1566470743,GB -1566470744,1566470747,IE -1566470748,1566470767,GB -1566470768,1566470847,IE -1566470848,1566470911,GB +1566470744,1566470847,IE +1566470848,1566470879,GB +1566470880,1566470895,IR +1566470896,1566470911,GB 1566470912,1566472191,IE 1566472192,1566474239,GB 1566474240,1566476287,DE @@ -44856,7 +47401,9 @@ 1566564352,1566566399,IS 1566566400,1566568447,FR 1566568448,1566570495,KZ -1566570496,1566572543,NL +1566570496,1566570943,NL +1566570944,1566570951,DE +1566570952,1566572543,NL 1566572544,1566703615,GB 1566703616,1566769151,SA 1566769152,1566773759,CZ @@ -44937,6 +47484,7 @@ 1570504704,1570570239,ES 1570570240,1570572287,NL 1570572288,1570574335,UA +1570574336,1570576383,RU 1570576384,1570578431,UA 1570578432,1570580479,CH 1570580480,1570582527,RU @@ -44948,6 +47496,7 @@ 1570596864,1570598911,UA 1570598912,1570600959,PL 1570600960,1570603007,RU +1570603008,1570605055,CZ 1570605056,1570607103,NL 1570607104,1570609151,RU 1570609152,1570611199,PL @@ -45055,7 +47604,9 @@ 1570667524,1570667527,IT 1570667528,1570667531,NO 1570667532,1570667535,GB -1570667536,1570667711,SE +1570667536,1570667587,SE +1570667588,1570667591,US +1570667592,1570667711,SE 1570667712,1570667727,FR 1570667728,1570667743,NL 1570667744,1570667775,SE @@ -45080,6 +47631,7 @@ 1570717696,1570725887,HR 1570725888,1570734079,DE 1570734080,1570750463,PL +1570750464,1570752511,AL 1570752512,1570754559,GB 1570754560,1570756607,ES 1570756608,1570764799,RU @@ -45087,7 +47639,13 @@ 1570766848,1571291135,DK 1571291136,1571422207,RO 1571422208,1571426303,RU -1571426304,1571553279,CZ +1571426304,1571428351,CZ +1571428352,1571428863,UA +1571428864,1571430399,CZ +1571430400,1571435519,UA +1571435520,1571446783,CZ +1571446784,1571448831,KZ +1571448832,1571553279,CZ 1571553280,1571684351,IL 1571684352,1571686399,ES 1571686400,1571688447,GB @@ -45224,7 +47782,8 @@ 1572504320,1572504575,DE 1572504576,1572504703,RO 1572504704,1572504831,TR -1572504832,1572507199,IT +1572504832,1572505087,SG +1572505088,1572507199,IT 1572507200,1572507207,GB 1572507208,1572507647,IT 1572507648,1572511743,GB @@ -45250,7 +47809,6 @@ 1572542000,1572542207,GB 1572542208,1572542463,FR 1572542464,1572544511,IT -1572544512,1572546559,HR 1572546560,1572548607,FR 1572548608,1572550655,GB 1572550656,1572552703,DE @@ -45313,7 +47871,13 @@ 1572661248,1572663295,NO 1572663296,1572665343,DE 1572665344,1572667391,NL -1572667392,1572669439,GB +1572667392,1572668303,GB +1572668304,1572668311,SA +1572668312,1572668415,GB +1572668416,1572668431,SA +1572668432,1572668463,GB +1572668464,1572668471,SA +1572668472,1572669439,GB 1572669440,1572673535,RU 1572673536,1572675583,AT 1572675584,1572677631,ES @@ -45386,13 +47950,12 @@ 1572800512,1572804607,RU 1572804608,1572808703,GB 1572808704,1572810751,FR -1572810752,1572812031,DE -1572812032,1572812543,RO -1572812544,1572812799,DE +1572810752,1572812799,DE 1572812800,1572814847,RU 1572814848,1572816895,KW 1572816896,1572818943,RU 1572818944,1572820991,FR +1572820992,1572823039,CH 1572823040,1572825087,BY 1572825088,1572827135,RU 1572827136,1572829183,NO @@ -45413,9 +47976,10 @@ 1572849664,1572851711,GB 1572851712,1572853759,DE 1572853760,1572854015,BE -1572854016,1572854527,LU +1572854016,1572854271,LU +1572854272,1572854527,BE 1572854528,1572855551,EU -1572855552,1572855807,LU +1572855552,1572855807,BE 1572855808,1572857855,KZ 1572857856,1572859903,SE 1572859904,1572861951,IT @@ -45443,8 +48007,8 @@ 1578590304,1578590311,IT 1578590312,1578590319,FR 1578590320,1578590335,CH -1578590336,1578590343,FR -1578590344,1578590351,GB +1578590336,1578590347,FR +1578590348,1578590351,PL 1578590352,1578590415,FR 1578590416,1578590431,PL 1578590432,1578590447,BE @@ -45477,7 +48041,7 @@ 1578590928,1578590935,DE 1578590936,1578590943,ES 1578590944,1578590959,CH -1578590960,1578590975,NL +1578590960,1578590975,FR 1578590976,1578590991,GB 1578590992,1578590999,IT 1578591000,1578591007,FR @@ -45497,18 +48061,17 @@ 1578591248,1578591263,PL 1578591264,1578591279,FR 1578591280,1578591287,ES -1578591288,1578591291,DE +1578591288,1578591291,NL 1578591292,1578591295,ES 1578591296,1578591327,FR 1578591328,1578591343,PL -1578591344,1578591359,FR -1578591360,1578591375,PL -1578591376,1578591391,FR +1578591344,1578591391,FR 1578591392,1578591407,CH -1578591408,1578591423,GB +1578591408,1578591411,ES +1578591412,1578591415,FR +1578591416,1578591423,ES 1578591424,1578591431,PL -1578591432,1578591435,DE -1578591436,1578591439,ES +1578591432,1578591439,ES 1578591440,1578591463,FR 1578591464,1578591487,PL 1578591488,1578591503,FR @@ -45533,14 +48096,16 @@ 1578591808,1578591823,DE 1578591824,1578591887,FR 1578591888,1578591891,DE -1578591892,1578591903,FR +1578591892,1578591899,FR +1578591900,1578591903,GB 1578591904,1578591919,PL 1578591920,1578591939,ES 1578591940,1578591951,FR 1578591952,1578591967,PT 1578591968,1578591983,FR 1578591984,1578592031,PL -1578592032,1578592047,IT +1578592032,1578592039,PT +1578592040,1578592047,ES 1578592048,1578592079,FR 1578592080,1578592095,PL 1578592096,1578592111,FR @@ -45555,9 +48120,9 @@ 1578592192,1578592199,BE 1578592200,1578592207,CH 1578592208,1578592223,FR -1578592224,1578592255,ES -1578592256,1578592271,FR -1578592272,1578592279,NL +1578592224,1578592239,ES +1578592240,1578592275,FR +1578592276,1578592279,FI 1578592280,1578592283,BE 1578592284,1578592287,NL 1578592288,1578592303,DE @@ -45580,16 +48145,17 @@ 1578592536,1578592543,NL 1578592544,1578592559,FR 1578592560,1578592575,NL -1578592576,1578592687,FR -1578592688,1578592719,ES +1578592576,1578592591,GB +1578592592,1578592687,FR +1578592688,1578592695,DE +1578592696,1578592719,ES 1578592720,1578592735,CH 1578592736,1578592751,FR 1578592752,1578592783,DE 1578592784,1578592799,FR 1578592800,1578592815,GB 1578592816,1578592823,PL -1578592824,1578592827,FR -1578592828,1578592831,IE +1578592824,1578592831,FR 1578592832,1578592847,PL 1578592848,1578592851,BE 1578592852,1578592855,DE @@ -45667,7 +48233,11 @@ 1578594312,1578594315,PL 1578594316,1578594319,FR 1578594320,1578594335,PL -1578594336,1578594375,FR +1578594336,1578594355,GB +1578594356,1578594359,FR +1578594360,1578594363,PT +1578594364,1578594367,IT +1578594368,1578594375,FR 1578594376,1578594383,PT 1578594384,1578594399,FR 1578594400,1578594431,PL @@ -45676,7 +48246,7 @@ 1578594464,1578594479,FR 1578594480,1578594495,ES 1578594496,1578594511,FR -1578594512,1578594515,DE +1578594512,1578594515,PL 1578594516,1578594519,FR 1578594520,1578594523,PL 1578594524,1578594543,FR @@ -45693,7 +48263,7 @@ 1578594712,1578594715,IT 1578594716,1578594751,FR 1578594752,1578594767,ES -1578594768,1578594771,DE +1578594768,1578594771,GB 1578594772,1578594775,FR 1578594776,1578594783,ES 1578594784,1578594799,FR @@ -45730,8 +48300,8 @@ 1578595388,1578595391,PL 1578595392,1578595423,CH 1578595424,1578595455,LT -1578595456,1578595463,DE -1578595464,1578595487,FR +1578595456,1578595459,DE +1578595460,1578595487,FR 1578595488,1578595503,DE 1578595504,1578595519,PL 1578595520,1578595607,FR @@ -45740,7 +48310,12 @@ 1578595616,1578595647,PL 1578595648,1578595679,FR 1578595680,1578595695,BE -1578595696,1578595763,FR +1578595696,1578595711,FR +1578595712,1578595743,GB +1578595744,1578595747,IT +1578595748,1578595751,FR +1578595752,1578595759,ES +1578595760,1578595763,FR 1578595764,1578595775,ES 1578595776,1578595807,CH 1578595808,1578595983,FR @@ -45750,7 +48325,9 @@ 1578596096,1578596099,DE 1578596100,1578596103,GB 1578596104,1578596111,FR -1578596112,1578596127,ES +1578596112,1578596115,DE +1578596116,1578596123,PT +1578596124,1578596127,ES 1578596128,1578596143,PL 1578596144,1578596147,DE 1578596148,1578596151,FR @@ -45778,14 +48355,18 @@ 1578610688,1578610943,FR 1578610944,1578610975,ES 1578610976,1578611039,PL -1578611040,1578611071,FR +1578611040,1578611043,ES +1578611044,1578611047,CZ +1578611048,1578611051,ES +1578611052,1578611055,PL +1578611056,1578611071,FR 1578611072,1578611075,DE 1578611076,1578611079,FR 1578611080,1578611087,NL 1578611088,1578611119,DE 1578611120,1578611135,FR 1578611136,1578611151,CH -1578611152,1578611167,FR +1578611152,1578611167,DE 1578611168,1578611183,ES 1578611184,1578611199,FR 1578611200,1578611215,NL @@ -45805,7 +48386,7 @@ 1578611400,1578611403,BE 1578611404,1578611407,ES 1578611408,1578611423,IT -1578611424,1578611439,FR +1578611424,1578611439,GB 1578611440,1578611455,IT 1578611456,1578611711,FR 1578611712,1578611775,CH @@ -45820,12 +48401,11 @@ 1578611952,1578611967,FR 1578611968,1578612159,GB 1578612160,1578612223,PL -1578612224,1578612239,DE +1578612224,1578612239,GB 1578612240,1578612255,FR 1578612256,1578612259,PL 1578612260,1578612263,IT -1578612264,1578612271,FR -1578612272,1578612287,ES +1578612264,1578612287,FR 1578612288,1578612303,BE 1578612304,1578612319,DE 1578612320,1578612383,FR @@ -45838,7 +48418,8 @@ 1578612704,1578612863,FR 1578612864,1578612895,NL 1578612896,1578612911,PL -1578612912,1578612975,ES +1578612912,1578612959,ES +1578612960,1578612975,GB 1578612976,1578612991,FR 1578612992,1578613247,DE 1578613248,1578613503,FR @@ -45889,7 +48470,9 @@ 1579091840,1579091855,US 1579091856,1579091967,GB 1579091968,1579092223,DE -1579092224,1579104511,GB +1579092224,1579093759,GB +1579093760,1579094015,NL +1579094016,1579104511,GB 1579104512,1579104767,NL 1579104768,1579105023,GB 1579105024,1579105151,NL @@ -45910,7 +48493,9 @@ 1580015616,1580048383,UA 1580048384,1580064767,RU 1580064768,1580072959,DE -1580072960,1580134399,PT +1580072960,1580085247,PT +1580085248,1580089343,MZ +1580089344,1580134399,PT 1580134400,1580136447,ES 1580136448,1580138495,PT 1580138496,1580204031,IT @@ -46028,7 +48613,9 @@ 1583813736,1583813743,DE 1583813744,1583813808,NL 1583813809,1583813815,US -1583813816,1583816703,NL +1583813816,1583815167,NL +1583815168,1583815199,US +1583815200,1583816703,NL 1583816704,1583820799,TR 1583820800,1583824895,LV 1583824896,1583828991,SI @@ -46043,7 +48630,13 @@ 1583848704,1583848735,NL 1583848736,1583848799,BE 1583848800,1583849471,NL -1583849472,1583853567,DE +1583849472,1583850751,DE +1583850752,1583850943,AT +1583850944,1583850951,DE +1583850952,1583850959,AT +1583850960,1583850999,DE +1583851000,1583851007,AT +1583851008,1583853567,DE 1583853568,1583857663,RU 1583857664,1583861759,SE 1583861760,1583865855,LU @@ -46097,7 +48690,9 @@ 1585265696,1585265727,IM 1585265728,1585265767,FR 1585265768,1585265775,IM -1585265776,1585266111,FR +1585265776,1585265919,FR +1585265920,1585265935,IM +1585265936,1585266111,FR 1585266112,1585266687,IM 1585266688,1585270783,DE 1585270784,1585272831,IT @@ -46207,14 +48802,15 @@ 1585991684,1585991687,US 1585991688,1585991935,SE 1585991936,1585991939,US -1585991940,1585995775,SE +1585991940,1585994499,SE +1585994500,1585994503,RU +1585994504,1585995775,SE 1585995776,1586003967,AT 1586003968,1586012159,SK 1586012160,1586020351,DE 1586020352,1586028543,RU 1586028544,1586036735,GB -1586036736,1586061311,RU -1586061312,1586069503,HR +1586036736,1586069503,RU 1586069504,1586077695,DE 1586077696,1586085887,GE 1586085888,1586110463,RU @@ -46281,6 +48877,7 @@ 1586438144,1586446335,RU 1586446336,1586448383,NO 1586448384,1586450431,ES +1586450432,1586452479,FR 1586452480,1586454527,CH 1586454528,1586456575,IT 1586456576,1586458623,GB @@ -46325,7 +48922,9 @@ 1588068352,1588592639,GB 1588592640,1588621311,RO 1588621312,1588625407,MD -1588625408,1588723711,RO +1588625408,1588670463,RO +1588670464,1588674559,MD +1588674560,1588723711,RO 1588723712,1588854783,UA 1588854784,1588985855,RU 1588985856,1589182463,IR @@ -46453,14 +49052,15 @@ 1592069888,1592074239,RU 1592074240,1592078335,SK 1592078336,1592082431,NL -1592082432,1592086527,GB +1592082432,1592085023,GB +1592085024,1592085039,ES +1592085040,1592086527,GB 1592086528,1592087295,CZ 1592087296,1592088063,PL 1592088064,1592090623,CZ 1592090624,1592094719,RU 1592094720,1592098815,RS 1592098816,1592102911,GB -1592102912,1592107007,PT 1592107008,1592111103,GB 1592111104,1592115199,DE 1592115200,1592119295,ES @@ -46501,6 +49101,7 @@ 1592287232,1592289279,RO 1592289280,1592291327,RU 1592291328,1592293375,NL +1592293376,1592295423,LT 1592295424,1592299519,RU 1592299520,1592303615,PL 1592303616,1592305663,NL @@ -46551,7 +49152,9 @@ 1593180160,1593196543,NO 1593196544,1593196783,SE 1593196784,1593196799,GB -1593196800,1593203455,SE +1593196800,1593202687,SE +1593202688,1593202815,NO +1593202816,1593203455,SE 1593203456,1593203487,NO 1593203488,1593204159,SE 1593204160,1593204223,DK @@ -46561,9 +49164,7 @@ 1593206084,1593206095,DK 1593206096,1593206103,FI 1593206104,1593206111,GB -1593206112,1593206207,SE -1593206208,1593206271,FI -1593206272,1593209151,SE +1593206112,1593209151,SE 1593209152,1593209155,GR 1593209156,1593209159,HU 1593209160,1593209163,FI @@ -46620,9 +49221,7 @@ 1593606144,1593638911,SY 1593638912,1593671679,RU 1593671680,1593704447,HR -1593704448,1593704959,SE -1593704960,1593705471,NO -1593705472,1593737215,SE +1593704448,1593737215,SE 1593737216,1593769983,PL 1593769984,1593802751,RU 1593802752,1593835519,SE @@ -46665,9 +49264,16 @@ 1599078400,1599094783,SE 1599094784,1599111167,RU 1599111168,1599127551,IR -1599127552,1599143935,CZ +1599127552,1599133695,CZ +1599133696,1599133823,SK +1599133824,1599134207,CZ +1599134208,1599134463,AT +1599134464,1599143935,CZ +1599143936,1599160319,UA 1599160320,1599176703,IR -1599176704,1599193087,FR +1599176704,1599188991,FR +1599188992,1599189263,DE +1599189264,1599193087,FR 1599193088,1599209471,RU 1599209472,1599242239,IR 1599242240,1599258623,CZ @@ -46753,7 +49359,9 @@ 1602271232,1602273279,MK 1602273280,1602273535,FR 1602273536,1602273791,GB -1602273792,1602275327,FR +1602273792,1602274559,IN +1602274560,1602274815,IE +1602274816,1602275327,FR 1602275328,1602275615,DE 1602275616,1602275647,CY 1602275648,1602279423,DE @@ -46781,8 +49389,10 @@ 1602314240,1602316287,CZ 1602316288,1602318335,GB 1602318336,1602320383,ES -1602320384,1602324479,NL -1602324480,1602326527,RU +1602320384,1602322687,NL +1602322688,1602322703,IE +1602322704,1602324479,NL +1602324480,1602328575,RU 1602328576,1602330623,ES 1602330624,1602336767,RU 1602336768,1602338815,GB @@ -46856,7 +49466,9 @@ 1602453504,1602455551,SK 1602455552,1602456015,FR 1602456016,1602456023,ES -1602456024,1602457599,FR +1602456024,1602456175,FR +1602456176,1602456183,ES +1602456184,1602457599,FR 1602457600,1602459647,RU 1602459648,1602461695,GB 1602461696,1602465791,ES @@ -46942,9 +49554,7 @@ 1603170304,1603174399,IE 1603174400,1603178495,TR 1603178496,1603182591,DK -1603182592,1603184639,FR -1603184640,1603185663,GB -1603185664,1603186687,FR +1603182592,1603186687,FR 1603186688,1603190783,IT 1603190784,1603194879,RU 1603194880,1603198975,IT @@ -46963,8 +49573,18 @@ 1603223937,1603223951,GB 1603223952,1603224319,FR 1603224320,1603224575,GB -1603224576,1603224735,FR -1603224736,1603226623,GB +1603224576,1603224775,FR +1603224776,1603224783,GB +1603224784,1603224799,FR +1603224800,1603225599,GB +1603225600,1603225607,ES +1603225608,1603225615,GB +1603225616,1603225623,DE +1603225624,1603225631,IT +1603225632,1603225639,US +1603225640,1603225647,CN +1603225648,1603225855,FR +1603225856,1603226623,GB 1603226624,1603227391,FR 1603227392,1603227647,GB 1603227648,1603231743,AT @@ -47056,7 +49676,11 @@ 1604894464,1604894719,DE 1604894720,1604895487,CZ 1604895488,1604895491,SK -1604895492,1604902911,CZ +1604895492,1604895607,CZ +1604895608,1604895611,SK +1604895612,1604900351,CZ +1604900352,1604900383,SC +1604900384,1604902911,CZ 1604902912,1604911103,BG 1604911104,1604919295,UA 1604919296,1604927487,NO @@ -47083,18 +49707,22 @@ 1605099520,1605107711,RU 1605107712,1605115903,GB 1605115904,1605124095,RU -1605124096,1605124351,US -1605124352,1605125263,GB +1605124096,1605124607,US +1605124608,1605124671,GB +1605124672,1605124735,US +1605124736,1605125263,GB 1605125264,1605125287,US 1605125288,1605125311,GB 1605125312,1605125319,US 1605125320,1605125327,GB -1605125328,1605125335,US -1605125336,1605125375,GB +1605125328,1605125343,US +1605125344,1605125375,GB 1605125376,1605125631,US 1605125632,1605126143,DE 1605126144,1605127679,US -1605127680,1605132287,GB +1605127680,1605130239,GB +1605130240,1605130271,US +1605130272,1605132287,GB 1605132288,1605148671,RU 1605148672,1605156863,PT 1605156864,1605165055,JO @@ -47179,7 +49807,9 @@ 1607947264,1607948287,RU 1607948288,1607949311,GB 1607949312,1607950335,UA +1607950336,1607952383,RU 1607952384,1607953407,UA +1607954432,1607956479,UA 1607956480,1607957503,ES 1607957504,1607958527,UA 1607958528,1607959551,PS @@ -47192,9 +49822,9 @@ 1607967744,1607968767,UA 1607968768,1607969791,SE 1607969792,1607971839,RU +1607972864,1607974911,NL 1607974912,1607975935,LV 1607976960,1607977983,KZ -1607977984,1607979007,NL 1607979008,1607980031,RU 1607980032,1607981055,DE 1607981056,1607982079,UA @@ -47231,8 +49861,8 @@ 1613471744,1613479935,JM 1613479936,1613488127,US 1613488128,1613492223,CA -1613496320,1613504511,US -1613512704,1613529087,CA +1613492224,1613504511,US +1613504512,1613529087,CA 1613529088,1613536191,US 1613536192,1613536223,TW 1613536224,1613536255,US @@ -47286,8 +49916,11 @@ 1613570048,1613574143,CA 1613574144,1613586431,US 1613586432,1613590527,CA -1613590528,1613606911,US -1613606912,1613615103,CA +1613590528,1613602815,US +1613606912,1613607423,CA +1613607424,1613607679,GB +1613607680,1613607935,US +1613607936,1613615103,CA 1613615104,1613635583,US 1613635584,1613639679,CA 1613639680,1613676543,US @@ -47322,7 +49955,9 @@ 1632355512,1632355519,US 1632355520,1632355583,CA 1632355584,1632355599,US -1632355600,1632362495,CA +1632355600,1632357439,CA +1632357440,1632357447,US +1632357448,1632362495,CA 1632362496,1634414591,US 1634414592,1634418687,CA 1634418688,1634447359,US @@ -47924,7 +50559,9 @@ 1652681520,1653534719,US 1653534720,1653538815,CA 1653538816,1653555199,US -1653555200,1653567487,CA +1653555200,1653560319,CA +1653560320,1653560327,US +1653560328,1653567487,CA 1653567488,1653571583,US 1653571584,1653575679,CA 1653575680,1653592063,US @@ -47936,9 +50573,12 @@ 1654546432,1654550527,VG 1654550528,1654554623,US 1654554624,1654558719,CA -1654558720,1654597631,US -1654597632,1654597887,CA -1654597888,1654648831,US +1654558720,1654583071,US +1654583072,1654583103,TR +1654583104,1654583135,CA +1654583136,1654599455,US +1654599456,1654599471,CA +1654599472,1654648831,US 1654648832,1654652927,CA 1654652928,1665833175,US 1665833176,1665833183,A2 @@ -48060,15 +50700,19 @@ 1697775616,1697776639,AP 1700790272,1702887679,AU 1711210496,1711276031,AP -1795162112,1796210687,US -1811939328,1828716543,US +1795162112,1815822335,US +1815822336,1815826431,CA +1815826432,1815846911,US +1815871488,1815879679,CA +1816133632,1822425087,US 1828716544,1830813695,FR 1830813696,1831337983,NL 1831337984,1831862271,DE 1831862272,1832124415,PT 1832124416,1832386559,IT 1832386560,1832517631,DK -1832517632,1832648703,SE +1832517632,1832615935,SE +1832615936,1832648703,DK 1832648704,1832681471,HR 1832681472,1832714239,RU 1832714240,1832747007,HU @@ -48244,7 +50888,6 @@ 1833504768,1833508863,DE 1833508864,1833512959,RU 1833512960,1833517055,DE -1833517056,1833521151,ES 1833521152,1833525247,IT 1833525248,1833529343,LV 1833529344,1833533439,GB @@ -48329,7 +50972,7 @@ 1834960896,1834964991,RU 1834964992,1834967039,PL 1834967040,1834971135,RU -1834971136,1834973183,KZ +1834971136,1834973183,UA 1834973184,1834975231,RU 1834975232,1834977279,IL 1834977280,1834983423,PL @@ -48493,7 +51136,9 @@ 1839801280,1839801311,VG 1839801312,1839801343,GB 1839801344,1839801471,CN -1839801472,1839801599,GB +1839801472,1839801551,GB +1839801552,1839801567,US +1839801568,1839801599,GB 1839801600,1839801855,US 1839801856,1839802111,GB 1839802112,1839802239,RO @@ -48543,13 +51188,14 @@ 1841629184,1841635327,RU 1841635328,1841639423,PL 1841639424,1841641471,RU -1841641472,1841643519,PL +1841641472,1841645567,PL 1841645568,1841647615,RU 1841647616,1841649663,RO 1841649664,1841651711,RU 1841651712,1841653759,PL 1841653760,1841655807,FR 1841655808,1841668095,RU +1841668096,1841670143,RO 1841670144,1841672191,PL 1841672192,1841674239,FR 1841674240,1841676287,PL @@ -48578,13 +51224,22 @@ 1841827088,1841827231,GB 1841827232,1841827263,BR 1841827264,1841827279,BD -1841827280,1841831935,GB +1841827280,1841827463,GB +1841827464,1841827471,BD +1841827472,1841827479,ES +1841827480,1841827695,GB +1841827696,1841827703,ES +1841827704,1841828879,GB +1841828880,1841828895,MT +1841828896,1841831935,GB 1841831936,1841840127,MT 1841840128,1841848319,PL 1841848320,1841856511,RU 1841856512,1841864703,UA 1841864704,1841872895,YE -1841872896,1841881087,NL +1841872896,1841879807,NL +1841879808,1841880063,GB +1841880064,1841881087,JP 1841881088,1841889279,UA 1841889280,1841897471,IR 1841897472,1841905663,RO @@ -48693,12 +51348,15 @@ 1843707904,1843724287,TR 1843724288,1843732479,UA 1843732480,1843765247,RU +1843765248,1843773439,KZ 1843773440,1843781631,LV 1843781632,1843789823,RU 1843789824,1843806207,SK 1843806208,1843822591,IR 1843822592,1843838975,RU -1843838976,1843855359,DE +1843838976,1843849215,DE +1843849216,1843850239,GB +1843850240,1843855359,DE 1843855360,1843871743,PL 1843871744,1843888127,GB 1843888128,1843904511,CZ @@ -48820,9 +51478,11 @@ 1844162560,1844164607,CZ 1844164608,1844166655,RU 1844166656,1844168703,AZ -1844168704,1844169727,LB -1844169728,1844170387,DE -1844170388,1844170751,GI +1844168704,1844169487,SE +1844169488,1844169503,IQ +1844169504,1844169983,SE +1844169984,1844170387,DE +1844170388,1844170751,SE 1844170752,1844174847,RU 1844174848,1844178943,DE 1844178944,1844180991,EE @@ -48834,7 +51494,25 @@ 1844181953,1844181958,GB 1844181959,1844181984,TR 1844181985,1844181990,GB -1844181991,1844183039,TR +1844181991,1844182271,TR +1844182272,1844182302,US +1844182303,1844182309,TR +1844182310,1844182329,US +1844182330,1844182343,TR +1844182344,1844182403,US +1844182404,1844182416,TR +1844182417,1844182417,US +1844182418,1844182424,TR +1844182425,1844182426,US +1844182427,1844182432,TR +1844182433,1844182442,US +1844182443,1844182459,TR +1844182460,1844182480,US +1844182481,1844182485,TR +1844182486,1844182489,US +1844182490,1844182501,TR +1844182502,1844182511,US +1844182512,1844183039,TR 1844183040,1844191231,IT 1844191232,1844195327,AL 1844195328,1844203519,RU @@ -48854,6 +51532,7 @@ 1844256768,1844260863,BA 1844260864,1844264959,CH 1844264960,1844269055,NL +1844269056,1844273151,UA 1844273152,1844277247,RU 1844277248,1844281343,AZ 1844281344,1844285439,DE @@ -49013,7 +51692,6 @@ 1851590656,1851591679,AU 1851592704,1851594751,AU 1851594752,1851596799,KR -1851596800,1851604991,IN 1851604992,1851613183,PH 1851613184,1851617279,JP 1851617280,1851637759,KR @@ -49189,7 +51867,6 @@ 1877706752,1877707775,SG 1877707776,1877709823,AU 1877710848,1877711871,AP -1877711872,1877712895,BD 1877712896,1877721087,CN 1877721088,1877737471,TW 1877737472,1877999615,JP @@ -49450,12 +52127,12 @@ 1916272640,1916534783,ID 1916534784,1917124607,CN 1917124608,1917169663,JP -1917169664,1917177855,NC +1917169664,1917181951,NC 1917181952,1917190143,IN 1917190144,1917321215,KR 1917321216,1917779967,AU 1917779968,1917796351,ID -1917796352,1917845503,IN +1917812736,1917845503,IN 1917845504,1919680511,CN 1919680512,1919729663,KR 1919729664,1919746047,PH @@ -49510,6 +52187,8 @@ 1921867776,1921871871,AU 1921875968,1921892351,CN 1921892352,1921896447,AU +1921896448,1921898495,SG +1921898496,1921900543,PH 1921900544,1921908735,KR 1921908736,1921943551,JP 1921943552,1921945599,IN @@ -50495,7 +53174,9 @@ 2038423552,2038431743,HK 2038431744,2042626047,KR 2042626048,2043150335,CN -2043150336,2043166719,AU +2043150336,2043162623,AU +2043162624,2043165695,IN +2043165696,2043166719,BD 2043166720,2043183103,KR 2043183104,2043199487,JP 2043199488,2043201535,BD @@ -50561,7 +53242,7 @@ 2053521408,2053529599,CN 2053529600,2053533695,AU 2053533696,2053534719,VN -2053535744,2053537791,IN +2053534720,2053537791,IN 2053537792,2053636095,JP 2053636096,2054160383,AU 2054160384,2054422527,CN @@ -50751,7 +53432,6 @@ 2066882560,2066890751,TW 2066890752,2066907135,PF 2066907136,2066915327,AU -2066915328,2066923519,IN 2066923520,2066939903,JP 2066939904,2066972671,AU 2066972672,2067005439,TW @@ -51109,6 +53789,7 @@ 2110832640,2110865407,KR 2110865408,2110881791,PK 2110881792,2110898175,AU +2110898176,2110914559,KR 2110914560,2111045631,CN 2111045632,2111078399,PH 2111078400,2111111167,VN @@ -51477,7 +54158,8 @@ 2194604032,2194669567,US 2194669568,2194735103,IS 2194735104,2194800639,GB -2194800640,2195193855,US +2194800640,2194866175,US +2194931712,2195193855,US 2195193856,2195324927,NZ 2195324928,2195455999,US 2195456000,2195521535,AU @@ -51680,7 +54362,9 @@ 2249457664,2249523199,US 2249523200,2249588735,CH 2249588736,2249654271,CA -2249654272,2249781247,US +2249654272,2249724671,US +2249724672,2249724927,CA +2249724928,2249781247,US 2249781248,2249781255,FR 2249781256,2249785343,US 2249785344,2249850879,SE @@ -52251,7 +54935,10 @@ 2329673728,2329739263,US 2329739264,2329804799,CH 2329804800,2329870335,DE -2329870336,2330132479,CH +2329870336,2329935871,CH +2329935872,2330001407,DE +2330001408,2330066943,CH +2330066944,2330132479,US 2330132480,2330198015,SE 2330198016,2330263551,CH 2330263552,2330394623,US @@ -52549,11 +55236,11 @@ 2382102528,2382168063,NL 2382168064,2382233599,BE 2382233600,2382299135,US -2382364672,2385430319,CA -2385430320,2385430335,US -2385430336,2385430655,CA +2382364672,2385430655,CA 2385430656,2385430687,US -2385430688,2386067455,CA +2385430688,2385903615,CA +2385903616,2385969151,US +2385969152,2386067455,CA 2386067456,2386083839,US 2386083840,2386624511,CA 2386624512,2386690047,US @@ -52565,7 +55252,10 @@ 2387410944,2387476479,US 2387476480,2387542015,CA 2387542016,2387607551,US -2387607552,2394947583,CA +2387607552,2390818815,CA +2390884352,2390995455,CA +2390995456,2391015423,US +2391015424,2394947583,CA 2394947584,2395013119,US 2395013120,2395209727,CA 2395340800,2399141887,CA @@ -52956,9 +55646,7 @@ 2467233792,2468020223,US 2468020224,2468085759,GR 2468085760,2468151295,JP -2468151296,2468174847,DK -2468174848,2468175359,NO -2468175360,2468189663,DK +2468151296,2468189663,DK 2468189664,2468189695,GB 2468189696,2468216831,DK 2468216832,2468282367,EU @@ -53418,7 +56106,9 @@ 2601451520,2601517055,CA 2601517056,2602565631,US 2602565632,2602631167,NZ -2602631168,2604007423,US +2602631168,2603417599,US +2603417600,2603483135,DE +2603483136,2604007423,US 2604007424,2604072959,ES 2604072960,2604138495,NO 2604138496,2604204031,DE @@ -53598,7 +56288,8 @@ 2642280448,2642411519,US 2642411520,2642477055,AU 2642477056,2642542591,FI -2642542592,2642935807,US +2642542592,2642608127,US +2642673664,2642935807,US 2642935808,2643001343,FR 2643001344,2643066879,US 2643066880,2643132415,IT @@ -54685,9 +57376,7 @@ 2816014272,2816015319,IL 2816015320,2816015327,US 2816015328,2816015335,IL -2816015336,2816015343,US -2816015344,2816015359,IL -2816015360,2816015423,US +2816015336,2816015423,US 2816015424,2816016383,IL 2816016384,2816671743,US 2816671744,2816737279,CA @@ -54915,35 +57604,25 @@ 2904555520,2904817663,CA 2904817664,2905376767,US 2905376768,2905377535,CA -2905377536,2905377791,US -2905377792,2905378047,CA -2905378048,2905378303,US +2905377536,2905378303,US 2905378304,2905378815,CA 2905378816,2905379071,US 2905379072,2905379583,CA -2905379584,2905380863,US -2905380864,2905381119,CA -2905381120,2905381887,US +2905379584,2905381887,US 2905381888,2905382016,CA -2905382017,2905384191,US -2905384192,2905385471,CA -2905385472,2905386239,US -2905386240,2905386495,CA -2905386496,2905388031,US +2905382017,2905384959,US +2905384960,2905385471,CA +2905385472,2905388031,US 2905388032,2905388287,CA -2905388288,2905391871,US -2905391872,2905392127,CA -2905392128,2905392895,US -2905392896,2905394943,CA +2905388288,2905392895,US +2905392896,2905393151,CA +2905393152,2905394175,US +2905394176,2905394943,CA 2905394944,2905395455,US 2905395456,2905396991,CA -2905396992,2905397759,US -2905397760,2905398271,CA -2905398272,2905399039,US +2905396992,2905399039,US 2905399040,2905399295,CA -2905399296,2905404671,US -2905404672,2905405183,CA -2905405184,2905407743,US +2905399296,2905407743,US 2905407744,2905407999,TW 2905408000,2905428967,US 2905428968,2905428975,AE @@ -55245,28 +57924,21 @@ 2915811136,2915811199,IN 2915811200,2915958783,US 2915958784,2916024319,CA -2916024320,2916091903,US -2916091904,2916092159,IN -2916092160,2916092927,US -2916092928,2916093183,IN -2916093184,2916093695,US -2916093696,2916093951,IN -2916093952,2916110623,US +2916024320,2916110623,US 2916110624,2916110639,CA 2916110640,2916163583,US 2916163584,2916171775,CA -2916171776,2916188159,US -2916188160,2916196351,CA -2916196352,2916200447,US -2916204544,2916253695,US +2916171776,2916184063,US +2916184064,2916196351,CA +2916196352,2916253695,US 2916253696,2916286463,CA 2916286464,2916319231,US 2916319232,2916335615,PR 2916352000,2916368383,US 2916368384,2916401151,CA 2916401152,2916417535,US -2916417536,2916434495,CA -2916434496,2916434559,US +2916417536,2916434431,CA +2916434432,2916434559,US 2916434560,2916434591,CA 2916434592,2916437503,US 2916437504,2916437567,CA @@ -55274,7 +57946,11 @@ 2916440064,2916440095,CA 2916440096,2916440143,US 2916440144,2916440159,CA -2916440160,2916441343,US +2916440160,2916440175,US +2916440176,2916440191,CA +2916440192,2916441119,US +2916441120,2916441151,CA +2916441152,2916441343,US 2916441344,2916442111,CA 2916442112,2916442623,US 2916442624,2916442879,CA @@ -55285,11 +57961,7 @@ 2916443904,2916444159,CA 2916444160,2916444927,US 2916444928,2916445951,CA -2916445952,2916447231,US -2916447232,2916448031,CA -2916448032,2916448063,US -2916448064,2916448255,CA -2916448256,2916449279,US +2916445952,2916449279,US 2916449280,2916450303,CA 2916450304,2916515839,US 2916548608,2916581375,US @@ -55330,6 +58002,7 @@ 2917580800,2917597439,US 2917597440,2917597695,GB 2917597696,2917621759,US +2917621760,2917629951,CA 2917629952,2917646335,US 2917662720,2917663231,US 2917663232,2917663487,CA @@ -55341,33 +58014,31 @@ 2917675264,2917675775,CA 2917675776,2917676031,US 2917676032,2917677055,CA -2917677056,2917677567,US -2917677568,2917678335,CA -2917678336,2917680895,US +2917677056,2917680895,US 2917680896,2917681407,CA 2917681408,2917681919,US 2917681920,2917682175,CA -2917682176,2917685247,US -2917685248,2917686015,CA +2917682176,2917682431,US +2917682432,2917683455,CA +2917683456,2917685503,US +2917685504,2917686015,CA 2917686016,2917690367,US 2917690368,2917690879,CA 2917690880,2917693183,US 2917693184,2917693951,CA 2917693952,2917695231,US 2917695232,2917695487,CA -2917695488,2917701119,US -2917701120,2917701375,CA -2917701376,2917702399,US -2917702400,2917707519,CA -2917707520,2917711871,US -2917711872,2917714431,CA +2917695488,2917695743,US +2917695744,2917696255,CA +2917696256,2917702399,US +2917702400,2917707007,CA +2917707008,2917714175,US +2917714176,2917714431,CA 2917714432,2917718527,US 2917718528,2917719039,CA -2917719040,2917719295,US -2917719296,2917719551,CA -2917719552,2917722367,US -2917722368,2917722879,CA -2917722880,2917842175,US +2917719040,2917722367,US +2917722368,2917722623,CA +2917722624,2917842175,US 2917842176,2917842431,CA 2917842432,2918055935,US 2918055936,2918121471,CA @@ -55381,7 +58052,9 @@ 2918260736,2918264831,CA 2918264832,2918277119,US 2918277120,2918281215,CA -2918281216,2918286879,US +2918281216,2918286335,US +2918286336,2918286719,CA +2918286720,2918286879,US 2918286880,2918286895,GB 2918286896,2918287103,US 2918287104,2918287359,CR @@ -55410,12 +58083,22 @@ 2918612992,2918760447,US 2918760448,2918776831,CA 2918776832,2918813695,US -2918825984,2918838271,US +2918825984,2918828031,US +2918828032,2918828543,UA +2918828544,2918829055,ES +2918829056,2918829183,US +2918829184,2918829311,PL +2918829312,2918829439,CA +2918829440,2918829567,JM +2918829568,2918829695,GR +2918829696,2918829823,DE +2918829824,2918830079,CN +2918830080,2918834175,CA +2918834176,2918838271,US 2918838272,2918875135,CA 2918875136,2918973439,US 2918973440,2918989823,CA -2919006208,2919071743,US -2919170048,2919174143,US +2919006208,2919174143,US 2919174144,2919178239,CA 2919178240,2919186431,US 2919186432,2919190527,CA @@ -55427,30 +58110,17 @@ 2921496896,2921496903,IN 2921496904,2921496967,US 2921496968,2921496975,IN -2921496976,2921497375,US -2921497376,2921497407,IN -2921497408,2921497415,US +2921496976,2921497415,US 2921497416,2921497423,IN 2921497424,2921497471,US 2921497472,2921497599,IN 2921497600,2921503607,US 2921503608,2921503615,GB 2921503616,2921503695,US -2921503696,2921503703,GB -2921503704,2921508095,US -2921508096,2921508103,IN -2921508104,2921508319,US -2921508320,2921508351,IN -2921508352,2921508639,US -2921508640,2921508671,IN -2921508672,2921508679,US -2921508680,2921508719,IN +2921503696,2921503703,ID +2921503704,2921508719,US 2921508720,2921508727,SE -2921508728,2921511351,US -2921511352,2921511359,IN -2921511360,2921511743,US -2921511744,2921511759,BE -2921511760,2921512703,US +2921508728,2921512703,US 2921512704,2921512959,CA 2921512960,2921562111,US 2921562112,2921594879,CA @@ -55458,7 +58128,55 @@ 2925002752,2925527039,CA 2925527040,2926575615,US 2926575616,2927099903,CA -2927099904,2928218127,US +2927099904,2928173103,US +2928173104,2928173119,PH +2928173120,2928173151,US +2928173152,2928173159,RU +2928173160,2928173343,US +2928173344,2928173351,NL +2928173352,2928173519,US +2928173520,2928173527,GB +2928173528,2928173551,US +2928173552,2928173559,CA +2928173560,2928173679,US +2928173680,2928173695,JP +2928173696,2928173711,US +2928173712,2928173727,JP +2928173728,2928173775,US +2928173776,2928173783,IE +2928173784,2928173855,US +2928173856,2928173871,AU +2928173872,2928173903,US +2928173904,2928173919,NZ +2928173920,2928173959,US +2928173960,2928173967,CA +2928173968,2928174095,US +2928174096,2928174103,CA +2928174104,2928174575,US +2928174576,2928174583,AU +2928174584,2928174911,US +2928174912,2928174919,AU +2928174920,2928175055,US +2928175056,2928175063,MX +2928175064,2928175791,US +2928175792,2928175799,CA +2928175800,2928175839,US +2928175840,2928175847,SE +2928175848,2928175967,US +2928175968,2928175975,ZA +2928175976,2928176223,US +2928176224,2928176231,JP +2928176232,2928176383,US +2928176384,2928176391,ES +2928176392,2928176575,US +2928176576,2928176591,MQ +2928176592,2928176783,US +2928176784,2928176799,MX +2928176800,2928176895,US +2928176896,2928176903,CA +2928176904,2928177151,US +2928177152,2928181247,CA +2928181248,2928218127,US 2928218128,2928218143,CA 2928218144,2928218623,US 2928218624,2928219135,CA @@ -55746,7 +58464,9 @@ 2928279024,2928279551,CA 2928279552,2928312319,US 2928312320,2928316415,CA -2928316416,2928321311,US +2928316416,2928318719,US +2928318720,2928318975,DO +2928318976,2928321311,US 2928321312,2928321327,GB 2928321328,2928321343,CN 2928321344,2928323135,US @@ -56387,6 +59107,7 @@ 2948135936,2948136959,IN 2948136960,2948595711,CN 2948595712,2952790015,KR +2969567232,2971664383,BR 2986344448,2987393023,DE 2987393024,2987397119,IM 2987397120,2987401215,LV @@ -56400,7 +59121,9 @@ 2987433216,2987433235,KZ 2987433236,2987433239,RU 2987433240,2987433287,KZ -2987433288,2987433983,RU +2987433288,2987433295,RU +2987433296,2987433331,KZ +2987433332,2987433983,RU 2987433984,2987438079,FR 2987438080,2987442175,FI 2987442176,2987446271,IE @@ -56435,6 +59158,7 @@ 2987548672,2987552767,RU 2987552768,2987556863,GB 2987556864,2987560959,NL +2987560960,2987565055,DE 2987565056,2987569151,AT 2987569152,2987573247,FR 2987573248,2987577343,TR @@ -56450,8 +59174,8 @@ 2987585848,2987585855,SE 2987585856,2987585863,RU 2987585864,2987585871,GB -2987585872,2987585879,IT -2987585880,2987585887,FR +2987585872,2987585879,MX +2987585880,2987585887,BR 2987585888,2987585895,PL 2987585896,2987589631,DE 2987589632,2987593727,FR @@ -56472,8 +59196,8 @@ 2987655168,2987658367,DE 2987658368,2987658383,AT 2987658384,2987659263,DE -2987659264,2987659519,BA -2987659520,2987661311,SI +2987659264,2987660799,BA +2987660800,2987661311,SI 2987661312,2987663359,GB 2987663360,2987665407,IT 2987665408,2987667455,RU @@ -56610,9 +59334,9 @@ 2988441888,2988441895,FR 2988441896,2988441903,PL 2988441904,2988441911,IT -2988441912,2988441983,FR -2988441984,2988441999,NL -2988442000,2988442003,FR +2988441912,2988441991,FR +2988441992,2988441995,ES +2988441996,2988442003,FR 2988442004,2988442007,ES 2988442008,2988442047,FR 2988442048,2988442063,GB @@ -56635,7 +59359,8 @@ 2988442920,2988442923,LT 2988442924,2988442927,GB 2988442928,2988442975,FR -2988442976,2988443023,GB +2988442976,2988443007,GB +2988443008,2988443023,PT 2988443024,2988443027,FR 2988443028,2988443031,BE 2988443032,2988443035,GB @@ -56661,7 +59386,11 @@ 2988443564,2988443567,PL 2988443568,2988443583,FR 2988443584,2988443647,GB -2988443648,2988444167,FR +2988443648,2988443903,FR +2988443904,2988443919,BE +2988443920,2988443923,FR +2988443924,2988443927,PL +2988443928,2988444167,FR 2988444168,2988444171,CZ 2988444172,2988444199,FR 2988444200,2988444203,DE @@ -56691,7 +59420,9 @@ 2988446272,2988446275,IT 2988446276,2988446287,FR 2988446288,2988446303,GB -2988446304,2988446323,FR +2988446304,2988446307,FR +2988446308,2988446319,PL +2988446320,2988446323,FR 2988446324,2988446327,LT 2988446328,2988446335,NL 2988446336,2988446399,PL @@ -56716,10 +59447,11 @@ 2988448256,2988448511,DE 2988448512,2988448519,FR 2988448520,2988448543,PL -2988448544,2988448559,FR +2988448544,2988448551,FR +2988448552,2988448559,PL 2988448560,2988448563,DE -2988448564,2988448567,ES -2988448568,2988448607,FR +2988448564,2988448575,ES +2988448576,2988448607,FR 2988448608,2988448639,ES 2988448640,2988448671,GB 2988448672,2988448691,IT @@ -56748,7 +59480,11 @@ 2988449136,2988449151,FR 2988449152,2988449279,PL 2988449280,2988449535,GB -2988449536,2988449663,PL +2988449536,2988449579,FR +2988449580,2988449583,PL +2988449584,2988449631,FR +2988449632,2988449647,ES +2988449648,2988449663,GB 2988449664,2988449695,DE 2988449696,2988449727,IT 2988449728,2988449743,BE @@ -56759,9 +59495,12 @@ 2988453888,2988457983,GB 2988457984,2988457987,FR 2988457988,2988457991,PL -2988457992,2988458031,FR +2988457992,2988457995,CH +2988457996,2988457999,FR +2988458000,2988458015,GB +2988458016,2988458031,FR 2988458032,2988458047,IT -2988458048,2988458055,FR +2988458048,2988458055,PL 2988458056,2988458063,CH 2988458064,2988458067,ES 2988458068,2988458075,FR @@ -56831,7 +59570,20 @@ 2988459736,2988459743,PL 2988459744,2988459747,ES 2988459748,2988459751,PL -2988459752,2988460031,FR +2988459752,2988459759,FR +2988459760,2988459767,GB +2988459768,2988459771,NL +2988459772,2988459775,GB +2988459776,2988459839,FR +2988459840,2988459855,GB +2988459856,2988459863,FR +2988459864,2988459867,ES +2988459868,2988459871,GB +2988459872,2988459887,FR +2988459888,2988459895,PL +2988459896,2988459967,FR +2988459968,2988459999,ES +2988460000,2988460031,FR 2988460032,2988460063,DE 2988460064,2988460095,FR 2988460096,2988460103,ES @@ -56843,7 +59595,9 @@ 2988460128,2988460131,PL 2988460132,2988460135,CZ 2988460136,2988460143,FR -2988460144,2988460159,ES +2988460144,2988460147,GB +2988460148,2988460151,FR +2988460152,2988460159,ES 2988460160,2988460191,GB 2988460192,2988460195,FR 2988460196,2988460199,CZ @@ -56867,7 +59621,9 @@ 2988460552,2988460575,PL 2988460576,2988460591,PT 2988460592,2988460607,GB -2988460608,2988460679,FR +2988460608,2988460615,IT +2988460616,2988460623,PL +2988460624,2988460679,FR 2988460680,2988460683,GB 2988460684,2988460687,DE 2988460688,2988460719,FR @@ -56876,18 +59632,21 @@ 2988460760,2988460763,PT 2988460764,2988460767,FR 2988460768,2988460799,PL -2988460800,2988460863,CH +2988460800,2988460863,DE 2988460864,2988460927,FR 2988460928,2988460931,DE 2988460932,2988460943,PL 2988460944,2988460959,DE 2988460960,2988460991,GB -2988460992,2988461055,FR -2988461056,2988461119,IE +2988460992,2988461087,FR +2988461088,2988461103,PL +2988461104,2988461119,FR 2988461120,2988461151,NL 2988461152,2988461247,GB 2988461248,2988461255,FR -2988461256,2988461295,IT +2988461256,2988461263,GB +2988461264,2988461279,PL +2988461280,2988461295,IT 2988461296,2988461299,PL 2988461300,2988461307,FR 2988461308,2988461311,PL @@ -56947,8 +59706,8 @@ 2988461904,2988461911,ES 2988461912,2988461935,FR 2988461936,2988461951,GB -2988461952,2988462079,PL -2988462080,2988462095,CZ +2988461952,2988462087,PL +2988462088,2988462095,DE 2988462096,2988462127,FR 2988462128,2988462131,ES 2988462132,2988462143,FR @@ -56976,7 +59735,8 @@ 2988462604,2988462607,BE 2988462608,2988462735,FR 2988462736,2988462743,IT -2988462744,2988462767,FR +2988462744,2988462751,FR +2988462752,2988462767,PL 2988462768,2988462775,GB 2988462776,2988462779,PL 2988462780,2988462783,FR @@ -57005,7 +59765,8 @@ 2988463228,2988463231,CH 2988463232,2988463263,NL 2988463264,2988463279,PL -2988463280,2988463315,FR +2988463280,2988463283,GB +2988463284,2988463315,FR 2988463316,2988463319,DE 2988463320,2988463323,FR 2988463324,2988463331,DE @@ -57041,7 +59802,11 @@ 2988463952,2988463999,FR 2988464000,2988464007,IE 2988464008,2988464015,LT -2988464016,2988464055,FR +2988464016,2988464019,PT +2988464020,2988464023,IT +2988464024,2988464027,GB +2988464028,2988464031,PL +2988464032,2988464055,FR 2988464056,2988464059,ES 2988464060,2988464063,FR 2988464064,2988464095,PL @@ -57056,7 +59821,8 @@ 2988464512,2988464519,PT 2988464520,2988464527,FR 2988464528,2988464543,DE -2988464544,2988464575,IT +2988464544,2988464551,FR +2988464552,2988464575,ES 2988464576,2988464607,FR 2988464608,2988464611,DE 2988464612,2988464615,PL @@ -57088,14 +59854,19 @@ 2988465296,2988465299,IT 2988465300,2988465343,FR 2988465344,2988465363,DE -2988465364,2988465371,PL -2988465372,2988465375,FR +2988465364,2988465367,PL +2988465368,2988465375,FR 2988465376,2988465391,IT -2988465392,2988465407,FR +2988465392,2988465395,ES +2988465396,2988465399,GB +2988465400,2988465403,PT +2988465404,2988465407,DE 2988465408,2988465423,CH 2988465424,2988465439,PT 2988465440,2988465471,GB -2988465472,2988465503,FR +2988465472,2988465479,FR +2988465480,2988465483,NL +2988465484,2988465503,FR 2988465504,2988465507,DE 2988465508,2988465511,PL 2988465512,2988465515,PT @@ -57106,7 +59877,8 @@ 2988465532,2988465535,GB 2988465536,2988465539,FR 2988465540,2988465543,GB -2988465544,2988465551,FR +2988465544,2988465547,CZ +2988465548,2988465551,IT 2988465552,2988465559,ES 2988465560,2988465567,GB 2988465568,2988465571,ES @@ -57183,7 +59955,10 @@ 2988507640,2988507643,FR 2988507644,2988507647,IT 2988507648,2988507711,DE -2988507712,2988507775,IT +2988507712,2988507743,FR +2988507744,2988507759,IE +2988507760,2988507767,FR +2988507768,2988507775,PL 2988507776,2988507839,IE 2988507840,2988507855,FR 2988507856,2988507859,BE @@ -57207,7 +59982,10 @@ 2988507980,2988507983,DE 2988507984,2988507999,FR 2988508000,2988508031,NL -2988508032,2988508063,DE +2988508032,2988508039,PL +2988508040,2988508047,FR +2988508048,2988508055,GB +2988508056,2988508063,ES 2988508064,2988508067,FR 2988508068,2988508071,PL 2988508072,2988508079,FR @@ -57219,11 +59997,15 @@ 2988508144,2988508151,FR 2988508152,2988508155,ES 2988508156,2988508159,PL -2988508160,2988508219,FR +2988508160,2988508207,FR +2988508208,2988508211,DE +2988508212,2988508215,PL +2988508216,2988508219,FR 2988508220,2988508223,DE 2988508224,2988508287,FR 2988508288,2988508303,PL -2988508304,2988508315,FR +2988508304,2988508307,CZ +2988508308,2988508315,FR 2988508316,2988508319,ES 2988508320,2988508343,FR 2988508344,2988508367,ES @@ -57268,7 +60050,7 @@ 2988509024,2988509055,ES 2988509056,2988509119,IT 2988509120,2988509151,GB -2988509152,2988509183,ES +2988509152,2988509183,PL 2988509184,2988509279,FR 2988509280,2988509283,DE 2988509284,2988509287,IT @@ -57330,7 +60112,8 @@ 2988509920,2988509931,FR 2988509932,2988509951,PL 2988509952,2988509955,IT -2988509956,2988509963,DE +2988509956,2988509959,PL +2988509960,2988509963,FR 2988509964,2988509967,GB 2988509968,2988509983,ES 2988509984,2988509995,FR @@ -57339,7 +60122,10 @@ 2988510016,2988510023,ES 2988510024,2988510031,FR 2988510032,2988510079,PL -2988510080,2988510111,NL +2988510080,2988510095,ES +2988510096,2988510099,FR +2988510100,2988510103,GB +2988510104,2988510111,BE 2988510112,2988510143,CZ 2988510144,2988510175,NL 2988510176,2988510207,ES @@ -57353,7 +60139,7 @@ 2988510288,2988510303,PL 2988510304,2988510307,ES 2988510308,2988510311,FR -2988510312,2988510319,BE +2988510312,2988510319,GB 2988510320,2988510323,FR 2988510324,2988510327,GB 2988510328,2988510399,FR @@ -57380,7 +60166,8 @@ 2988511084,2988511087,PL 2988511088,2988511103,FR 2988511104,2988511167,PL -2988511168,2988511183,FR +2988511168,2988511175,IE +2988511176,2988511183,FR 2988511184,2988511191,GB 2988511192,2988511487,FR 2988511488,2988511551,PL @@ -57400,9 +60187,7 @@ 2988511700,2988511703,IT 2988511704,2988511711,PL 2988511712,2988511719,DE -2988511720,2988511723,FR -2988511724,2988511727,GB -2988511728,2988511735,FR +2988511720,2988511735,FR 2988511736,2988511739,DE 2988511740,2988511743,FR 2988511744,2988511747,PL @@ -57437,9 +60222,12 @@ 2988512152,2988512155,ES 2988512156,2988512159,FR 2988512160,2988512191,GB -2988512192,2988512199,FR +2988512192,2988512195,FR +2988512196,2988512199,DE 2988512200,2988512207,ES -2988512208,2988512239,FR +2988512208,2988512223,FR +2988512224,2988512227,BE +2988512228,2988512239,FR 2988512240,2988512247,LT 2988512248,2988512251,GB 2988512252,2988512255,ES @@ -57489,16 +60277,21 @@ 2988512832,2988512835,FR 2988512836,2988512839,ES 2988512840,2988512847,DE -2988512848,2988512879,FR +2988512848,2988512851,ES +2988512852,2988512855,DE +2988512856,2988512879,FR 2988512880,2988512895,DE 2988512896,2988512899,PL -2988512900,2988512907,GB +2988512900,2988512903,GB +2988512904,2988512907,ES 2988512908,2988512911,LT 2988512912,2988512943,FR 2988512944,2988512951,GB 2988512952,2988512955,FR 2988512956,2988512959,LT -2988512960,2988512975,BE +2988512960,2988512967,ES +2988512968,2988512971,GB +2988512972,2988512975,NL 2988512976,2988512995,FR 2988512996,2988512999,GB 2988513000,2988513003,FR @@ -57515,7 +60308,9 @@ 2988513208,2988513219,FR 2988513220,2988513223,CZ 2988513224,2988513227,NL -2988513228,2988513271,FR +2988513228,2988513235,FR +2988513236,2988513239,ES +2988513240,2988513271,FR 2988513272,2988513275,DE 2988513276,2988513279,CH 2988513280,2988513283,FR @@ -57523,14 +60318,14 @@ 2988513288,2988513307,FR 2988513308,2988513311,PL 2988513312,2988513327,PT -2988513328,2988513331,ES +2988513328,2988513331,PL 2988513332,2988513335,FR 2988513336,2988513343,GB -2988513344,2988513351,ES +2988513344,2988513351,FR 2988513352,2988513359,IT 2988513360,2988513375,GB -2988513376,2988513391,IT -2988513392,2988513407,GB +2988513376,2988513383,FR +2988513384,2988513407,GB 2988513408,2988513471,PL 2988513472,2988513503,FR 2988513504,2988513507,CH @@ -57570,8 +60365,7 @@ 2988514024,2988514027,PT 2988514028,2988514111,FR 2988514112,2988514115,DE -2988514116,2988514119,FR -2988514120,2988514127,PT +2988514116,2988514127,FR 2988514128,2988514131,IE 2988514132,2988514139,IT 2988514140,2988514143,PL @@ -57615,7 +60409,7 @@ 2988514736,2988514739,FR 2988514740,2988514743,ES 2988514744,2988514747,BE -2988514748,2988514751,IT +2988514748,2988514751,GB 2988514752,2988514815,FI 2988514816,2988514823,FR 2988514824,2988514827,PL @@ -57636,11 +60430,13 @@ 2988515328,2988517375,DE 2988517376,2988519423,FR 2988519424,2988521471,PL -2988521472,2988539935,FR +2988521472,2988535807,FR +2988535808,2988537855,ES +2988537856,2988539935,FR 2988539936,2988539967,GB 2988539968,2988539971,ES 2988539972,2988539975,IT -2988539976,2988539983,DE +2988539976,2988539983,FR 2988539984,2988540003,PL 2988540004,2988540007,CZ 2988540008,2988540023,FR @@ -57728,13 +60524,15 @@ 2988541244,2988541247,GB 2988541248,2988541279,FR 2988541280,2988541311,NL -2988541312,2988541327,DE +2988541312,2988541315,DE +2988541316,2988541319,CH +2988541320,2988541327,DE 2988541328,2988541335,PL 2988541336,2988541375,FR 2988541376,2988541391,BE 2988541392,2988541407,FR 2988541408,2988541423,BE -2988541424,2988541439,PL +2988541424,2988541439,DE 2988541440,2988541443,IT 2988541444,2988541463,FR 2988541464,2988541467,ES @@ -57745,7 +60543,7 @@ 2988541552,2988541583,FR 2988541584,2988541587,ES 2988541588,2988541591,FR -2988541592,2988541599,PL +2988541592,2988541599,GB 2988541600,2988541603,FR 2988541604,2988541607,NL 2988541608,2988541611,GB @@ -57781,9 +60579,9 @@ 2988541824,2988541855,LT 2988541856,2988541887,IE 2988541888,2988541895,DE -2988541896,2988541899,FR +2988541896,2988541899,PL 2988541900,2988541903,BE -2988541904,2988541907,DE +2988541904,2988541907,CZ 2988541908,2988541911,GB 2988541912,2988541935,PL 2988541936,2988541939,FR @@ -57799,8 +60597,9 @@ 2988542020,2988542023,FR 2988542024,2988542027,NL 2988542028,2988542031,PL -2988542032,2988542055,FR -2988542056,2988542063,BE +2988542032,2988542047,FR +2988542048,2988542055,PL +2988542056,2988542063,FR 2988542064,2988542067,GB 2988542068,2988542071,ES 2988542072,2988542367,FR @@ -57808,7 +60607,8 @@ 2988542400,2988542407,FR 2988542408,2988542415,PL 2988542416,2988542431,FR -2988542432,2988542443,ES +2988542432,2988542439,PL +2988542440,2988542443,ES 2988542444,2988542447,FR 2988542448,2988542455,PL 2988542456,2988542459,FR @@ -57818,14 +60618,14 @@ 2988542528,2988542535,DE 2988542536,2988542539,NL 2988542540,2988542543,LT -2988542544,2988542551,NL +2988542544,2988542551,DE 2988542552,2988542559,ES 2988542560,2988542591,FR 2988542592,2988542595,PT 2988542596,2988542599,FI 2988542600,2988542603,GB -2988542604,2988542615,FR -2988542616,2988542623,DE +2988542604,2988542611,FR +2988542612,2988542623,DE 2988542624,2988542655,FR 2988542656,2988542719,BE 2988542720,2988542783,CH @@ -57838,7 +60638,11 @@ 2988542964,2988542967,CH 2988542968,2988542971,NL 2988542972,2988542975,DE -2988542976,2988543039,FR +2988542976,2988543007,FR +2988543008,2988543011,PL +2988543012,2988543015,GB +2988543016,2988543023,CH +2988543024,2988543039,DE 2988543040,2988543043,CZ 2988543044,2988543047,ES 2988543048,2988543051,IE @@ -57915,13 +60719,418 @@ 2988544800,2988544831,FI 2988544832,2988544863,FR 2988544864,2988544895,PL -2988544896,2988572671,FR +2988544896,2988544927,FR +2988544928,2988544931,DE +2988544932,2988544935,FR +2988544936,2988544943,IT +2988544944,2988544951,PL +2988544952,2988544959,GB +2988544960,2988544979,ES +2988544980,2988544983,FR +2988544984,2988544991,IE +2988544992,2988544995,PL +2988544996,2988544999,FR +2988545000,2988545003,DE +2988545004,2988545007,ES +2988545008,2988545011,FR +2988545012,2988545019,DE +2988545020,2988545031,FR +2988545032,2988545039,PL +2988545040,2988545047,ES +2988545048,2988545051,FR +2988545052,2988545055,PL +2988545056,2988545063,FR +2988545064,2988545067,GB +2988545068,2988545071,ES +2988545072,2988545151,FR +2988545152,2988545167,GB +2988545168,2988545171,DE +2988545172,2988545175,FR +2988545176,2988545179,GB +2988545180,2988545183,PL +2988545184,2988545215,FR +2988545216,2988545247,ES +2988545248,2988545287,PL +2988545288,2988545291,FR +2988545292,2988545295,DE +2988545296,2988545311,FR +2988545312,2988545327,CH +2988545328,2988545335,IT +2988545336,2988545343,DE +2988545344,2988545407,FR +2988545408,2988545439,IE +2988545440,2988545471,FR +2988545472,2988545503,ES +2988545504,2988545507,FR +2988545508,2988545511,DE +2988545512,2988545515,IT +2988545516,2988545531,PL +2988545532,2988545535,FR +2988545536,2988545567,BE +2988545568,2988545663,FR +2988545664,2988545695,ES +2988545696,2988545727,DE +2988545728,2988545791,FR +2988545792,2988545807,DE +2988545808,2988545815,FR +2988545816,2988545823,NL +2988545824,2988545831,FR +2988545832,2988545835,GB +2988545836,2988545839,DE +2988545840,2988545855,FR +2988545856,2988545859,ES +2988545860,2988545867,FR +2988545868,2988545871,PL +2988545872,2988545919,FR +2988545920,2988545923,GB +2988545924,2988545927,PL +2988545928,2988545931,BE +2988545932,2988545943,FR +2988545944,2988545967,NL +2988545968,2988545983,GB +2988545984,2988545987,FR +2988545988,2988545991,PL +2988545992,2988545995,LT +2988545996,2988545999,FI +2988546000,2988546015,GB +2988546016,2988546031,FR +2988546032,2988546035,ES +2988546036,2988546039,BE +2988546040,2988546043,FR +2988546044,2988546047,ES +2988546048,2988546111,PL +2988546112,2988546115,ES +2988546116,2988546119,FR +2988546120,2988546123,IE +2988546124,2988546127,ES +2988546128,2988546143,GB +2988546144,2988546159,PL +2988546160,2988546175,ES +2988546176,2988546239,GB +2988546240,2988546271,LT +2988546272,2988546279,IT +2988546280,2988546283,GB +2988546284,2988546287,BE +2988546288,2988546291,GB +2988546292,2988546295,ES +2988546296,2988546303,PL +2988546304,2988546307,ES +2988546308,2988546311,NL +2988546312,2988546315,IT +2988546316,2988546319,FR +2988546320,2988546327,CH +2988546328,2988546335,ES +2988546336,2988546351,PT +2988546352,2988546367,ES +2988546368,2988546431,FR +2988546432,2988546463,DE +2988546464,2988546527,FR +2988546528,2988546535,BE +2988546536,2988546539,IE +2988546540,2988546547,ES +2988546548,2988546559,FR +2988546560,2988546567,NL +2988546568,2988546575,FR +2988546576,2988546579,ES +2988546580,2988546583,GB +2988546584,2988546591,FR +2988546592,2988546599,DE +2988546600,2988546603,PT +2988546604,2988546615,GB +2988546616,2988546619,FI +2988546620,2988546623,FR +2988546624,2988546687,FI +2988546688,2988546695,PL +2988546696,2988546699,FR +2988546700,2988546703,IT +2988546704,2988546727,FR +2988546728,2988546735,ES +2988546736,2988546751,FR +2988546752,2988546783,ES +2988546784,2988546831,FR +2988546832,2988546835,DE +2988546836,2988546839,ES +2988546840,2988546847,IE +2988546848,2988546879,FR +2988546880,2988546947,ES +2988546948,2988546951,DE +2988546952,2988546959,FR +2988546960,2988546967,DE +2988546968,2988546971,FR +2988546972,2988546975,BE +2988546976,2988546991,FI +2988546992,2988546995,DE +2988546996,2988546999,ES +2988547000,2988547003,IT +2988547004,2988547007,ES +2988547008,2988547011,GB +2988547012,2988547015,FR +2988547016,2988547019,NL +2988547020,2988547023,ES +2988547024,2988547039,FR +2988547040,2988547047,ES +2988547048,2988547055,FR +2988547056,2988547059,IT +2988547060,2988547063,FR +2988547064,2988547067,GB +2988547068,2988547071,PL +2988547072,2988547087,GB +2988547088,2988547095,NL +2988547096,2988547099,PL +2988547100,2988547103,IE +2988547104,2988547111,DE +2988547112,2988547115,GB +2988547116,2988547123,FR +2988547124,2988547127,IT +2988547128,2988547135,FR +2988547136,2988547167,IT +2988547168,2988547199,BE +2988547200,2988547207,IE +2988547208,2988547211,FR +2988547212,2988547215,DE +2988547216,2988547219,IT +2988547220,2988547223,FR +2988547224,2988547227,ES +2988547228,2988547231,PT +2988547232,2988547239,FR +2988547240,2988547247,PL +2988547248,2988547255,NL +2988547256,2988547271,FR +2988547272,2988547279,ES +2988547280,2988547295,FR +2988547296,2988547303,DE +2988547304,2988547311,FR +2988547312,2988547327,PL +2988547328,2988547423,FR +2988547424,2988547431,GB +2988547432,2988547435,ES +2988547436,2988547443,PL +2988547444,2988547447,DE +2988547448,2988547455,FR +2988547456,2988547471,DE +2988547472,2988547475,NL +2988547476,2988547479,GB +2988547480,2988547487,FR +2988547488,2988547519,ES +2988547520,2988547523,PL +2988547524,2988547527,CZ +2988547528,2988547531,IT +2988547532,2988547535,ES +2988547536,2988547539,FR +2988547540,2988547543,DE +2988547544,2988547547,IT +2988547548,2988547551,PL +2988547552,2988547567,FR +2988547568,2988547583,DE +2988547584,2988547599,ES +2988547600,2988547615,FR +2988547616,2988547647,PL +2988547648,2988547655,FR +2988547656,2988547663,PL +2988547664,2988547679,IE +2988547680,2988547711,CH +2988547712,2988547727,PL +2988547728,2988547751,FR +2988547752,2988547775,DE +2988547776,2988547807,ES +2988547808,2988547871,FR +2988547872,2988547903,GB +2988547904,2988547935,FR +2988547936,2988547967,LT +2988547968,2988548047,FR +2988548048,2988548055,ES +2988548056,2988548059,PL +2988548060,2988548063,DE +2988548064,2988548095,ES +2988548096,2988556287,FR +2988556288,2988556295,PL +2988556296,2988556303,FR +2988556304,2988556311,PL +2988556312,2988556319,FR +2988556320,2988556351,GB +2988556352,2988556359,DE +2988556360,2988556383,FR +2988556384,2988556415,DE +2988556416,2988556447,FR +2988556448,2988556451,NL +2988556452,2988556479,FR +2988556480,2988556495,IT +2988556496,2988556511,FR +2988556512,2988556543,DE +2988556544,2988556799,FR +2988556800,2988556839,DE +2988556840,2988556847,FR +2988556848,2988556855,ES +2988556856,2988556863,GB +2988556864,2988556879,FR +2988556880,2988556883,ES +2988556884,2988556887,DE +2988556888,2988556895,FR +2988556896,2988556911,PL +2988556912,2988556919,NL +2988556920,2988556959,PL +2988556960,2988556963,ES +2988556964,2988556967,FR +2988556968,2988556975,BE +2988556976,2988556979,FI +2988556980,2988557023,FR +2988557024,2988557039,IE +2988557040,2988557047,FR +2988557048,2988557055,PL +2988557056,2988557071,FR +2988557072,2988557075,PL +2988557076,2988557079,FR +2988557080,2988557087,FI +2988557088,2988557119,DE +2988557120,2988557151,NL +2988557152,2988557215,FR +2988557216,2988557247,BE +2988557248,2988557251,FR +2988557252,2988557255,ES +2988557256,2988557279,GB +2988557280,2988557295,ES +2988557296,2988557299,BE +2988557300,2988557303,PL +2988557304,2988557311,CZ +2988557312,2988557327,DE +2988557328,2988557343,ES +2988557344,2988557379,FR +2988557380,2988557383,ES +2988557384,2988557387,GB +2988557388,2988557391,ES +2988557392,2988557395,FR +2988557396,2988557399,PL +2988557400,2988557407,DE +2988557408,2988557427,ES +2988557428,2988557431,DE +2988557432,2988557435,PL +2988557436,2988557439,FR +2988557440,2988557471,GB +2988557472,2988557487,PL +2988557488,2988557495,DE +2988557496,2988557539,PL +2988557540,2988557543,IE +2988557544,2988557599,FR +2988557600,2988557631,GB +2988557632,2988557639,FR +2988557640,2988557643,IE +2988557644,2988557647,GB +2988557648,2988557651,NL +2988557652,2988557663,FR +2988557664,2988557695,PL +2988557696,2988557727,FR +2988557728,2988557759,PL +2988557760,2988557763,FR +2988557764,2988557767,GB +2988557768,2988557771,PL +2988557772,2988557823,FR +2988557824,2988557951,DE +2988557952,2988557983,LT +2988557984,2988557999,GB +2988558000,2988558015,IE +2988558016,2988558047,FR +2988558048,2988558063,PL +2988558064,2988558071,IT +2988558072,2988558075,DE +2988558076,2988558079,PL +2988558080,2988558127,FR +2988558128,2988558135,PL +2988558136,2988558139,GB +2988558140,2988558143,DE +2988558144,2988558207,PL +2988558208,2988558271,ES +2988558272,2988558335,FI +2988558336,2988558399,IE +2988558400,2988558463,LT +2988558464,2988558527,NL +2988558528,2988558591,PL +2988558592,2988558655,GB +2988558656,2988558767,FR +2988558768,2988558783,CH +2988558784,2988558831,FR +2988558832,2988558847,IT +2988558848,2988558883,FR +2988558884,2988558887,BE +2988558888,2988558891,GB +2988558892,2988558895,NL +2988558896,2988558903,FR +2988558904,2988558907,NL +2988558908,2988558935,GB +2988558936,2988558939,PL +2988558940,2988558943,GB +2988558944,2988558975,FR +2988558976,2988559007,GB +2988559008,2988559011,BE +2988559012,2988559015,PL +2988559016,2988559071,FR +2988559072,2988559103,ES +2988559104,2988559135,PL +2988559136,2988559139,FR +2988559140,2988559151,PL +2988559152,2988559231,FR +2988559232,2988559247,DE +2988559248,2988559255,FR +2988559256,2988559259,DE +2988559260,2988559263,GB +2988559264,2988559295,LT +2988559296,2988559359,PL +2988559360,2988559631,FR +2988559632,2988559663,IE +2988559664,2988559679,ES +2988559680,2988559691,FR +2988559692,2988559695,PL +2988559696,2988559699,DE +2988559700,2988559703,PL +2988559704,2988559707,DE +2988559708,2988559711,PL +2988559712,2988559719,FR +2988559720,2988559727,DE +2988559728,2988559731,FR +2988559732,2988559735,PL +2988559736,2988559743,GB +2988559744,2988559871,FR +2988559872,2988560383,IT +2988560384,2988560575,FR +2988560576,2988560591,ES +2988560592,2988560595,DE +2988560596,2988560599,IT +2988560600,2988560603,PL +2988560604,2988560607,PT +2988560608,2988560623,FR +2988560624,2988560627,BE +2988560628,2988560639,FR +2988560640,2988560703,GB +2988560704,2988560711,DE +2988560712,2988560719,PL +2988560720,2988560735,FR +2988560736,2988560751,DE +2988560752,2988560759,GB +2988560760,2988560767,FI +2988560768,2988560783,FR +2988560784,2988560799,NL +2988560800,2988560815,DE +2988560816,2988560831,FR +2988560832,2988560863,GB +2988560864,2988560895,DE +2988560896,2988560911,PL +2988560912,2988560919,FR +2988560920,2988560923,DE +2988560924,2988560951,FR +2988560952,2988560959,PL +2988560960,2988561023,IE +2988561024,2988561031,ES +2988561032,2988561039,FR +2988561040,2988561043,ES +2988561044,2988561055,FR +2988561056,2988561071,FI +2988561072,2988572671,FR 2988572672,2988703743,RU 2988703744,2988834815,PL 2988834816,2988965887,CH 2988965888,2989096959,SK 2989096960,2989228031,PL 2989228032,2989490175,RU +2989490176,2989555711,HU 2989555712,2989621247,RU 2989621248,2989752319,BE 2989752320,2989817855,SY @@ -57961,139 +61170,139 @@ 2991185952,2991185967,NL 2991185968,2991185983,DE 2991185984,2991185999,DK -2991186000,2991186015,FI +2991186000,2991186015,ES 2991186016,2991186175,SE 2991186176,2991186207,GB 2991186208,2991186223,NL 2991186224,2991186239,DE 2991186240,2991186255,DK -2991186256,2991186271,FI +2991186256,2991186271,ES 2991186272,2991186431,SE 2991186432,2991186463,GB 2991186464,2991186479,NL 2991186480,2991186495,DE 2991186496,2991186511,DK -2991186512,2991186527,FI +2991186512,2991186527,ES 2991186528,2991186687,SE 2991186688,2991186719,GB 2991186720,2991186735,NL 2991186736,2991186751,DE 2991186752,2991186767,DK -2991186768,2991186783,FI +2991186768,2991186783,ES 2991186784,2991186943,SE 2991186944,2991186975,GB 2991186976,2991186991,NL 2991186992,2991187007,DE 2991187008,2991187023,DK -2991187024,2991187039,FI +2991187024,2991187039,ES 2991187040,2991187199,SE 2991187200,2991187231,GB 2991187232,2991187247,NL 2991187248,2991187263,DE 2991187264,2991187279,DK -2991187280,2991187295,FI +2991187280,2991187295,ES 2991187296,2991187455,SE 2991187456,2991187487,GB 2991187488,2991187503,NL 2991187504,2991187519,DE 2991187520,2991187535,DK -2991187536,2991187551,FI +2991187536,2991187551,ES 2991187552,2991187711,SE 2991187712,2991187743,GB 2991187744,2991187759,NL 2991187760,2991187775,DE 2991187776,2991187791,DK -2991187792,2991187807,FI +2991187792,2991187807,ES 2991187808,2991187967,SE 2991187968,2991187999,GB 2991188000,2991188015,NL 2991188016,2991188031,DE 2991188032,2991188047,DK -2991188048,2991188063,FI +2991188048,2991188063,ES 2991188064,2991188223,SE 2991188224,2991188255,GB 2991188256,2991188271,NL 2991188272,2991188287,DE 2991188288,2991188303,DK -2991188304,2991188319,FI +2991188304,2991188319,ES 2991188320,2991188479,SE 2991188480,2991188511,GB 2991188512,2991188527,NL 2991188528,2991188543,DE 2991188544,2991188559,DK -2991188560,2991188575,FI +2991188560,2991188575,ES 2991188576,2991188735,SE 2991188736,2991188767,GB 2991188768,2991188783,NL 2991188784,2991188799,DE 2991188800,2991188815,DK -2991188816,2991188831,FI +2991188816,2991188831,ES 2991188832,2991188991,SE 2991188992,2991189023,GB 2991189024,2991189039,NL 2991189040,2991189055,DE 2991189056,2991189071,DK -2991189072,2991189087,FI +2991189072,2991189087,ES 2991189088,2991189247,SE 2991189248,2991189279,GB 2991189280,2991189295,NL 2991189296,2991189311,DE 2991189312,2991189327,DK -2991189328,2991189343,FI +2991189328,2991189343,ES 2991189344,2991189503,SE 2991189504,2991189535,GB 2991189536,2991189551,NL 2991189552,2991189567,DE 2991189568,2991189583,DK -2991189584,2991189599,FI +2991189584,2991189599,ES 2991189600,2991189759,SE 2991189760,2991189791,GB 2991189792,2991189807,NL 2991189808,2991189823,DE 2991189824,2991189839,DK -2991189840,2991189855,FI +2991189840,2991189855,ES 2991189856,2991190015,SE 2991190016,2991190047,GB 2991190048,2991190063,NL 2991190064,2991190079,DE 2991190080,2991190095,DK -2991190096,2991190111,FI +2991190096,2991190111,ES 2991190112,2991190271,SE 2991190272,2991190303,GB 2991190304,2991190319,NL 2991190320,2991190335,DE 2991190336,2991190351,DK -2991190352,2991190367,FI +2991190352,2991190367,ES 2991190368,2991190527,SE 2991190528,2991190559,GB 2991190560,2991190575,NL 2991190576,2991190591,DE 2991190592,2991190607,DK -2991190608,2991190623,FI +2991190608,2991190623,ES 2991190624,2991190783,SE 2991190784,2991190815,GB 2991190816,2991190831,NL 2991190832,2991190847,DE 2991190848,2991190863,DK -2991190864,2991190879,FI +2991190864,2991190879,ES 2991190880,2991191039,SE 2991191040,2991191071,GB 2991191072,2991191087,NL 2991191088,2991191103,DE 2991191104,2991191119,DK -2991191120,2991191135,FI +2991191120,2991191135,ES 2991191136,2991191295,SE 2991191296,2991191327,GB 2991191328,2991191343,NL 2991191344,2991191359,DE 2991191360,2991191375,DK -2991191376,2991191391,FI +2991191376,2991191391,ES 2991191392,2991191551,SE 2991191552,2991191583,GB 2991191584,2991191599,NL 2991191600,2991191615,DE 2991191616,2991191631,DK -2991191632,2991191647,FI +2991191632,2991191647,ES 2991191648,2991191807,SE 2991191808,2991192063,FI 2991192064,2991192319,DK @@ -58127,15 +61336,7 @@ 2991980808,2991980815,NA 2991980816,2991981063,UA 2991981064,2991981071,DE -2991981072,2991981311,UA -2991981312,2991981315,RU -2991981316,2991981375,UA -2991981376,2991981383,NA -2991981384,2991981415,UA -2991981416,2991981423,NA -2991981424,2991981439,UA -2991981440,2991981447,NA -2991981448,2991981463,UA +2991981072,2991981463,UA 2991981464,2991981471,NA 2991981472,2991981495,UA 2991981496,2991981503,NA @@ -58147,13 +61348,15 @@ 2991981840,2991981847,RU 2991981848,2991981911,UA 2991981912,2991981919,RU -2991981920,2991981935,UA -2991981936,2991981943,RU -2991981944,2991982535,UA +2991981920,2991982535,UA 2991982536,2991982543,GL 2991982544,2991982592,UA -2991982593,2991982846,JP -2991982847,2992111615,UA +2991982593,2991982599,JP +2991982600,2991982607,UA +2991982608,2991982846,JP +2991982847,2991983359,UA +2991983360,2991983615,JP +2991983616,2992111615,UA 2992111616,2992373759,KZ 2992373760,2992635903,UA 2992635904,2993684479,GB @@ -58179,9 +61382,7 @@ 2996174848,2996305919,UA 2996305920,2996436991,QA 2996436992,2996469759,BY -2996469760,2996479487,RU -2996479488,2996479495,US -2996479496,2996535295,RU +2996469760,2996535295,RU 2996535296,2996568063,DK 2996568064,2996600831,ES 2996600832,2996633599,RO @@ -58189,6 +61390,7 @@ 2996649984,2996666367,RO 2996666368,2996682751,RU 2996682752,2996699135,DK +2996731904,2996748287,UA 2996764672,2996768767,NL 2996768768,2996772863,RU 2996772864,2996776959,UA @@ -58199,14 +61401,15 @@ 2996797440,2996801535,PL 2996801536,2996805631,RO 2996805632,2996809727,PL +2996809728,2996813823,UA +2996813824,2996817919,PL +2996817920,2996826111,UA +2996826112,2996830207,RU 2996830208,2996862975,HR 2996862976,2996895743,AM 2996895744,2996928511,KW 2996928512,2996994047,RU -2996994048,2996994303,DE -2996994304,2996994815,BY -2996994816,2996994847,DE -2996994848,2996994879,SC +2996994048,2996994879,DE 2996994880,2996994943,UA 2996994944,2996995071,US 2996995072,2996995327,BZ @@ -58214,8 +61417,7 @@ 2996995648,2996995711,BZ 2996995712,2996995775,BY 2996995776,2996995839,RU -2996995840,2996996095,UA -2996996096,2996996127,DE +2996995840,2996996127,DE 2996996128,2996996159,CA 2996996160,2996996287,DE 2996996288,2996996351,RU @@ -58227,8 +61429,7 @@ 2996996768,2996996831,RU 2996996832,2996996863,DE 2996996864,2996997119,CN -2996997120,2996997631,DE -2996997632,2996998143,BY +2996997120,2996998143,DE 2996998144,2996998271,UA 2996998272,2996998463,DE 2996998464,2996998527,CA @@ -58237,13 +61438,14 @@ 2996998720,2996998911,RU 2996998912,2996999199,DE 2996999200,2996999231,AU -2996999232,2996999359,IN +2996999232,2996999359,DE 2996999360,2996999423,IL 2996999424,2996999551,IN 2996999552,2996999679,DE 2996999680,2996999935,GB -2996999936,2997000063,DE -2997000064,2997000447,CN +2996999936,2996999967,DE +2996999968,2996999999,AU +2997000000,2997000447,DE 2997000448,2997000703,RU 2997000704,2997000767,DE 2997000768,2997000831,SC @@ -58252,8 +61454,7 @@ 2997000992,2997001119,RO 2997001120,2997001471,DE 2997001472,2997001727,BZ -2997001728,2997001983,UA -2997001984,2997003071,DE +2997001728,2997003071,DE 2997003072,2997003135,RU 2997003136,2997003199,DE 2997003200,2997003263,RU @@ -58281,7 +61482,8 @@ 2997006592,2997006655,DE 2997006656,2997006719,TR 2997006720,2997006847,RU -2997006848,2997008255,DE +2997006848,2997008191,DE +2997008192,2997008255,TR 2997008256,2997008383,LT 2997008384,2997008447,DE 2997008448,2997008511,RU @@ -58296,18 +61498,23 @@ 2997019648,2997019679,DE 2997019680,2997019711,AU 2997019712,2997019903,US -2997019904,2997020159,IN -2997020160,2997020415,DE +2997019904,2997020415,DE 2997020416,2997020671,CA -2997020672,2997020927,IR -2997020928,2997021183,CN +2997020672,2997021183,DE 2997021184,2997021695,GB 2997021696,2997021951,NL 2997021952,2997022015,DE 2997022016,2997022143,GB -2997022144,2997022239,DE +2997022144,2997022207,IN +2997022208,2997022239,DE 2997022240,2997022303,NL -2997022304,2997026815,DE +2997022304,2997022367,SG +2997022368,2997022783,DE +2997022784,2997022847,IN +2997022848,2997023231,BZ +2997023232,2997024255,DE +2997024256,2997024511,TR +2997024512,2997026815,DE 2997026816,2997059583,RU 2997059584,2997092351,BY 2997092352,2997125119,NO @@ -58321,7 +61528,9 @@ 2997387264,2997420031,BY 2997420032,2997452799,RU 2997452800,2997485567,BG -2997485568,2997518335,FR +2997485568,2997486847,FR +2997486848,2997486911,BH +2997486912,2997518335,FR 2997518336,2997528063,RU 2997528064,2997528319,UA 2997528320,2997583871,RU @@ -58347,8 +61556,8 @@ 2999985712,2999985727,BE 2999985728,2999985743,CZ 2999985744,2999985759,NL -2999985760,2999985919,BE -2999985920,2999992319,NL +2999985760,2999986687,BE +2999986688,2999992319,NL 2999992320,3000000511,RU 3000000512,3000008703,DE 3000008704,3000016895,RU @@ -58406,11 +61615,30 @@ 3000317952,3000319999,PL 3000320000,3000322047,FR 3000322048,3000326143,RU -3000326144,3000328191,PL +3000326144,3000330239,PL +3000330240,3000332287,UA +3000332288,3000334335,RU +3000334336,3000336383,PL +3000336384,3000338431,AM +3000338432,3000340479,PL +3000340480,3000342527,RU +3000342528,3000344575,CZ +3000344576,3000346623,PL +3000346624,3000348671,UA +3000348672,3000350719,RO +3000350720,3000352767,UA +3000352768,3000358911,RU +3000358912,3000360959,PL +3000360960,3000363007,RU +3000363008,3000365055,FI +3000365056,3000369151,RU 3000369152,3000377343,PL 3000377344,3000385535,RU 3000385536,3000393727,PS 3000393728,3000401919,NL +3000401920,3000410111,PL +3000410112,3000426495,UA +3000426496,3000434687,RU 3000434688,3000451071,IR 3000451072,3000467455,RU 3000467456,3000471551,GB @@ -58437,6 +61665,7 @@ 3000543232,3000545279,UA 3000545280,3000547327,RU 3000547328,3000549375,UA +3000549376,3000551423,SE 3000551424,3000553471,RS 3000553472,3000555519,KG 3000555520,3000557567,RU @@ -58486,7 +61715,6 @@ 3000713216,3000717311,A2 3000717312,3000721407,UA 3000721408,3000729599,PL -3000729600,3000733695,NL 3000733696,3000737791,RU 3000737792,3000741887,UA 3000741888,3000745983,RU @@ -58511,12 +61739,17 @@ 3001843712,3001845759,RU 3001845760,3001851903,GB 3001851904,3001855999,IT -3001856000,3001858559,NL -3001858560,3001859071,RO +3001856000,3001859071,NL 3001859072,3001860095,MD 3001860096,3001864191,EE 3001864192,3001868287,RU -3001868288,3001872383,FR +3001868288,3001869312,FR +3001869313,3001869599,SA +3001869600,3001869600,FR +3001869601,3001869696,IR +3001869697,3001869823,YE +3001869824,3001869887,IR +3001869888,3001872383,FR 3001872384,3001876479,RU 3001876480,3001880575,IT 3001880576,3001884671,RU @@ -58525,7 +61758,9 @@ 3001885056,3001885087,US 3001885088,3001885439,NL 3001885440,3001886463,BE -3001886464,3001888767,NL +3001886464,3001886511,NL +3001886512,3001886527,US +3001886528,3001888767,NL 3001888768,3001892863,BH 3001892864,3001896959,AZ 3001896960,3001901055,CH @@ -58552,22 +61787,88 @@ 3001975608,3001975615,RU 3001975616,3001975623,US 3001975624,3001975631,RU -3001975632,3001976575,GB -3001976576,3001976607,TW +3001975632,3001975655,GB +3001975656,3001975663,RU +3001975664,3001975671,US +3001975672,3001975679,CN +3001975680,3001975687,TW +3001975688,3001975695,US +3001975696,3001975703,GB +3001975704,3001975711,DE +3001975712,3001975719,MY +3001975720,3001975727,US +3001975728,3001975735,GB +3001975736,3001975743,MY +3001975744,3001975759,GB +3001975760,3001975799,US +3001975800,3001975815,GB +3001975816,3001975823,US +3001975824,3001975839,GB +3001975840,3001975847,CN +3001975848,3001975855,US +3001975856,3001975863,GB +3001975864,3001975871,AU +3001975872,3001975879,US +3001975880,3001975895,GB +3001975896,3001975903,RU +3001975904,3001976415,GB +3001976416,3001976447,IL +3001976448,3001976575,GB +3001976576,3001976607,US 3001976608,3001976623,GB 3001976624,3001976639,CN 3001976640,3001976655,RU -3001976656,3001976679,GB +3001976656,3001976671,GB +3001976672,3001976679,IN 3001976680,3001976687,US -3001976688,3001976927,GB +3001976688,3001976831,GB +3001976832,3001976895,CN +3001976896,3001976927,IL 3001976928,3001976959,RU -3001976960,3001977215,GB +3001976960,3001977087,GB +3001977088,3001977103,IN +3001977104,3001977119,RU +3001977120,3001977135,GB +3001977136,3001977151,AE +3001977152,3001977167,GB +3001977168,3001977183,LK +3001977184,3001977199,GB +3001977200,3001977215,DE 3001977216,3001977247,RU 3001977248,3001977311,GB 3001977312,3001977343,CN -3001977344,3001977455,GB +3001977344,3001977375,IL +3001977376,3001977407,CA +3001977408,3001977439,IL +3001977440,3001977447,GB +3001977448,3001977455,IT 3001977456,3001977463,US -3001977464,3001982975,GB +3001977464,3001977487,GB +3001977488,3001977503,LK +3001977504,3001977519,GB +3001977520,3001977535,CN +3001977536,3001977575,GB +3001977576,3001977583,CA +3001977584,3001977599,GB +3001977600,3001977855,DK +3001977856,3001978047,GB +3001978048,3001978111,US +3001978112,3001978303,GB +3001978304,3001978367,IL +3001978368,3001978495,US +3001978496,3001978527,RU +3001978528,3001978559,UA +3001978560,3001978591,US +3001978592,3001978607,AU +3001978608,3001978623,GB +3001978624,3001978687,CA +3001978688,3001978751,EE +3001978752,3001978783,RU +3001978784,3001978815,US +3001978816,3001978831,LK +3001978832,3001978847,GB +3001978848,3001978879,UA +3001978880,3001982975,GB 3001982976,3001987071,CH 3001987072,3001991167,JO 3001991168,3001995263,IR @@ -58578,7 +61879,15 @@ 3002015744,3002019839,IT 3002019840,3002020095,NL 3002020096,3002020159,SG -3002020160,3002023935,NL +3002020160,3002020223,NL +3002020224,3002020287,IL +3002020288,3002020303,US +3002020304,3002020319,BZ +3002020320,3002021695,NL +3002021696,3002021759,SG +3002021760,3002022527,NL +3002022528,3002022655,BZ +3002022656,3002023935,NL 3002023936,3002028031,DE 3002028032,3002036223,GB 3002036224,3002040319,BG @@ -58588,7 +61897,9 @@ 3002052608,3002056703,IT 3002056704,3002060799,FI 3002060800,3002064895,ES -3002064896,3002068991,BG +3002064896,3002065407,BG +3002065408,3002065663,RS +3002065664,3002068991,BG 3002068992,3002073087,ES 3002073088,3002597375,TR 3002597376,3002599423,RU @@ -58607,14 +61918,18 @@ 3002619952,3002619967,GB 3002619968,3002619983,IT 3002619984,3002619991,GB -3002619992,3002620023,IT -3002620024,3002620031,GB +3002619992,3002620015,IT +3002620016,3002620031,GB 3002620032,3002620039,DE 3002620040,3002620047,IT -3002620048,3002620071,GB -3002620072,3002621951,IT +3002620048,3002620095,GB +3002620096,3002620103,IT +3002620104,3002620111,GB +3002620112,3002621951,IT 3002621952,3002623999,NO -3002624000,3002628095,GB +3002624000,3002626551,GB +3002626552,3002626559,US +3002626560,3002628095,GB 3002628096,3002630143,NO 3002630144,3002632191,GB 3002632192,3002634239,EE @@ -58735,11 +62050,16 @@ 3003056128,3003058175,DE 3003058176,3003058431,MT 3003058432,3003058687,FI -3003058688,3003060223,EE +3003058688,3003058943,EE +3003058944,3003059135,PH +3003059136,3003060223,EE 3003060224,3003062271,DE 3003062272,3003064319,NL 3003064320,3003066367,RO -3003066368,3003068415,PL +3003066368,3003066887,PL +3003066888,3003066895,MX +3003066896,3003066911,UA +3003066912,3003068415,PL 3003068416,3003070463,NL 3003070464,3003074559,GB 3003074560,3003076607,IT @@ -58787,7 +62107,6 @@ 3025989632,3025993727,KR 3025993728,3026059263,VN 3026059264,3026067455,PH -3026067456,3026068479,BD 3026068480,3026069503,PH 3026069504,3026071551,JP 3026071552,3026073599,AP @@ -58826,12 +62145,10 @@ 3029614592,3029622783,AU 3029630976,3029635071,VN 3029635072,3029637119,JP -3029637120,3029639167,BD 3029639168,3029643263,JP 3029643264,3029644287,AU 3029645312,3029651455,JP -3029651456,3029654527,BD -3029654528,3029655551,IN +3029651456,3029653503,BD 3029655552,3029663743,CN 3029663744,3029671935,BD 3029671936,3029680127,IN @@ -58839,7 +62156,10 @@ 3029696512,3029704703,CN 3029704704,3029712895,JP 3029712896,3029713919,AU -3029714944,3029716991,JP +3029714944,3029715199,JP +3029715200,3029715455,AU +3029715456,3029715967,AP +3029715968,3029716991,JP 3029716992,3029721087,PK 3029721088,3029725183,AP 3029725184,3029727231,IN @@ -58900,7 +62220,6 @@ 3033268224,3033530367,TW 3033530368,3033661439,CN 3033661440,3033694207,KR -3033694208,3033710591,BD 3033710592,3033712639,KR 3033712640,3033714687,SG 3033714688,3033715711,NZ @@ -58933,7 +62252,7 @@ 3034251264,3034316799,HK 3034316800,3034447871,JP 3034447872,3034456063,AU -3034464256,3034465279,NZ +3034464256,3034466303,NZ 3034466304,3034472447,JP 3034472448,3034480639,IN 3034480640,3034482687,SG @@ -58964,8 +62283,8 @@ 3035316224,3035324415,CN 3035324416,3035326463,JP 3035326464,3035327487,AU -3035328512,3035332607,BD 3035332608,3035333631,AU +3035333632,3035334655,HK 3035335680,3035337727,JP 3035337728,3035338751,ID 3035338752,3035339007,SG @@ -59193,7 +62512,15 @@ 3091726336,3093168127,US 3093168128,3093200895,CA 3093233664,3093237759,PR -3093299200,3093954759,US +3093299200,3093939167,US +3093939168,3093939175,CN +3093939176,3093941111,US +3093941112,3093941119,MY +3093941120,3093941199,US +3093941200,3093941207,CN +3093941208,3093942271,US +3093942272,3093942527,CA +3093942528,3093954759,US 3093954760,3093954767,AR 3093954768,3093954975,US 3093954976,3093954983,AU @@ -59219,7 +62546,9 @@ 3093955664,3093955679,CA 3093955680,3093956479,US 3093956480,3093956495,IE -3093956496,3093956895,US +3093956496,3093956567,US +3093956568,3093956575,MX +3093956576,3093956895,US 3093956896,3093956943,CA 3093956944,3093957103,US 3093957104,3093957119,CA @@ -59249,13 +62578,35 @@ 3093958746,3093958747,FR 3093958748,3093959559,US 3093959560,3093959567,CA -3093959568,3093960191,US +3093959568,3093959751,US +3093959752,3093959759,GB +3093959760,3093959911,US +3093959912,3093959919,CA +3093959920,3093960063,US +3093960064,3093960095,CA +3093960096,3093960191,US 3093960192,3093960207,CA 3093960208,3093960351,US 3093960352,3093960383,CA -3093960384,3093962259,US +3093960384,3093960447,US +3093960448,3093960463,CA +3093960464,3093962259,US 3093962260,3093962263,CA -3093962264,3093986367,US +3093962264,3093962287,US +3093962288,3093962291,MX +3093962292,3093962375,US +3093962376,3093962379,CA +3093962380,3093962475,US +3093962476,3093962479,CA +3093962480,3093962807,US +3093962808,3093962815,AU +3093962816,3093963359,US +3093963360,3093963367,CA +3093963368,3093963487,US +3093963488,3093963495,IE +3093963496,3093963599,US +3093963600,3093963607,CA +3093963608,3093986367,US 3093986368,3093986431,DE 3093986432,3093986463,US 3093986464,3093986495,GB @@ -59267,7 +62618,12 @@ 3097493504,3097755647,CA 3097755648,3098148863,US 3098148864,3098165247,JM -3098542080,3103784959,US +3098214400,3098263551,US +3098263552,3098271743,CA +3098271744,3098275839,US +3098279936,3098476543,US +3098476544,3098492927,CA +3098492928,3103784959,US 3120562176,3120594943,CO 3120594944,3120599039,AR 3120599040,3120601087,EC @@ -59296,7 +62652,7 @@ 3121545216,3121610751,CR 3121610752,3121741823,PY 3121741824,3121872895,AR -3121872896,3121938431,CL +3121872896,3122003967,CL 3122003968,3122135039,AR 3122135040,3122331647,VE 3122331648,3122348031,BO @@ -59336,6 +62692,11 @@ 3132358656,3132424191,CO 3132489728,3132555263,AR 3132620800,3132751871,VE +3132882944,3132915711,VE +3132948480,3133014015,AR +3133014016,3133046783,HT +3133046784,3133054975,AR +3133079552,3133145087,AR 3133145088,3145727999,BR 3145728000,3154116607,MX 3154116608,3154182143,EU @@ -59497,12 +62858,9 @@ 3158895424,3158895487,RU 3158895488,3158895551,MK 3158895552,3158895615,AE -3158895616,3158895871,IN -3158895872,3158896255,DE +3158895616,3158896255,DE 3158896256,3158896383,IN -3158896384,3158897151,DE -3158897152,3158897407,BY -3158897408,3158897503,DE +3158896384,3158897503,DE 3158897504,3158897567,RU 3158897568,3158897631,DE 3158897632,3158897663,BZ @@ -59510,8 +62868,7 @@ 3158897728,3158897791,RU 3158897792,3158897855,DE 3158897856,3158897919,UA -3158897920,3158898175,BY -3158898176,3158898207,DE +3158897920,3158898207,DE 3158898208,3158898271,CZ 3158898272,3158898335,RU 3158898336,3158898431,DE @@ -59555,10 +62912,10 @@ 3160186880,3160188927,EE 3160188928,3160190975,SE 3160190976,3160193023,RU -3160193024,3160193279,IT +3160193024,3160193279,A2 3160193280,3160193535,DE -3160193536,3160193807,A2 -3160193808,3160193871,LY +3160193536,3160193791,A2 +3160193792,3160193871,LY 3160193872,3160194047,A2 3160194048,3160194175,LY 3160194176,3160194543,A2 @@ -59658,14 +63015,13 @@ 3160377344,3160379391,NL 3160379392,3160381439,TR 3160381440,3160383487,UA -3160383488,3160385535,GB 3160385536,3160387583,NL 3160387584,3160389631,RS 3160389632,3160391679,RU 3160391680,3160395775,GB 3160395776,3160397823,EE 3160397824,3160399871,ES -3160399872,3160403967,SE +3160399872,3160401919,SE 3160403968,3160406015,NO 3160408064,3161456639,DE 3161456640,3161473023,PL @@ -59715,10 +63071,14 @@ 3162087424,3162095615,SK 3162095616,3162103807,GE 3162103808,3162104319,FR -3162104320,3162111999,NL +3162104320,3162108415,NL +3162108416,3162108671,FR +3162108672,3162108927,NL +3162108928,3162109951,FR +3162109952,3162111999,NL 3162112000,3162120191,PL -3162120192,3162128895,GB -3162128896,3162129407,NL +3162120192,3162128383,GB +3162128384,3162129407,NL 3162129408,3162129919,DE 3162129920,3162136575,NL 3162144768,3162152959,SE @@ -59735,7 +63095,6 @@ 3162234880,3162243071,RU 3162243072,3162251263,TR 3162251264,3162259455,RU -3162259456,3162267647,CZ 3162267648,3162275839,RU 3162275840,3162284031,NO 3162284032,3162292223,PL @@ -59743,9 +63102,10 @@ 3162300416,3162308607,RU 3162308608,3162316799,HR 3162316800,3162324991,PL -3162324992,3162327039,GB -3162327040,3162327296,CH -3162327297,3162332671,GB +3162324992,3162327039,IR +3162327040,3162329087,CH +3162329088,3162331135,IR +3162331136,3162332671,GB 3162332672,3162332927,NL 3162332928,3162333183,DE 3162333184,3162341375,IT @@ -59777,9 +63137,7 @@ 3162681344,3162682367,UA 3162682368,3162685439,RU 3162685440,3162697727,UA -3162697728,3162700287,RU -3162700288,3162700799,LV -3162700800,3162701823,RU +3162697728,3162701823,RU 3162701824,3162734591,MD 3162734592,3162767359,RU 3162767360,3162800127,SA @@ -59803,27 +63161,24 @@ 3163162144,3163162175,DE 3163162176,3163162207,US 3163162208,3163162239,TR -3163162240,3163162271,CH +3163162240,3163162271,DE 3163162272,3163162303,NL 3163162304,3163162431,DE 3163162432,3163162463,CY 3163162464,3163163871,DE 3163163872,3163163903,RU -3163163904,3163163935,DE +3163163904,3163163935,GR 3163163936,3163163967,VG 3163163968,3163164543,DE 3163164544,3163164575,RU -3163164576,3163165695,DE -3163165696,3163165727,TR -3163165728,3163165759,DE +3163164576,3163165759,DE 3163165760,3163165791,PL -3163165792,3163166175,DE +3163165792,3163165823,RU +3163165824,3163166175,DE 3163166176,3163166207,US -3163166208,3163166335,DE -3163166336,3163166399,NL -3163166400,3163166431,DE -3163166432,3163166463,NL -3163166464,3163166495,DE +3163166208,3163166367,DE +3163166368,3163166399,NL +3163166400,3163166495,DE 3163166496,3163166527,RO 3163166528,3163166559,DE 3163166560,3163166591,HU @@ -59833,15 +63188,12 @@ 3163167840,3163167967,DE 3163167968,3163167999,TR 3163168000,3163168031,DE -3163168032,3163168063,RU -3163168064,3163168095,DE +3163168032,3163168095,RU 3163168096,3163168127,TR -3163168128,3163168159,IL +3163168128,3163168159,SA 3163168160,3163168319,DE 3163168320,3163168351,DK -3163168352,3163168415,DE -3163168416,3163168447,CA -3163168448,3163168575,DE +3163168352,3163168575,DE 3163168576,3163168607,NL 3163168608,3163168671,DE 3163168672,3163168703,US @@ -59857,21 +63209,23 @@ 3163170208,3163170239,RU 3163170240,3163170303,DE 3163170304,3163170335,IT -3163170336,3163170367,DE -3163170368,3163170399,IR -3163170400,3163170495,DE +3163170336,3163170495,DE 3163170496,3163170527,BR 3163170528,3163170591,DE 3163170592,3163170623,BR -3163170624,3163172127,DE +3163170624,3163171871,DE +3163171872,3163171903,RO +3163171904,3163172127,DE 3163172128,3163172159,NL 3163172160,3163172191,RU -3163172192,3163172223,DE -3163172224,3163172255,NL +3163172192,3163172255,DE 3163172256,3163172287,PL -3163172288,3163172351,NL +3163172288,3163172319,DE +3163172320,3163172351,NL 3163172352,3163172383,GB -3163172384,3163172607,DE +3163172384,3163172447,DE +3163172448,3163172479,TR +3163172480,3163172607,DE 3163172608,3163172639,DK 3163172640,3163172735,DE 3163172736,3163172767,GR @@ -59883,15 +63237,17 @@ 3163174368,3163174591,DE 3163174592,3163174623,SE 3163174624,3163174655,GB -3163174656,3163174687,DE -3163174688,3163174719,US +3163174656,3163174687,NL +3163174688,3163174719,DE 3163174720,3163174751,NL 3163174752,3163174783,US 3163174784,3163176127,DE 3163176128,3163176159,NL 3163176160,3163176255,DE 3163176256,3163176287,UG -3163176288,3163176479,DE +3163176288,3163176319,DE +3163176320,3163176351,US +3163176352,3163176479,DE 3163176480,3163176543,GB 3163176544,3163176575,DE 3163176576,3163176607,GR @@ -59935,7 +63291,7 @@ 3164946496,3164946499,IT 3164946500,3164946503,GB 3164946504,3164946507,BE -3164946508,3164946511,FR +3164946508,3164946511,CZ 3164946512,3164946527,ES 3164946528,3164946559,GB 3164946560,3164946783,FR @@ -59947,7 +63303,20 @@ 3164947064,3164947067,NL 3164947068,3164947071,PL 3164947072,3164947199,DE -3164947200,3164947743,FR +3164947200,3164947455,FR +3164947456,3164947519,PL +3164947520,3164947551,ES +3164947552,3164947583,DE +3164947584,3164947599,FR +3164947600,3164947615,GB +3164947616,3164947627,FR +3164947628,3164947635,ES +3164947636,3164947639,DE +3164947640,3164947643,IT +3164947644,3164947647,FR +3164947648,3164947651,BE +3164947652,3164947655,PL +3164947656,3164947743,FR 3164947744,3164947747,ES 3164947748,3164947751,BE 3164947752,3164947839,FR @@ -59958,7 +63327,8 @@ 3164949088,3164949095,FR 3164949096,3164949103,IT 3164949104,3164949119,GB -3164949120,3164949131,DE +3164949120,3164949123,PT +3164949124,3164949131,DE 3164949132,3164949151,FR 3164949152,3164949155,NL 3164949156,3164949159,FR @@ -59967,8 +63337,7 @@ 3164949184,3164949215,DE 3164949216,3164949219,PL 3164949220,3164949223,FR -3164949224,3164949227,PL -3164949228,3164949231,GB +3164949224,3164949231,PL 3164949232,3164949247,BE 3164949248,3164949279,FR 3164949280,3164949295,ES @@ -59988,9 +63357,7 @@ 3164950272,3164950399,DE 3164950400,3164950407,ES 3164950408,3164950411,FR -3164950412,3164950415,CZ -3164950416,3164950431,PL -3164950432,3164950435,FR +3164950412,3164950435,PL 3164950436,3164950439,ES 3164950440,3164950447,FR 3164950448,3164950451,PL @@ -60002,7 +63369,8 @@ 3164950496,3164950511,ES 3164950512,3164950515,GB 3164950516,3164950519,ES -3164950520,3164950527,GB +3164950520,3164950523,FR +3164950524,3164950527,ES 3164950528,3164950543,BE 3164950544,3164950591,NL 3164950592,3164950623,FR @@ -60085,16 +63453,15 @@ 3164953392,3164953395,IT 3164953396,3164953399,NL 3164953400,3164953403,BE -3164953404,3164953407,CH +3164953404,3164953407,PL 3164953408,3164953423,BE 3164953424,3164953439,FR -3164953440,3164953443,CZ +3164953440,3164953443,PL 3164953444,3164953447,DE 3164953448,3164953451,ES 3164953452,3164953455,FR -3164953456,3164953459,IE -3164953460,3164953463,PT -3164953464,3164953467,PL +3164953456,3164953463,PL +3164953464,3164953467,FR 3164953468,3164953471,GB 3164953472,3164953503,PL 3164953504,3164953511,FR @@ -60133,8 +63500,7 @@ 3164956544,3164958847,FR 3164958848,3164958911,IT 3164958912,3164958927,CH -3164958928,3164958943,ES -3164958944,3164958955,FR +3164958928,3164958955,FR 3164958956,3164958959,GB 3164958960,3164959039,FR 3164959040,3164959135,DE @@ -60158,12 +63524,34 @@ 3164960000,3164960255,DE 3164960256,3164960511,FR 3164960512,3164960575,PL -3164960576,3164960767,IT +3164960576,3164960591,DE +3164960592,3164960599,ES +3164960600,3164960603,IT +3164960604,3164960607,CZ +3164960608,3164960639,BE +3164960640,3164960643,LT +3164960644,3164960647,FR +3164960648,3164960651,CH +3164960652,3164960659,IT +3164960660,3164960671,PL +3164960672,3164960675,ES +3164960676,3164960679,GB +3164960680,3164960699,PL +3164960700,3164960703,ES +3164960704,3164960719,GB +3164960720,3164960723,CH +3164960724,3164960727,DE +3164960728,3164960735,GB +3164960736,3164960767,ES 3164960768,3164960831,PL 3164960832,3164960895,FR 3164960896,3164960959,PT 3164960960,3164961023,CH -3164961024,3164961279,FR +3164961024,3164961151,FR +3164961152,3164961167,DE +3164961168,3164961175,PL +3164961176,3164961247,FR +3164961248,3164961279,NL 3164961280,3164961311,DE 3164961312,3164961319,FR 3164961320,3164961327,PL @@ -60191,7 +63579,12 @@ 3164961696,3164961727,GB 3164961728,3164961743,ES 3164961744,3164961759,PL -3164961760,3164961855,FR +3164961760,3164961763,ES +3164961764,3164961767,IT +3164961768,3164961775,BE +3164961776,3164961783,FR +3164961784,3164961791,ES +3164961792,3164961855,FR 3164961856,3164961871,PL 3164961872,3164961887,IE 3164961888,3164961903,ES @@ -60208,8 +63601,11 @@ 3164962080,3164962095,ES 3164962096,3164962111,BE 3164962112,3164962143,GB -3164962144,3164962175,FR -3164962176,3164962239,NL +3164962144,3164962203,FR +3164962204,3164962207,PT +3164962208,3164962211,GB +3164962212,3164962215,PL +3164962216,3164962239,FR 3164962240,3164962247,PL 3164962248,3164962251,FR 3164962252,3164962255,DE @@ -60234,11 +63630,10 @@ 3164962540,3164962543,CZ 3164962544,3164962623,FR 3164962624,3164962627,BE -3164962628,3164962631,CH +3164962628,3164962631,PL 3164962632,3164962655,FR 3164962656,3164962687,ES -3164962688,3164962703,GB -3164962704,3164962715,FR +3164962688,3164962715,FR 3164962716,3164962719,NL 3164962720,3164962723,IT 3164962724,3164962727,ES @@ -60246,7 +63641,7 @@ 3164962752,3164964863,ES 3164964864,3164966911,FI 3164966912,3164967039,FR -3164967040,3164967071,PL +3164967040,3164967071,GB 3164967072,3164967087,FR 3164967088,3164967095,IT 3164967096,3164967103,PL @@ -60256,7 +63651,7 @@ 3164967160,3164967167,FR 3164967168,3164967295,ES 3164967296,3164967303,NL -3164967304,3164967307,IT +3164967304,3164967307,PT 3164967308,3164967311,DE 3164967312,3164967343,IT 3164967344,3164967351,ES @@ -60290,10 +63685,10 @@ 3164969136,3164969143,ES 3164969144,3164969147,PT 3164969148,3164969183,GB -3164969184,3164969199,DE +3164969184,3164969199,FR 3164969200,3164969203,LT 3164969204,3164969207,ES -3164969208,3164969211,IT +3164969208,3164969211,PL 3164969212,3164969471,FR 3164969472,3164969727,PL 3164969728,3164969983,GB @@ -60304,7 +63699,13 @@ 3164970212,3164970215,GB 3164970216,3164970219,PL 3164970220,3164970223,FR -3164970224,3164970303,GB +3164970224,3164970239,GB +3164970240,3164970271,IE +3164970272,3164970287,DE +3164970288,3164970291,PL +3164970292,3164970295,DE +3164970296,3164970299,ES +3164970300,3164970303,DE 3164970304,3164970335,ES 3164970336,3164970339,NL 3164970340,3164970343,BE @@ -60345,7 +63746,9 @@ 3164970832,3164970835,IT 3164970836,3164970839,PL 3164970840,3164970847,GB -3164970848,3164970911,FR +3164970848,3164970855,FR +3164970856,3164970863,PL +3164970864,3164970911,FR 3164970912,3164970915,ES 3164970916,3164970919,FR 3164970920,3164970923,GB @@ -60355,8 +63758,7 @@ 3164971008,3164971011,ES 3164971012,3164971015,FR 3164971016,3164971023,PL -3164971024,3164971055,FR -3164971056,3164971071,NL +3164971024,3164971071,FR 3164971072,3164971135,DE 3164971136,3164971263,GB 3164971264,3164971455,DE @@ -60389,8 +63791,7 @@ 3164972352,3164972415,NL 3164972416,3164972479,BE 3164972480,3164972499,FR -3164972500,3164972503,IT -3164972504,3164972511,DE +3164972500,3164972511,DE 3164972512,3164972527,GB 3164972528,3164972799,FR 3164972800,3164973311,ES @@ -60404,12 +63805,10 @@ 3164973884,3164973887,DE 3164973888,3164973919,ES 3164973920,3164973935,FR -3164973936,3164973939,IT +3164973936,3164973939,IE 3164973940,3164973943,FR 3164973944,3164973951,PL -3164973952,3164974623,FR -3164974624,3164974639,DE -3164974640,3164974651,FR +3164973952,3164974651,FR 3164974652,3164974655,DE 3164974656,3164974663,FR 3164974664,3164974667,GB @@ -60428,16 +63827,15 @@ 3164975104,3164975167,CH 3164975168,3164975231,GB 3164975232,3164975299,IT -3164975300,3164975307,ES -3164975308,3164975311,GB +3164975300,3164975303,ES +3164975304,3164975311,IT 3164975312,3164975343,ES 3164975344,3164975351,GB 3164975352,3164975355,NL 3164975356,3164975359,FR 3164975360,3164975615,ES 3164975616,3164976127,GB -3164976128,3164976639,IT -3164976640,3164976767,FR +3164976128,3164976767,FR 3164976768,3164976783,DE 3164976784,3164976799,ES 3164976800,3164976815,DE @@ -60525,7 +63923,9 @@ 3166306304,3166437375,RU 3166437376,3166568447,BE 3166699520,3166961663,DE -3167223808,3167748095,NL +3167223808,3167594831,NL +3167594832,3167594839,A2 +3167594840,3167748095,NL 3167748096,3167940095,RO 3167940096,3167940351,CY 3167940352,3168092159,RO @@ -60622,6 +64022,10 @@ 3187703808,3187711999,UY 3187712000,3187720191,AR 3187720192,3187728383,GT +3187728384,3187730431,CR +3187730432,3187732479,AR +3187732480,3187734527,CO +3187734528,3187736575,BO 3187736576,3187752959,AR 3187752960,3187761151,CO 3187769344,3187802111,CO @@ -60710,8 +64114,7 @@ 3188678656,3188686847,AR 3188686848,3188690943,EC 3188695040,3188703231,VE -3188703232,3188711423,AR -3188719616,3188981759,AR +3188703232,3188981759,AR 3188981760,3189178367,CL 3189178368,3189211135,PY 3189243904,3189637119,CO @@ -60825,6 +64228,10 @@ 3194519552,3194535935,PY 3194552320,3194585087,AR 3194585088,3194589183,HN +3194593280,3194595327,AR +3194595328,3194596351,PA +3194596352,3194597375,HT +3194597376,3194601471,AR 3194601472,3194602495,AN 3194602496,3194605567,AR 3194609664,3194613759,AR @@ -60861,12 +64268,14 @@ 3194863616,3194871807,HN 3194880000,3194896383,DO 3194896384,3194904575,CO -3194912768,3194920959,CL +3194912768,3194929151,CL 3194929152,3194937343,EC 3194945536,3194953727,GT 3194961920,3194966015,EC 3194970112,3194974207,PA 3194974208,3194976255,AR +3194976256,3194977279,VE +3194977280,3194978303,AR 3194978304,3194994687,PA 3194994688,3195002879,AR 3195011072,3195023359,AR @@ -60889,10 +64298,12 @@ 3195207680,3195211775,GT 3195215872,3195224063,AR 3195224064,3195232255,PA +3195240448,3195256831,HT +3195256832,3195265023,AR 3195273216,3195535359,PE 3195535360,3195539455,SV 3195543552,3195547647,PE -3195551744,3195555839,EC +3195551744,3195559935,EC 3195559936,3195564031,AR 3195568128,3195572223,CO 3195572224,3195576319,AR @@ -60961,14 +64372,14 @@ 3198910464,3198926847,CL 3198943232,3199500799,AR 3199500800,3199501311,US -3199501312,3199533055,AR +3199501312,3199516671,AR 3199533056,3199549439,BO 3199565824,3199582207,NI 3199598592,3199631359,CO 3199664128,3199729663,AR 3199729664,3199762431,NI 3199795200,3199827967,AN -3199827968,3199844351,AR +3199827968,3199860735,AR 3199860736,3199926271,BO 3199926272,3199991807,PE 3199991808,3200516095,AR @@ -60981,8 +64392,14 @@ 3201302528,3201433599,CL 3201433600,3201499135,AR 3201499136,3201515519,CL -3201531904,3201533951,AR +3201531904,3201540095,AR 3201540096,3201544191,CL +3201548288,3201556479,AR +3201556480,3201560575,BO +3201560576,3201561599,PY +3201561600,3201562623,AR +3201562624,3201563647,CL +3201563648,3201564671,PA 3201564672,3201630207,NI 3201630208,3201695743,TT 3201695744,3201761279,EC @@ -64670,7 +68087,7 @@ 3238630400,3238630655,GR 3238630656,3238632959,GB 3238632960,3238633215,UA -3238633216,3238657791,DK +3238633216,3238653951,DK 3238657792,3238658047,AT 3238658048,3238675455,SE 3238675456,3238675711,DK @@ -64949,6 +68366,7 @@ 3239488256,3239488511,CH 3239488512,3239488767,KW 3239488768,3239489023,RO +3239489024,3239489279,DE 3239489280,3239489535,PL 3239489536,3239501823,DE 3239501824,3239505919,BE @@ -65098,6 +68516,7 @@ 3239691776,3239692031,EU 3239692032,3239692287,AT 3239692288,3239697407,DE +3239697408,3239697663,HR 3239697664,3239697919,RU 3239697920,3239698431,PL 3239698432,3239706367,DE @@ -65154,12 +68573,12 @@ 3239761408,3239761663,RU 3239761664,3239761919,PL 3239761920,3239762175,BG +3239762176,3239762431,RU 3239762432,3239762687,DK 3239762688,3239762943,RO 3239763200,3239763455,SE 3239763456,3239763967,GB 3239763968,3239772159,DE -3239772160,3239772415,UA 3239772416,3239772671,GB 3239772672,3239773183,DK 3239773184,3239773439,FR @@ -65466,7 +68885,7 @@ 3240199168,3240199679,HU 3240199680,3240200191,NL 3240200192,3240200703,RO -3240200704,3240201215,GB +3240200704,3240201215,SE 3240201216,3240201727,RO 3240201728,3240202239,CH 3240202240,3240202751,RU @@ -65524,7 +68943,7 @@ 3240232960,3240235007,RU 3240235008,3240236031,FR 3240236032,3240237055,UA -3240237056,3240238079,DE +3240237056,3240239103,DE 3240239104,3240240127,FR 3240240128,3240241151,US 3240241152,3240242175,FI @@ -65545,6 +68964,7 @@ 3240258560,3240259583,RO 3240259584,3240260607,PL 3240260608,3240262655,DE +3240262656,3240263679,RU 3240263680,3240264191,UA 3240264192,3240264703,FR 3240264704,3240265215,TR @@ -65588,11 +69008,10 @@ 3240281600,3240281727,JO 3240281728,3240281855,PL 3240281856,3240281983,NL -3240281984,3240282111,IT 3240282112,3240282239,DE 3240282240,3240282367,UA 3240282368,3240282495,RO -3240282624,3240282879,SE +3240282496,3240282879,SE 3240282880,3240283007,UA 3240283008,3240283135,PL 3240284160,3240285183,RU @@ -65736,6 +69155,7 @@ 3240706048,3240707071,BG 3240707072,3240707839,NL 3240707840,3240709119,FR +3240709120,3240710143,RU 3240710144,3240710399,UA 3240710400,3240710655,LT 3240710656,3240710911,DE @@ -65898,11 +69318,13 @@ 3240859648,3240861183,CH 3240861184,3240861695,AT 3240861696,3240866815,IT +3240866816,3240867071,RU 3240867072,3240867327,PL 3240867328,3240867583,RU 3240867584,3240867839,CH 3240867840,3240873983,IT 3240873984,3240874495,RU +3240874496,3240875007,UA 3240875008,3240875519,AT 3240875520,3240876031,FR 3240876032,3240876543,DK @@ -66137,6 +69559,7 @@ 3241865728,3241865983,CH 3241865984,3241866239,RO 3241866240,3241866751,DE +3241866752,3241867007,UA 3241867008,3241867263,FR 3241867264,3241867519,UA 3241867520,3241867775,PL @@ -66381,12 +69804,13 @@ 3244823296,3244823551,FR 3244823552,3244823807,GE 3244823808,3244824063,RO -3244824064,3244824319,MT +3244824064,3244824319,UA 3244824320,3244824575,SI 3244824576,3244824831,RU 3244824832,3244825087,GB 3244825088,3244825343,DE -3244825344,3244826111,RU +3244825344,3244825599,UA +3244825600,3244826111,RU 3244826112,3244826367,RO 3244826368,3244826623,CH 3244826624,3244826879,DE @@ -66459,7 +69883,6 @@ 3244844800,3244845055,GB 3244845056,3244845311,NL 3244845312,3244845567,NO -3244845568,3244845823,AD 3244845824,3244846335,GB 3244846336,3244846591,TR 3244846592,3244846847,CZ @@ -66470,7 +69893,7 @@ 3244847872,3244848127,IL 3244848128,3244848383,CH 3244848384,3244848639,IL -3244848640,3244848895,HU +3244848640,3244848895,DE 3244848896,3244849151,IL 3244849152,3244849407,AT 3244849408,3244849663,RO @@ -66566,6 +69989,7 @@ 3244875008,3244875263,PL 3244875264,3244875519,LI 3244875520,3244875775,IT +3244875776,3244876799,BZ 3244876800,3244877055,GB 3244877056,3244877311,JO 3244877312,3244877567,RU @@ -66594,7 +70018,7 @@ 3244883200,3244883455,UA 3244883456,3244883711,CZ 3244883712,3244883967,NL -3244883968,3244884223,MD +3244883968,3244884223,UA 3244884224,3244884479,FR 3244884480,3244884735,IR 3244884736,3244884991,NL @@ -66758,7 +70182,6 @@ 3244927744,3244927999,US 3244928000,3244928255,GB 3244928256,3244928511,US -3244928512,3244928767,UA 3244928768,3244929023,RU 3244929024,3244929535,RO 3244929536,3244929791,PL @@ -66813,6 +70236,7 @@ 3244942848,3244943103,DE 3244943104,3244943359,GB 3244943360,3244943615,FR +3244943616,3244943871,NL 3244943872,3244944127,TR 3244944128,3244944639,RU 3244944640,3244944895,GE @@ -66895,7 +70319,7 @@ 3245024256,3245025279,BG 3245025280,3245026303,UA 3245026304,3245027327,GB -3245027328,3245028351,RU +3245027328,3245029375,RU 3245029376,3245030399,FR 3245030400,3245032447,RU 3245032448,3245033471,BG @@ -67079,7 +70503,6 @@ 3245168896,3245169151,RU 3245169152,3245169407,IT 3245169408,3245169919,PL -3245169920,3245170175,UA 3245170176,3245170431,GB 3245170432,3245170687,CH 3245170688,3245171711,DE @@ -67326,7 +70749,7 @@ 3245319680,3245319935,PL 3245319936,3245320191,DE 3245320192,3245320447,GB -3245320704,3245320959,DE +3245320448,3245320959,DE 3245320960,3245321215,IE 3245321216,3245321471,NL 3245321472,3245321727,UA @@ -67395,7 +70818,9 @@ 3245904200,3245904207,GB 3245904208,3245906367,IE 3245906368,3245906431,GB -3245906432,3245910831,IE +3245906432,3245909567,IE +3245909568,3245909631,US +3245909632,3245910831,IE 3245910832,3245910847,GB 3245910848,3245921279,IE 3245921280,3245921535,BE @@ -67534,6 +70959,7 @@ 3247081472,3247083519,PL 3247083520,3247084543,UA 3247084544,3247085567,RU +3247085568,3247086591,CZ 3247086592,3247087615,NL 3247087616,3247088639,IT 3247088640,3247089663,DE @@ -67833,7 +71259,6 @@ 3247347968,3247348223,HU 3247348224,3247348991,FI 3247348992,3247349247,DE -3247349248,3247349759,FI 3247349760,3247353855,SE 3247353856,3247362047,FI 3247362048,3247362303,RO @@ -67939,6 +71364,7 @@ 3247918080,3247919103,PL 3247919104,3247920127,BG 3247920128,3247921151,FR +3247921152,3247922175,UA 3247922176,3247923199,SE 3247923200,3247925247,PL 3247925248,3247926271,UA @@ -67976,7 +71402,7 @@ 3248488704,3248491519,NO 3248491520,3248492031,RU 3248492032,3248496895,NO -3248496896,3248497151,IL +3248496896,3248497151,US 3248497152,3248498431,NO 3248498432,3248498687,DE 3248498688,3248513279,NO @@ -68183,7 +71609,7 @@ 3249136128,3249137151,RU 3249137152,3249137663,FR 3249137664,3249138175,PL -3249138176,3249138687,JM +3249138176,3249138687,UA 3249139200,3249139711,RU 3249139712,3249140223,UA 3249140224,3249140735,IT @@ -68232,7 +71658,8 @@ 3249698560,3249698815,HU 3249698816,3249699839,GB 3249699840,3249700863,UA -3249700864,3249701887,SE +3249700864,3249701631,SE +3249701632,3249701887,RU 3249701888,3249702143,PL 3249702144,3249702399,FI 3249702400,3249702655,FR @@ -68303,7 +71730,9 @@ 3249731584,3249732607,UA 3249732608,3249733631,IT 3249733632,3249799167,CZ -3249799168,3249932031,SE +3249799168,3249931007,SE +3249931008,3249931263,GB +3249931264,3249932031,SE 3249932032,3249934335,GB 3249934336,3250061311,SE 3250061312,3250061635,FI @@ -68428,7 +71857,6 @@ 3250416128,3250417663,DE 3250417664,3250418175,IT 3250418176,3250418687,DE -3250418688,3250419199,PL 3250419200,3250419711,NO 3250419712,3250420223,RU 3250420224,3250420735,IR @@ -68447,7 +71875,7 @@ 3250425856,3250426111,LT 3250426112,3250426367,NO 3250426368,3250426623,AT -3250426624,3250426879,BE +3250426624,3250426879,FR 3250426880,3250427135,JO 3250427136,3250427391,NL 3250427392,3250429951,DE @@ -68491,7 +71919,9 @@ 3250601984,3250610175,GB 3250610176,3250618367,TR 3250618368,3250626559,RU -3250626560,3250634751,PL +3250626560,3250633983,PL +3250633984,3250634239,US +3250634240,3250634751,PL 3250634752,3250642943,GB 3250642944,3250651135,CH 3250651136,3250659327,IT @@ -68809,6 +72239,7 @@ 3251209216,3251210239,GB 3251210240,3251211263,PL 3251211264,3251212287,UA +3251212288,3251212415,IE 3251212416,3251212671,FI 3251212672,3251212799,SE 3251212800,3251212927,FR @@ -68921,6 +72352,7 @@ 3251265536,3251267839,NL 3251267840,3251268351,GB 3251268352,3251268607,NL +3251268608,3251268863,BG 3251268864,3251269119,NL 3251269120,3251269375,DK 3251269376,3251269631,FR @@ -68987,6 +72419,7 @@ 3251355648,3251356159,GB 3251356160,3251356671,AT 3251356672,3251357183,EE +3251357184,3251357695,BG 3251357696,3251358207,ES 3251358208,3251358719,RU 3251358720,3251359231,RO @@ -69129,14 +72562,15 @@ 3252387328,3252387583,PL 3252387584,3252387839,RU 3252387840,3252404223,LT -3252404224,3252406527,NO -3252406528,3252407295,LT +3252404224,3252406783,NO +3252406784,3252407295,LT 3252407296,3252407583,NO 3252407584,3252407599,NG 3252407600,3252407615,BJ 3252407616,3252407711,NO 3252407712,3252407727,NG -3252407728,3252407759,NO +3252407728,3252407751,NO +3252407752,3252407759,AO 3252407760,3252407767,NE 3252407768,3252407775,CD 3252407776,3252407791,GH @@ -69145,10 +72579,9 @@ 3252408000,3252408159,NO 3252408160,3252408191,GQ 3252408192,3252408319,NO -3252408320,3252408335,LT -3252408336,3252408343,GN -3252408344,3252408351,LT -3252408352,3252408367,GN +3252408320,3252408327,MW +3252408328,3252408335,LT +3252408336,3252408367,GN 3252408368,3252408375,NG 3252408376,3252408383,LT 3252408384,3252408391,BI @@ -69182,8 +72615,12 @@ 3252409200,3252409207,TZ 3252409208,3252409215,LT 3252409216,3252409223,BW -3252409224,3252409263,LT -3252409264,3252409343,SO +3252409224,3252409231,LT +3252409232,3252409247,UG +3252409248,3252409263,LT +3252409264,3252409271,SO +3252409272,3252409279,LT +3252409280,3252409343,SO 3252409344,3252409375,TD 3252409376,3252409407,LT 3252409408,3252409471,BI @@ -69195,15 +72632,20 @@ 3252409600,3252409615,MA 3252409616,3252409631,LT 3252409632,3252409647,AO -3252409648,3252410375,LT +3252409648,3252409727,LT +3252409728,3252409735,LR +3252409736,3252410375,LT 3252410376,3252410391,BW 3252410392,3252410431,LT 3252410432,3252410463,BI -3252410464,3252410623,LT +3252410464,3252410495,LT +3252410496,3252410623,BI 3252410624,3252410751,ZW 3252410752,3252411135,LT 3252411136,3252411167,IQ -3252411168,3252411375,LT +3252411168,3252411327,LT +3252411328,3252411367,CD +3252411368,3252411375,LT 3252411376,3252411391,CD 3252411392,3252411647,LT 3252411648,3252411679,BI @@ -69225,7 +72667,8 @@ 3252414512,3252414527,MR 3252414528,3252414591,LT 3252414592,3252414599,GH -3252414600,3252414623,LT +3252414600,3252414607,LT +3252414608,3252414623,ER 3252414624,3252414639,TZ 3252414640,3252414647,GH 3252414648,3252414655,NE @@ -69234,9 +72677,12 @@ 3252414984,3252415007,IQ 3252415008,3252415015,LT 3252415016,3252415127,IQ -3252415128,3252415551,LT -3252415552,3252415567,NG -3252415568,3252415743,LT +3252415128,3252415135,LT +3252415136,3252415167,IQ +3252415168,3252415199,LT +3252415200,3252415231,IQ +3252415232,3252415487,LT +3252415488,3252415743,IQ 3252415744,3252415775,GB 3252415776,3252415967,LT 3252415968,3252415999,CM @@ -69246,8 +72692,8 @@ 3252416960,3252417023,GN 3252417024,3252417279,LT 3252417280,3252417287,IQ -3252417288,3252417359,AF -3252417360,3252417791,LT +3252417288,3252417375,AF +3252417376,3252417791,LT 3252417792,3252417855,NG 3252417856,3252417919,LT 3252417920,3252417935,MW @@ -69277,7 +72723,11 @@ 3252419344,3252419359,LT 3252419360,3252419423,GH 3252419424,3252419839,LT -3252419840,3252419911,IQ +3252419840,3252419879,IQ +3252419880,3252419887,LT +3252419888,3252419895,IQ +3252419896,3252419903,LT +3252419904,3252419911,IQ 3252419912,3252419919,LT 3252419920,3252419927,IQ 3252419928,3252419935,LT @@ -69297,16 +72747,10 @@ 3252420240,3252420247,IQ 3252420248,3252420263,LT 3252420264,3252420271,IQ -3252420272,3252420303,LT -3252420304,3252420311,IQ -3252420312,3252420327,LT -3252420328,3252420335,IQ -3252420336,3252420367,LT +3252420272,3252420367,LT 3252420368,3252420415,IQ 3252420416,3252420431,GB -3252420432,3252420447,IQ -3252420448,3252420455,LT -3252420456,3252420463,IQ +3252420432,3252420463,IQ 3252420464,3252420471,AF 3252420472,3252420583,LT 3252420584,3252420591,IQ @@ -69335,7 +72779,7 @@ 3252427264,3252427519,NG 3252427520,3252427775,LT 3252427776,3252428287,MW -3252428288,3252428351,NG +3252428288,3252428351,LT 3252428352,3252428383,AO 3252428384,3252428415,LT 3252428416,3252428447,KE @@ -69373,7 +72817,7 @@ 3252435312,3252435319,LT 3252435320,3252435327,MZ 3252435328,3252435343,CD -3252435344,3252435359,LT +3252435344,3252435359,BF 3252435360,3252435375,CD 3252435376,3252435415,GN 3252435416,3252435423,CD @@ -69396,13 +72840,16 @@ 3252436320,3252436335,LT 3252436336,3252436351,ZM 3252436352,3252436383,GN -3252436384,3252436447,LT +3252436384,3252436399,LR +3252436400,3252436407,SL +3252436408,3252436415,ML +3252436416,3252436447,LT 3252436448,3252436479,ER 3252436480,3252436991,LT 3252436992,3252437503,NG 3252437504,3252438015,LT 3252438016,3252438271,TR -3252438272,3252438527,MD +3252438272,3252438527,LT 3252438528,3252438783,CM 3252438784,3252439039,LT 3252439040,3252439055,BJ @@ -69442,7 +72889,9 @@ 3252450880,3252450911,NO 3252450912,3252451071,LT 3252451072,3252451327,CH -3252451328,3252451839,LT +3252451328,3252451583,LT +3252451584,3252451599,GM +3252451600,3252451839,LT 3252451840,3252451855,NO 3252451856,3252451967,LT 3252451968,3252451999,NO @@ -69466,9 +72915,7 @@ 3252452504,3252452511,SD 3252452512,3252452607,LT 3252452608,3252452735,TD -3252452736,3252452863,LT -3252452864,3252452879,TZ -3252452880,3252453119,LT +3252452736,3252453119,LT 3252453120,3252453151,NG 3252453152,3252453247,LT 3252453248,3252453271,NG @@ -70045,7 +73492,11 @@ 3254510564,3254510847,NE 3254510848,3254521855,FR 3254521856,3254522367,GB -3254522368,3254550527,FR +3254522368,3254523665,FR +3254523666,3254523666,UG +3254523667,3254523667,CH +3254523668,3254523668,RO +3254523669,3254550527,FR 3254550528,3254550783,US 3254550784,3254551039,IR 3254551040,3254551295,US @@ -70099,7 +73550,7 @@ 3254703616,3254704127,NL 3254704128,3254705663,UA 3254705664,3254706175,GR -3254706176,3254706687,RU +3254706176,3254707199,RU 3254707200,3254707711,TR 3254707712,3254708223,RO 3254708224,3254708735,UA @@ -70129,6 +73580,8 @@ 3254784000,3254784255,IT 3254784256,3254784511,CH 3254784512,3254785279,LT +3254785280,3254785535,KZ +3254785536,3254785791,DK 3254796288,3254797311,SE 3254797312,3254798335,RU 3254798336,3254799359,AT @@ -70479,7 +73932,9 @@ 3255249936,3255249951,LU 3255249952,3255250079,BE 3255250080,3255250111,LU -3255250112,3255252487,BE +3255250112,3255250815,BE +3255250816,3255250879,LU +3255250880,3255252487,BE 3255252488,3255252495,FR 3255252496,3255252527,BE 3255252528,3255252543,LU @@ -70511,7 +73966,9 @@ 3255262800,3255262815,LU 3255262816,3255263295,BE 3255263296,3255263327,US -3255263328,3255270431,BE +3255263328,3255265007,BE +3255265008,3255265023,LU +3255265024,3255270431,BE 3255270432,3255270463,FR 3255270464,3255273855,BE 3255273856,3255273887,LU @@ -70549,7 +74006,9 @@ 3255280048,3255280055,LU 3255280056,3255281407,BE 3255281408,3255281439,LU -3255281440,3255283415,BE +3255281440,3255281759,BE +3255281760,3255281791,LU +3255281792,3255283415,BE 3255283416,3255283423,LU 3255283424,3255283927,BE 3255283928,3255283931,LU @@ -70632,6 +74091,7 @@ 3255328768,3255336959,DE 3255336960,3255341055,RU 3255341056,3255342079,UA +3255342080,3255343103,FR 3255343104,3255344127,RU 3255344128,3255345151,UA 3255345152,3255353343,RU @@ -70812,7 +74272,7 @@ 3255566336,3255574527,SE 3255574528,3255578623,CZ 3255578624,3255582719,SE -3255590912,3255599103,UA +3255582720,3255599103,UA 3255599104,3255615487,CH 3255615488,3255623679,DE 3255623680,3255631871,BG @@ -70823,7 +74283,9 @@ 3255666688,3255697407,NL 3255697408,3255739647,SE 3255739648,3255739903,GB -3255739904,3255745535,SE +3255739904,3255743231,SE +3255743232,3255743487,IT +3255743488,3255745535,SE 3255745536,3255746047,DK 3255746048,3255762943,SE 3255762944,3255799039,DE @@ -70894,6 +74356,7 @@ 3256414720,3256415231,DE 3256415232,3256415743,PL 3256415744,3256416255,UA +3256416256,3256416767,RS 3256416768,3256417279,GB 3256417280,3256417791,NO 3256417792,3256418303,GB @@ -70953,6 +74416,7 @@ 3256643584,3256644607,MD 3256644608,3256645631,IT 3256645632,3256646655,SE +3256646656,3256647679,GB 3256647680,3256648703,RS 3256648704,3256649727,UA 3256649728,3256650751,GB @@ -71078,7 +74542,9 @@ 3257011200,3257011455,BG 3257011456,3257058815,GB 3257058816,3257059071,PL -3257059072,3257144831,GB +3257059072,3257139199,GB +3257139200,3257139455,DK +3257139456,3257144831,GB 3257144832,3257145087,FR 3257145088,3257180159,GB 3257180160,3257180415,TR @@ -71243,6 +74709,7 @@ 3257561088,3257561599,UA 3257561600,3257562111,DE 3257562112,3257563647,PL +3257563648,3257564159,NL 3257564160,3257564671,GB 3257564672,3257565183,RO 3257565184,3257570303,CY @@ -72345,6 +75812,7 @@ 3258903040,3258903295,FR 3258903296,3258903551,GB 3258903552,3258903807,DE +3258903808,3258904063,AT 3258904064,3258941439,GB 3258941440,3258943487,PL 3258943488,3258944511,BG @@ -72366,9 +75834,7 @@ 3259032440,3259032443,ES 3259032444,3259032551,DE 3259032552,3259032559,IT -3259032560,3259032831,DE -3259032832,3259032879,GB -3259032880,3259034319,DE +3259032560,3259034319,DE 3259034320,3259034327,GB 3259034328,3259035447,DE 3259035448,3259035455,IT @@ -72664,6 +76130,7 @@ 3260481536,3260547071,RU 3260547072,3260547327,DE 3260547328,3260547583,UA +3260547584,3260547839,NL 3260547840,3260548095,PL 3260548096,3260548351,IE 3260548352,3260548607,DK @@ -72712,6 +76179,7 @@ 3260600320,3260601343,RU 3260601344,3260601855,CH 3260601856,3260602367,PL +3260602368,3260602879,DK 3260602880,3260603903,UA 3260603904,3260604415,FR 3260604416,3260604927,PL @@ -72837,7 +76305,7 @@ 3261767680,3261775871,RS 3261775872,3261776383,PL 3261776384,3261777407,RU -3261777408,3261777919,KZ +3261777664,3261777919,KZ 3261777920,3261778431,PL 3261778432,3261778943,RU 3261778944,3261779455,RO @@ -72924,47 +76392,41 @@ 3262027776,3262029823,FI 3262029824,3262030847,US 3262030848,3262031871,FR -3262031872,3262033919,FI -3262033920,3262033935,AX -3262033936,3262033951,FI -3262033952,3262033983,AX -3262033984,3262033991,FI -3262033992,3262033999,AX -3262034000,3262034015,FI -3262034016,3262034039,AX -3262034040,3262034111,FI -3262034112,3262034127,AX -3262034128,3262034143,FI -3262034144,3262034295,AX -3262034296,3262034303,FI -3262034304,3262034447,AX -3262034448,3262034451,FI -3262034452,3262034463,AX -3262034464,3262034495,FI -3262034496,3262034511,AX -3262034512,3262034519,FI -3262034520,3262034655,AX -3262034656,3262034687,FI -3262034688,3262034735,AX -3262034736,3262034767,FI -3262034768,3262034879,AX -3262034880,3262034943,FI -3262034944,3262035967,AX -3262035968,3262036111,FI -3262036112,3262036119,AX -3262036120,3262036127,FI -3262036128,3262036159,AX -3262036160,3262036223,FI -3262036224,3262036335,AX -3262036336,3262036351,FI -3262036352,3262036439,AX -3262036440,3262036447,FI -3262036448,3262036623,AX -3262036624,3262036643,FI -3262036644,3262036671,AX -3262036672,3262036687,FI -3262036688,3262036703,AX -3262036704,3262036719,FI +3262031872,3262034047,FI +3262034048,3262034119,AX +3262034120,3262034123,FI +3262034124,3262034127,AX +3262034128,3262034431,FI +3262034432,3262034447,AX +3262034448,3262034455,FI +3262034456,3262034463,AX +3262034464,3262034527,FI +3262034528,3262034559,AX +3262034560,3262034687,FI +3262034688,3262034719,AX +3262034720,3262034783,FI +3262034784,3262034791,AX +3262034792,3262034839,FI +3262034840,3262034847,AX +3262034848,3262034943,FI +3262034944,3262035455,AX +3262035456,3262035487,FI +3262035488,3262035551,AX +3262035552,3262036143,FI +3262036144,3262036151,AX +3262036152,3262036287,FI +3262036288,3262036303,AX +3262036304,3262036311,FI +3262036312,3262036335,AX +3262036336,3262036367,FI +3262036368,3262036383,AX +3262036384,3262036415,FI +3262036416,3262036431,AX +3262036432,3262036463,FI +3262036464,3262036479,AX +3262036480,3262036607,FI +3262036608,3262036615,AX +3262036616,3262036719,FI 3262036720,3262038015,AX 3262038016,3262038271,FR 3262038272,3262038527,RU @@ -72977,8 +76439,7 @@ 3262040064,3262040319,PL 3262040320,3262040575,ES 3262040576,3262040831,RU -3262040832,3262041087,GB -3262041088,3262041343,HU +3262040832,3262041343,GB 3262041344,3262041599,BG 3262041600,3262041855,DK 3262041856,3262042367,FR @@ -73018,23 +76479,35 @@ 3262096128,3262096383,AX 3262096384,3262099199,FI 3262099200,3262099455,NL -3262099456,3262106111,FI -3262106112,3262106623,AX -3262106624,3262108671,FI +3262099456,3262108671,FI 3262108672,3262108927,RU 3262108928,3262114047,FI 3262114048,3262114303,SE 3262114304,3262115071,FI 3262115072,3262115327,RU 3262115328,3262119935,FI -3262119936,3262122367,AX -3262122368,3262122383,FI -3262122384,3262122399,AX -3262122400,3262122431,FI -3262122432,3262123519,AX -3262123520,3262123527,FI -3262123528,3262123775,AX -3262123776,3262124031,FI +3262119936,3262120447,AX +3262120448,3262120703,FI +3262120704,3262121599,AX +3262121600,3262121663,FI +3262121664,3262121727,AX +3262121728,3262121983,FI +3262121984,3262122007,AX +3262122008,3262122015,FI +3262122016,3262122039,AX +3262122040,3262122143,FI +3262122144,3262122159,AX +3262122160,3262122239,FI +3262122240,3262122367,AX +3262122368,3262122431,FI +3262122432,3262122455,AX +3262122456,3262122463,FI +3262122464,3262122591,AX +3262122592,3262122631,FI +3262122632,3262122639,AX +3262122640,3262122751,FI +3262122752,3262122815,AX +3262122816,3262124031,FI 3262124032,3262128127,DE 3262128128,3262136319,GB 3262136320,3262137599,EU @@ -73158,15 +76631,14 @@ 3262444544,3262445055,UA 3262445056,3262445567,RO 3262445568,3262446079,PL -3262446080,3262446591,RU 3262446592,3262447103,PL 3262447104,3262447615,GB 3262447616,3262460415,PT 3262460416,3262460543,UA 3262460544,3262460671,RU -3262460672,3262460799,AE +3262460672,3262460927,AE 3262460928,3262461055,HU -3262461056,3262461183,LV +3262461056,3262461183,DK 3262461184,3262461311,SN 3262461312,3262461439,NO 3262461440,3262461567,DE @@ -73197,7 +76669,9 @@ 3262472336,3262472339,US 3262472340,3262472351,DE 3262472352,3262472355,NL -3262472356,3262472359,ES +3262472356,3262472356,ES +3262472357,3262472358,CH +3262472359,3262472359,ES 3262472360,3262472363,NL 3262472364,3262472367,GB 3262472368,3262472371,NL @@ -73375,9 +76849,7 @@ 3262473484,3262473484,VE 3262473485,3262473485,US 3262473486,3262473486,CA -3262473487,3262473513,US -3262473514,3262473514,PR -3262473515,3262473516,US +3262473487,3262473516,US 3262473517,3262473517,CN 3262473518,3262473526,US 3262473527,3262473527,CN @@ -73878,7 +77350,7 @@ 3262476456,3262476459,CA 3262476460,3262476463,DK 3262476464,3262476467,SK -3262476468,3262476471,IT +3262476468,3262476471,DE 3262476472,3262476475,CA 3262476476,3262476483,US 3262476484,3262476487,DE @@ -74470,8 +77942,7 @@ 3262478510,3262478513,DE 3262478514,3262478514,SE 3262478515,3262478515,PT -3262478516,3262478516,ES -3262478517,3262478519,DE +3262478516,3262478519,DE 3262478520,3262478520,CH 3262478521,3262478521,NL 3262478522,3262478522,QA @@ -74743,8 +78214,7 @@ 3262478913,3262478913,FR 3262478914,3262478914,DE 3262478915,3262478915,NL -3262478916,3262478919,DE -3262478920,3262478920,ZA +3262478916,3262478920,DE 3262478921,3262478921,AT 3262478922,3262478924,DE 3262478925,3262478925,NL @@ -75112,8 +78582,7 @@ 3262479427,3262479427,IT 3262479428,3262479429,FR 3262479430,3262479430,GB -3262479431,3262479432,DE -3262479433,3262479433,ZA +3262479431,3262479433,DE 3262479434,3262479434,IT 3262479435,3262479437,DE 3262479438,3262479438,IT @@ -75205,8 +78674,7 @@ 3262479566,3262479566,NL 3262479567,3262479567,CH 3262479568,3262479568,NO -3262479569,3262479572,DE -3262479573,3262479573,IT +3262479569,3262479573,DE 3262479574,3262479574,CH 3262479575,3262479575,DE 3262479576,3262479576,NL @@ -76121,9 +79589,7 @@ 3263774464,3263774719,BE 3263774720,3263792351,FI 3263792352,3263792367,SE -3263792368,3263792383,FI -3263792384,3263792639,AX -3263792640,3263793151,FI +3263792368,3263793151,FI 3263793152,3263793407,BE 3263793408,3263815123,FI 3263815124,3263815127,AX @@ -76327,7 +79793,9 @@ 3264431104,3264431615,LI 3264431616,3264446207,CH 3264446208,3264446463,FR -3264446464,3264483071,CH +3264446464,3264463871,CH +3264463872,3264466943,LI +3264466944,3264483071,CH 3264483072,3264483327,LI 3264483328,3264486527,CH 3264486528,3264486559,LI @@ -76452,7 +79920,6 @@ 3264665600,3264666111,RO 3264666112,3264666623,IL 3264666624,3264667135,UA -3264667136,3264667647,SE 3264667648,3264668159,BE 3264668160,3264669183,DE 3264669184,3264669695,PL @@ -76548,7 +80015,7 @@ 3264846720,3264846847,RU 3264846848,3264846911,DK 3264846912,3264846975,SK -3264847040,3264847103,GB +3264846976,3264847103,GB 3264847104,3264847135,FR 3264847136,3264847167,ES 3264847168,3264847199,IE @@ -76557,7 +80024,6 @@ 3264847360,3264847487,FR 3264847488,3264847615,RU 3264847616,3264847679,PL -3264847680,3264847743,LV 3264847744,3264847807,BE 3264847808,3264847871,SE 3264847872,3264849919,DE @@ -76610,8 +80076,8 @@ 3264906912,3264906919,GR 3264906920,3264906983,CY 3264906984,3264906995,GR -3264906996,3264907135,CY -3264907136,3264907143,GR +3264906996,3264907139,CY +3264907140,3264907143,GR 3264907144,3264907151,CY 3264907152,3264907155,GR 3264907156,3264907639,CY @@ -76640,8 +80106,8 @@ 3264907964,3264907971,GR 3264907972,3264907987,CY 3264907988,3264907991,GR -3264907992,3264908011,CY -3264908012,3264908019,GR +3264907992,3264908007,CY +3264908008,3264908019,GR 3264908020,3264908023,CY 3264908024,3264908031,GR 3264908032,3264908063,CY @@ -76757,9 +80223,7 @@ 3265219072,3265257471,GB 3265257472,3265259519,NL 3265259520,3265265663,GB -3265265664,3265286463,SK -3265286464,3265286527,SR -3265286528,3265331199,SK +3265265664,3265331199,SK 3265331200,3265340415,GB 3265340416,3265340671,DE 3265340672,3265340927,GB @@ -76853,7 +80317,6 @@ 3265604096,3265604351,SA 3265604352,3265604607,FR 3265604608,3265604863,CH -3265604864,3265605119,FR 3265605120,3265605375,UA 3265605376,3265605631,CZ 3265605632,3265605887,PL @@ -77067,9 +80530,7 @@ 3266804736,3266804991,NL 3266804992,3266805503,GB 3266805504,3266805759,NL -3266805760,3266809343,AT -3266809344,3266809599,LI -3266809600,3266813951,AT +3266805760,3266813951,AT 3266813952,3266822143,UA 3266822144,3266830335,FR 3266830336,3266835151,BE @@ -77452,9 +80913,7 @@ 3267666448,3267666463,EU 3267666464,3267666543,GB 3267666544,3267666575,EU -3267666576,3267666951,GB -3267666952,3267666959,EU -3267666960,3267667199,GB +3267666576,3267667199,GB 3267667200,3267667455,NL 3267667456,3267667967,GB 3267667968,3267670015,EU @@ -77656,8 +81115,8 @@ 3268223232,3268224767,EU 3268224768,3268225023,US 3268225024,3268226367,EU -3268226368,3268226639,GB -3268226640,3268226687,EU +3268226368,3268226655,GB +3268226656,3268226687,EU 3268226688,3268226815,GB 3268226816,3268227327,EU 3268227328,3268227391,GB @@ -77712,8 +81171,10 @@ 3268238360,3268238367,DE 3268238368,3268238463,GB 3268238464,3268238471,DE -3268238472,3268238623,GB -3268238624,3268239103,EU +3268238472,3268238759,GB +3268238760,3268238767,EU +3268238768,3268238847,GB +3268238848,3268239103,EU 3268239104,3268239359,GB 3268239360,3268239583,EU 3268239584,3268240127,GB @@ -77763,9 +81224,7 @@ 3268248320,3268248447,GB 3268248448,3268248511,EU 3268248512,3268248543,GB -3268248544,3268248831,EU -3268248832,3268248959,GB -3268248960,3268249599,EU +3268248544,3268249599,EU 3268249600,3268251311,GB 3268251312,3268251327,IE 3268251328,3268251583,GB @@ -78477,9 +81936,7 @@ 3271280688,3271280703,SE 3271280704,3271280719,FI 3271280720,3271280735,SE -3271280736,3271282687,FI -3271282688,3271284735,AX -3271284736,3271290623,FI +3271280736,3271290623,FI 3271290624,3271290879,BE 3271290880,3271299071,FI 3271299072,3271299199,AX @@ -79630,7 +83087,7 @@ 3273015296,3273023487,SE 3273023488,3273024511,PL 3273024512,3273025535,NL -3273025536,3273027583,RU +3273025536,3273026559,RU 3273027584,3273028607,UA 3273028608,3273029631,PL 3273029632,3273030655,DK @@ -79660,7 +83117,8 @@ 3273050784,3273050879,GR 3273050880,3273051647,IT 3273051648,3273051903,US -3273051904,3273052039,IT +3273051904,3273051967,IE +3273051968,3273052039,IT 3273052040,3273052047,NL 3273052048,3273052063,GR 3273052064,3273052087,IT @@ -79753,8 +83211,8 @@ 3273327280,3273327287,DE 3273327288,3273327359,EU 3273327360,3273327423,IE -3273327424,3273327503,GB -3273327504,3273327519,EU +3273327424,3273327511,GB +3273327512,3273327519,EU 3273327520,3273327551,IE 3273327552,3273328511,EU 3273328512,3273328639,DE @@ -79870,8 +83328,8 @@ 3273364992,3273365247,DE 3273365248,3273365503,EU 3273365504,3273365519,NL -3273365520,3273365527,GB -3273365528,3273365759,NL +3273365520,3273365543,GB +3273365544,3273365759,NL 3273365760,3273365767,GB 3273365768,3273365887,EU 3273365888,3273366015,FR @@ -79957,12 +83415,12 @@ 3273388928,3273389055,DE 3273389056,3273390079,EU 3273390080,3273390111,DE -3273390112,3273390143,EU +3273390112,3273390143,US 3273390144,3273390207,DE 3273390208,3273390335,EU 3273390336,3273390463,DE -3273390464,3273391231,EU -3273391232,3273391327,DE +3273390464,3273391103,EU +3273391104,3273391327,DE 3273391328,3273391343,EU 3273391344,3273391359,DE 3273391360,3273391871,EU @@ -79997,7 +83455,6 @@ 3273438208,3273438719,IL 3273438720,3273439231,PL 3273439232,3273439743,RO -3273439744,3273440255,UA 3273440256,3273440767,RO 3273440768,3273441279,AT 3273441280,3273441463,FR @@ -80061,7 +83518,7 @@ 3273803776,3273804287,CH 3273804288,3273804799,UA 3273804800,3273805311,RO -3273805312,3273805823,GB +3273805312,3273805823,GI 3273805824,3273806335,PL 3273806336,3273806847,DE 3273806848,3273807359,SE @@ -80521,6 +83978,7 @@ 3274698752,3274699007,GB 3274699008,3274699263,FR 3274699264,3274699519,RO +3274699520,3274699775,SI 3274699776,3274700031,GB 3274700032,3274700287,CH 3274700288,3274700543,PL @@ -80553,6 +84011,7 @@ 3274821632,3274823679,KZ 3274823680,3274825727,TR 3274825728,3274827775,DE +3274827776,3274829823,RO 3274829824,3274831871,SE 3274831872,3274833919,RO 3274833920,3274842111,BY @@ -80792,13 +84251,11 @@ 3275423808,3275423871,EU 3275423872,3275424255,GB 3275424256,3275425791,EU -3275425792,3275426599,GB -3275426600,3275426607,EU -3275426608,3275426671,GB -3275426672,3275426815,EU -3275426816,3275427199,GB -3275427200,3275427327,EU -3275427328,3275427583,GB +3275425792,3275426687,GB +3275426688,3275426815,EU +3275426816,3275427271,GB +3275427272,3275427279,EU +3275427280,3275427583,GB 3275427584,3275427839,EU 3275427840,3275428375,GB 3275428376,3275428383,EU @@ -80810,8 +84267,8 @@ 3275430400,3275430591,EU 3275430592,3275430623,GB 3275430624,3275431935,EU -3275431936,3275432447,GB -3275432448,3275433983,EU +3275431936,3275432703,GB +3275432704,3275433983,EU 3275433984,3275437567,GB 3275437568,3275438079,EU 3275438080,3275438607,GB @@ -80822,8 +84279,10 @@ 3275442720,3275444223,EU 3275444224,3275444735,GB 3275444736,3275446271,EU -3275446272,3275446943,GB -3275446944,3275448319,EU +3275446272,3275446991,GB +3275446992,3275447007,EU +3275447008,3275447039,GB +3275447040,3275448319,EU 3275448320,3275449519,GB 3275449520,3275449527,FR 3275449528,3275450879,GB @@ -80832,20 +84291,20 @@ 3275451264,3275452415,EU 3275452416,3275454127,GB 3275454128,3275454143,EU -3275454144,3275454159,GB -3275454160,3275454463,EU -3275454464,3275456383,GB -3275456384,3275456511,EU +3275454144,3275454263,GB +3275454264,3275454271,EU +3275454272,3275454367,GB +3275454368,3275454463,EU +3275454464,3275456415,GB +3275456416,3275456511,EU 3275456512,3275457023,GB 3275457024,3275457791,FK 3275457792,3275458559,GB 3275458560,3275460095,IE 3275460096,3275460607,EU 3275460608,3275460863,HK -3275460864,3275463471,GB -3275463472,3275463487,EU -3275463488,3275463519,GB -3275463520,3275463679,EU +3275460864,3275463523,GB +3275463524,3275463679,EU 3275463680,3275464031,GB 3275464032,3275464047,IE 3275464048,3275468655,GB @@ -80875,8 +84334,8 @@ 3275509984,3275510015,PT 3275510016,3275510079,SE 3275510080,3275510143,ES -3275510144,3275510207,IT -3275510336,3275510399,IE +3275510208,3275510271,SE +3275510272,3275510399,IE 3275510400,3275510463,NL 3275510464,3275510527,GB 3275510528,3275510559,PL @@ -81121,7 +84580,6 @@ 3275628032,3275628543,IL 3275628544,3275629567,RU 3275629568,3275630079,UA -3275630080,3275630591,EU 3275630592,3275631103,PL 3275631104,3275631615,FR 3275631616,3275632127,DE @@ -81374,12 +84832,10 @@ 3276018096,3276018127,GB 3276018128,3276018143,FR 3276018144,3276018159,GB -3276018160,3276018183,FR -3276018184,3276018207,GB -3276018208,3276018375,FR +3276018160,3276018375,FR 3276018376,3276018383,GB -3276018384,3276018423,FR -3276018424,3276018447,GB +3276018384,3276018431,FR +3276018432,3276018447,GB 3276018448,3276018495,FR 3276018496,3276018527,GB 3276018528,3276018543,FR @@ -81414,15 +84870,15 @@ 3276019864,3276019887,GB 3276019888,3276019919,FR 3276019920,3276019927,GB -3276019928,3276020103,FR -3276020104,3276020111,GB -3276020112,3276020399,FR +3276019928,3276020367,FR +3276020368,3276020383,GB +3276020384,3276020399,FR 3276020400,3276020423,GB 3276020424,3276020431,FR 3276020432,3276020439,GB 3276020440,3276020495,FR -3276020496,3276020503,GB -3276020504,3276020559,FR +3276020496,3276020511,GB +3276020512,3276020559,FR 3276020560,3276020567,GB 3276020568,3276020623,FR 3276020624,3276020631,GB @@ -81434,14 +84890,10 @@ 3276020880,3276020887,GB 3276020888,3276020943,FR 3276020944,3276020991,GB -3276020992,3276021103,FR -3276021104,3276021111,GB -3276021112,3276021527,FR -3276021528,3276021535,GB -3276021536,3276021591,FR +3276020992,3276021591,FR 3276021592,3276021599,GB -3276021600,3276021855,FR -3276021856,3276021871,GB +3276021600,3276021863,FR +3276021864,3276021871,GB 3276021872,3276022039,FR 3276022040,3276022047,GB 3276022048,3276022087,FR @@ -81518,7 +84970,9 @@ 3276026320,3276026351,GB 3276026352,3276026423,FR 3276026424,3276026431,GB -3276026432,3276026527,FR +3276026432,3276026439,FR +3276026440,3276026447,GB +3276026448,3276026527,FR 3276026528,3276026535,GB 3276026536,3276026543,FR 3276026544,3276026575,GB @@ -81592,7 +85046,9 @@ 3276029856,3276029887,GB 3276029888,3276029919,FR 3276029920,3276029967,GB -3276029968,3276030079,FR +3276029968,3276029983,FR +3276029984,3276029999,GB +3276030000,3276030079,FR 3276030080,3276030095,GB 3276030096,3276030191,FR 3276030192,3276030207,GB @@ -81604,7 +85060,9 @@ 3276030272,3276030303,GB 3276030304,3276030407,FR 3276030408,3276030415,GB -3276030416,3276030543,FR +3276030416,3276030463,FR +3276030464,3276030495,GB +3276030496,3276030543,FR 3276030544,3276030559,GB 3276030560,3276031255,FR 3276031256,3276031263,GB @@ -81824,7 +85282,9 @@ 3276045288,3276045311,GB 3276045312,3276045351,FR 3276045352,3276045359,GB -3276045360,3276045455,FR +3276045360,3276045391,FR +3276045392,3276045407,GB +3276045408,3276045455,FR 3276045456,3276045463,GB 3276045464,3276045479,FR 3276045480,3276045487,GB @@ -81837,8 +85297,8 @@ 3276045648,3276045767,FR 3276045768,3276045783,GB 3276045784,3276045815,FR -3276045816,3276045823,GB -3276045824,3276045919,FR +3276045816,3276045855,GB +3276045856,3276045919,FR 3276045920,3276045951,GB 3276045952,3276046335,FR 3276046336,3276062719,RU @@ -81908,10 +85368,11 @@ 3276128256,3276129279,AT 3276129280,3276131327,UA 3276131328,3276132351,DK +3276132352,3276133375,PL 3276133376,3276134399,GB 3276134400,3276135423,RU 3276135424,3276136447,UA -3276136448,3276138495,PL +3276137472,3276138495,PL 3276138496,3276139519,NL 3276139520,3276140543,IL 3276140544,3276141567,DE @@ -81925,11 +85386,7 @@ 3276185600,3276193791,NO 3276193792,3276201983,RU 3276201984,3276210175,AT -3276210176,3276227607,DE -3276227608,3276227615,MT -3276227616,3276227727,DE -3276227728,3276227743,MT -3276227744,3276233791,DE +3276210176,3276233791,DE 3276233792,3276233799,RO 3276233800,3276233807,DE 3276233808,3276233823,RO @@ -84051,7 +87508,9 @@ 3276474272,3276474295,AT 3276474296,3276474319,EU 3276474320,3276474367,AT -3276474368,3276475015,EU +3276474368,3276474623,EU +3276474624,3276474879,GB +3276474880,3276475015,EU 3276475016,3276475063,IT 3276475064,3276475071,EU 3276475072,3276475135,IT @@ -84435,8 +87894,8 @@ 3276535552,3276535807,PK 3276535808,3276536063,FI 3276536064,3276536319,EU -3276536320,3276536415,ES -3276536416,3276536447,EU +3276536320,3276536430,ES +3276536431,3276536447,EU 3276536448,3276536511,ES 3276536512,3276536583,EU 3276536584,3276536591,HR @@ -84446,8 +87905,8 @@ 3276536688,3276536711,HU 3276536712,3276536735,EU 3276536736,3276536743,HU -3276536744,3276536863,EU -3276536864,3276536895,ES +3276536744,3276536831,EU +3276536832,3276536895,ES 3276536896,3276536967,EU 3276536968,3276536991,ES 3276536992,3276537151,EU @@ -84497,13 +87956,13 @@ 3276697088,3276697599,GB 3276697600,3276698111,UA 3276698112,3276699647,RU -3276700160,3276700671,KZ +3276700160,3276700671,UA 3276700672,3276701183,RO 3276701184,3276701695,RU 3276701696,3276709887,SE 3276709888,3276718079,DE 3276718080,3276726271,IT -3276726272,3276727295,PK +3276726272,3276727295,DE 3276727296,3276728319,ES 3276728320,3276729343,UA 3276729344,3276730367,PL @@ -84907,7 +88366,9 @@ 3276861440,3276865535,DK 3276865536,3276866559,NL 3276866560,3276866815,IT -3276866816,3276866863,DE +3276866816,3276866831,DE +3276866832,3276866839,GB +3276866840,3276866863,DE 3276866864,3276866879,GB 3276866880,3276866959,DE 3276866960,3276866967,GB @@ -84927,12 +88388,10 @@ 3276872480,3276872511,GB 3276872512,3276872703,DE 3276872704,3276873727,GB -3276873728,3276874335,ES -3276874336,3276874367,GB +3276873728,3276874351,ES +3276874352,3276874367,GB 3276874368,3276874751,ES -3276874752,3276875007,NL -3276875008,3276875263,GB -3276875264,3276875775,NL +3276874752,3276875775,NL 3276875776,3276876031,GB 3276876032,3276876287,DK 3276876288,3276876799,GB @@ -84961,8 +88420,8 @@ 3276883968,3276884487,PL 3276884488,3276886015,GB 3276886016,3276886271,RO -3276886272,3276887551,GB -3276887552,3276888063,DE +3276886272,3276887167,GB +3276887168,3276888063,DE 3276888064,3276888575,GB 3276888576,3276888831,AT 3276888832,3276889087,GB @@ -84977,9 +88436,7 @@ 3276891392,3276892159,US 3276892160,3276893695,IT 3276893696,3276894463,GB -3276894464,3276894719,IT -3276894720,3276894975,GB -3276894976,3276895999,IT +3276894464,3276895999,IT 3276896000,3276896255,CZ 3276896256,3276896831,BE 3276896832,3276896847,SE @@ -84991,15 +88448,21 @@ 3276898304,3276898775,CH 3276898776,3276898783,GB 3276898784,3276900039,CH -3276900040,3276900095,GB -3276900096,3276900351,CH +3276900040,3276900047,GB +3276900048,3276900351,CH 3276900352,3276900607,GB -3276900608,3276900735,CH -3276900736,3276902143,GB +3276900608,3276900799,CH +3276900800,3276900863,GB +3276900864,3276901119,CH +3276901120,3276901375,GB +3276901376,3276901391,CH +3276901392,3276902143,GB 3276902144,3276902151,CH 3276902152,3276902159,GB 3276902160,3276902175,CH -3276902176,3276902399,GB +3276902176,3276902207,GB +3276902208,3276902271,CH +3276902272,3276902399,GB 3276902400,3276902575,SE 3276902576,3276902655,GB 3276902656,3276903422,SE @@ -85009,15 +88472,20 @@ 3276905312,3276905319,ES 3276905320,3276905471,GB 3276905472,3276905727,SE -3276905728,3276906239,BE +3276905728,3276905983,BE +3276905984,3276905999,GB +3276906000,3276906003,BE +3276906004,3276906239,GB 3276906240,3276906279,SE 3276906280,3276906495,GB 3276906496,3276906863,NL 3276906864,3276906879,GB 3276906880,3276907551,NL 3276907552,3276907775,GB -3276907776,3276908031,NL -3276908032,3276910079,GB +3276907776,3276908159,NL +3276908160,3276908287,GB +3276908288,3276908543,NL +3276908544,3276910079,GB 3276910080,3276910591,NL 3276910592,3276910967,IT 3276910968,3276910975,GB @@ -85028,9 +88496,7 @@ 3276913216,3276913919,IT 3276913920,3276913983,US 3276913984,3276914687,IT -3276914688,3276915455,ES -3276915456,3276915487,GB -3276915488,3276916175,ES +3276914688,3276916175,ES 3276916176,3276916183,GB 3276916184,3276917231,ES 3276917232,3276917247,GB @@ -85038,28 +88504,28 @@ 3276917280,3276917287,GB 3276917288,3276917311,ES 3276917312,3276917343,GB -3276917344,3276917823,ES -3276917824,3276918271,GB -3276918272,3276918783,ES +3276917344,3276917887,ES +3276917888,3276918015,GB +3276918016,3276918783,ES 3276918784,3276920551,DE 3276920552,3276920559,GB 3276920560,3276921183,DE 3276921184,3276921191,GB 3276921192,3276921239,DE -3276921240,3276921343,GB -3276921344,3276921399,DE +3276921240,3276921247,GB +3276921248,3276921279,DE +3276921280,3276921295,GB +3276921296,3276921303,DE +3276921304,3276921399,GB 3276921400,3276921403,DK -3276921404,3276921607,DE -3276921608,3276921855,GB -3276921856,3276922623,DE +3276921404,3276921599,GB +3276921600,3276921607,DE +3276921608,3276921727,GB +3276921728,3276922623,DE 3276922624,3276923431,FR -3276923432,3276923455,GB -3276923456,3276923615,FR -3276923616,3276923647,GB -3276923648,3276923743,FR -3276923744,3276923751,GB -3276923752,3276924039,FR -3276924040,3276924095,GB +3276923432,3276923439,GB +3276923440,3276924071,FR +3276924072,3276924095,GB 3276924096,3276924351,FR 3276924352,3276924415,GB 3276924416,3276925951,FR @@ -85276,18 +88742,13 @@ 3277464832,3277467471,US 3277467472,3277467551,CA 3277467552,3277471743,US -3277471744,3277472511,NL -3277472512,3277472607,EU +3277471744,3277472607,NL 3277472608,3277472623,IL -3277472624,3277474815,EU +3277472624,3277474815,NL 3277474816,3277475711,BE -3277475712,3277475839,EU -3277475840,3277476095,NL -3277476096,3277476607,EU +3277475712,3277476607,NL 3277476608,3277477631,BE -3277477632,3277478143,EU -3277478144,3277478399,NL -3277478400,3277479935,EU +3277477632,3277479935,NL 3277479936,3277480959,GB 3277480960,3277481471,DK 3277481472,3277481983,PL @@ -85319,6 +88780,7 @@ 3277687296,3277687807,UA 3277687808,3277688319,RO 3277688320,3277688831,PL +3277688832,3277689343,RU 3277689344,3277689855,AT 3277689856,3277690879,RU 3277690880,3277691391,KZ @@ -85451,6 +88913,7 @@ 3277840384,3277840895,FR 3277840896,3277841407,GR 3277841408,3277841919,RO +3277841920,3277842431,IT 3277842432,3277842943,UA 3277842944,3277843455,PL 3277843456,3277843967,PT @@ -85489,9 +88952,7 @@ 3278054912,3278055423,NL 3278055424,3278061567,GB 3278061568,3278065663,NL -3278065664,3278067967,GB -3278067968,3278068223,BE -3278068224,3278103039,GB +3278065664,3278103039,GB 3278103040,3278103295,FR 3278103296,3278110719,GB 3278110720,3278110751,SE @@ -85501,8 +88962,8 @@ 3278111248,3278115327,SE 3278115328,3278116607,ES 3278116608,3278116863,SE -3278116864,3278118303,ES -3278118304,3278119935,SE +3278116864,3278118399,ES +3278118400,3278119935,SE 3278119936,3278119943,DE 3278119944,3278119967,SE 3278119968,3278119975,NO @@ -85537,13 +88998,13 @@ 3278769664,3278770175,DE 3278770176,3278770687,DK 3278770688,3278771199,DE -3278771200,3278771711,GB 3278771712,3278772223,NL 3278772224,3278772735,BG 3278772736,3278773247,DE 3278773248,3278773759,NO 3278773760,3278774271,GB 3278774272,3278774783,RU +3278774784,3278775295,FR 3278775296,3278775807,GB 3278775808,3278776319,IR 3278776320,3278776831,IL @@ -85560,7 +89021,7 @@ 3278782464,3278782975,GB 3278782976,3278783231,DE 3278783232,3278784703,GB -3278784704,3278784735,US +3278784704,3278784735,NL 3278784736,3278786911,GB 3278786912,3278786943,LU 3278786944,3278787567,GB @@ -85637,8 +89098,7 @@ 3278938368,3278938375,FR 3278938376,3278938379,DE 3278938380,3278938383,FR -3278938384,3278938387,ZA -3278938388,3278938399,DE +3278938384,3278938399,DE 3278938400,3278938403,AT 3278938404,3278938407,GB 3278938408,3278938411,CH @@ -85909,7 +89369,9 @@ 3278939780,3278939783,FR 3278939784,3278939787,BE 3278939788,3278939791,DE -3278939792,3278939803,ES +3278939792,3278939795,ES +3278939796,3278939799,DE +3278939800,3278939803,ES 3278939804,3278939807,GB 3278939808,3278939815,DE 3278939816,3278939819,NL @@ -86108,7 +89570,7 @@ 3278940804,3278940807,DK 3278940808,3278940815,DE 3278940816,3278940819,IT -3278940820,3278940823,GB +3278940820,3278940823,DE 3278940824,3278940827,IT 3278940828,3278940831,DE 3278940832,3278940835,CH @@ -86753,7 +90215,7 @@ 3278943203,3278943203,SE 3278943204,3278943206,DE 3278943207,3278943207,IT -3278943208,3278943208,GB +3278943208,3278943208,DE 3278943209,3278943209,ES 3278943210,3278943212,IT 3278943213,3278943213,DE @@ -87615,9 +91077,7 @@ 3278944366,3278944366,MX 3278944367,3278944367,US 3278944368,3278944368,CA -3278944369,3278944373,US -3278944374,3278944374,PR -3278944375,3278944379,US +3278944369,3278944379,US 3278944380,3278944380,DE 3278944381,3278944385,US 3278944386,3278944386,DE @@ -87684,9 +91144,7 @@ 3278944580,3278944580,AR 3278944581,3278944581,US 3278944582,3278944583,DE -3278944584,3278944586,US -3278944587,3278944587,PR -3278944588,3278944588,US +3278944584,3278944588,US 3278944589,3278944589,DE 3278944590,3278944599,US 3278944600,3278944600,SA @@ -87895,7 +91353,7 @@ 3278945797,3278945797,BE 3278945798,3278945798,NL 3278945799,3278945799,LU -3278945800,3278945800,SE +3278945800,3278945800,DE 3278945801,3278945801,NL 3278945802,3278945802,PT 3278945803,3278945803,GB @@ -87954,8 +91412,8 @@ 3278945875,3278945875,ES 3278945876,3278945876,NL 3278945877,3278945877,SE -3278945878,3278945879,FR -3278945880,3278945880,DE +3278945878,3278945878,FR +3278945879,3278945880,DE 3278945881,3278945881,BE 3278945882,3278945886,DE 3278945887,3278945888,IT @@ -88268,13 +91726,17 @@ 3279593536,3279593567,DE 3279593568,3279593599,GB 3279593600,3279594495,DE -3279594496,3279595903,GB +3279594496,3279595775,GB +3279595776,3279595839,DE +3279595840,3279595903,GB 3279595904,3279595999,DE 3279596000,3279596023,GB 3279596024,3279596031,DE 3279596032,3279596543,GB 3279596544,3279597311,DE -3279597312,3279600383,GB +3279597312,3279598591,GB +3279598592,3279599615,DE +3279599616,3279600383,GB 3279600384,3279600479,DE 3279600480,3279600487,GB 3279600488,3279600639,DE @@ -88343,8 +91805,7 @@ 3280011784,3280011791,BE 3280011792,3280011903,EU 3280011904,3280011951,BE -3280011952,3280014847,EU -3280014848,3280015103,FR +3280011952,3280015103,EU 3280015104,3280015359,GB 3280015360,3280015871,EU 3280015872,3280016383,GB @@ -88922,8 +92383,14 @@ 3280933617,3280933618,GB 3280933619,3280933620,DE 3280933621,3280933631,GB -3280933632,3280934399,DE -3280934400,3280934655,GB +3280933632,3280933647,DE +3280933648,3280933687,GB +3280933688,3280933699,DE +3280933700,3280933703,GB +3280933704,3280933855,DE +3280933856,3280934219,GB +3280934220,3280934243,DE +3280934244,3280934655,GB 3280934656,3280934863,DE 3280934864,3280934911,GB 3280934912,3280934943,DE @@ -89202,8 +92669,10 @@ 3280950016,3280950655,GB 3280950656,3280950687,DE 3280950688,3280951039,GB -3280951040,3280952063,DE -3280952064,3280952067,GB +3280951040,3280951807,DE +3280951808,3280951819,GB +3280951820,3280951831,DE +3280951832,3280952067,GB 3280952068,3280952079,DE 3280952080,3280952087,GB 3280952088,3280952095,DE @@ -89270,7 +92739,13 @@ 3280954128,3280954367,GB 3280954368,3280954495,DE 3280954496,3280955391,GB -3280955392,3280956927,DE +3280955392,3280955419,DE +3280955420,3280955423,GB +3280955424,3280955791,DE +3280955792,3280955799,GB +3280955800,3280956143,DE +3280956144,3280956415,GB +3280956416,3280956927,DE 3280956928,3280956991,GB 3280956992,3280957007,DE 3280957008,3280957015,GB @@ -89286,8 +92761,8 @@ 3280957250,3280957255,GB 3280957256,3280957263,DE 3280957264,3280957311,GB -3280957312,3280957695,DE -3280957696,3280957743,GB +3280957312,3280957503,DE +3280957504,3280957743,GB 3280957744,3280957791,DE 3280957792,3280957823,GB 3280957824,3280957839,DE @@ -89310,13 +92785,15 @@ 3280958916,3280958919,GB 3280958920,3280958927,DE 3280958928,3280958975,GB -3280958976,3280959231,DE -3280959232,3280959487,GB +3280958976,3280959199,DE +3280959200,3280959487,GB 3280959488,3280959711,DE 3280959712,3280959743,GB 3280959744,3280959935,DE -3280959936,3280959999,GB -3280960000,3280960039,DE +3280959936,3280960015,GB +3280960016,3280960023,DE +3280960024,3280960031,GB +3280960032,3280960039,DE 3280960040,3280960255,GB 3280960256,3280960287,DE 3280960288,3280960511,GB @@ -89340,8 +92817,14 @@ 3280963264,3280963303,GB 3280963304,3280963311,DE 3280963312,3280963327,GB -3280963328,3280963583,DE -3280963584,3280963590,GB +3280963328,3280963343,DE +3280963344,3280963359,GB +3280963360,3280963495,DE +3280963496,3280963511,GB +3280963512,3280963515,DE +3280963516,3280963519,GB +3280963520,3280963527,DE +3280963528,3280963590,GB 3280963591,3280963591,DE 3280963592,3280963593,GB 3280963594,3280963595,DE @@ -89438,7 +92921,9 @@ 3280976720,3280976831,GB 3280976832,3280976847,DE 3280976848,3280976895,GB -3280976896,3280977407,DE +3280976896,3280977119,DE +3280977120,3280977135,GB +3280977136,3280977407,DE 3280977408,3280977439,GB 3280977440,3280977479,DE 3280977480,3280977487,GB @@ -90123,7 +93608,6 @@ 3281343232,3281343487,FI 3281343488,3281343743,GB 3281343744,3281343999,TR -3281344000,3281344255,PL 3281344256,3281344511,RU 3281344512,3281344767,UA 3281344768,3281345023,RU @@ -90229,9 +93713,7 @@ 3281975296,3281976319,RU 3281976320,3281976831,DE 3281976832,3281977343,RU -3281977344,3281999095,NO -3281999096,3281999103,US -3281999104,3282042879,NO +3281977344,3282042879,NO 3282042880,3282083839,CH 3282083840,3282084351,DE 3282084352,3282084863,RO @@ -90284,6 +93766,14 @@ 3282181120,3282181631,GB 3282181632,3282182143,DE 3282182144,3282190335,RU +3282190336,3282190847,UA +3282190848,3282191359,IL +3282191360,3282191871,RU +3282191872,3282192383,UA +3282192384,3282192895,BG +3282192896,3282193407,UA +3282193408,3282193919,PL +3282193920,3282194431,RU 3282194432,3282195455,UA 3282195456,3282196479,IE 3282196480,3282197503,UA @@ -90407,9 +93897,7 @@ 3283091456,3283156991,CH 3283156992,3283158215,DE 3283158216,3283158219,EE -3283158220,3283160171,DE -3283160172,3283160175,BE -3283160176,3283173375,DE +3283158220,3283173375,DE 3283173376,3283174399,PL 3283174400,3283176447,UA 3283176448,3283177471,GB @@ -90497,7 +93985,9 @@ 3283291488,3283291491,ES 3283291492,3283304919,DE 3283304920,3283304923,ES -3283304924,3283305087,DE +3283304924,3283304959,DE +3283304960,3283305023,GB +3283305024,3283305087,DE 3283305088,3283305127,FR 3283305128,3283305711,DE 3283305712,3283305715,ES @@ -90997,26 +94487,25 @@ 3283650960,3283650975,CH 3283650976,3283651071,GB 3283651072,3283651135,IT -3283651136,3283651167,EU +3283651136,3283651167,BE 3283651168,3283651183,ES -3283651184,3283651199,EU +3283651184,3283651199,BE 3283651200,3283651263,HU 3283651264,3283651327,ZA -3283651328,3283651423,EU +3283651328,3283651423,BE 3283651424,3283651439,DE -3283651440,3283651463,EU +3283651440,3283651463,BE 3283651464,3283651471,DE -3283651472,3283651487,EU +3283651472,3283651487,BE 3283651488,3283651519,FR 3283651520,3283651583,IL 3283651584,3283651591,GB -3283651592,3283651599,EU +3283651592,3283651599,BE 3283651600,3283651615,DE -3283651616,3283651647,EU +3283651616,3283651647,BE 3283651648,3283651663,SE 3283651664,3283651671,RO -3283651672,3283651679,BE -3283651680,3283651687,EU +3283651672,3283651687,BE 3283651688,3283651695,IT 3283651696,3283651711,GB 3283651712,3283651727,CH @@ -91027,21 +94516,20 @@ 3283651840,3283651967,NL 3283651968,3283652031,DK 3283652032,3283652063,DE -3283652064,3283652071,EU +3283652064,3283652071,BE 3283652072,3283652079,GB -3283652080,3283652095,EU +3283652080,3283652095,BE 3283652096,3283652351,GB 3283652352,3283652479,IT -3283652480,3283652519,EU +3283652480,3283652519,BE 3283652520,3283652527,SE -3283652528,3283652543,EU +3283652528,3283652543,BE 3283652544,3283652575,FR 3283652576,3283652607,DE 3283652608,3283652863,NO -3283652864,3283653055,BE -3283653056,3283653247,EU +3283652864,3283653247,BE 3283653248,3283653311,NO -3283653312,3283653503,EU +3283653312,3283653503,BE 3283653504,3283653631,GB 3283653632,3283653887,FR 3283653888,3283654015,SE @@ -91049,7 +94537,7 @@ 3283654144,3283654399,DE 3283654400,3283654655,CH 3283654656,3283654911,DK -3283654912,3283655039,EU +3283654912,3283655039,BE 3283655040,3283655167,DK 3283655168,3283655295,DE 3283655296,3283655423,BE @@ -91057,16 +94545,16 @@ 3283655680,3283655935,ES 3283655936,3283656191,ZA 3283656192,3283656223,GB -3283656224,3283656255,EU +3283656224,3283656255,BE 3283656256,3283656271,GB -3283656272,3283656303,EU +3283656272,3283656303,BE 3283656304,3283656311,GB -3283656312,3283656447,EU +3283656312,3283656447,BE 3283656448,3283656559,ES 3283656560,3283656575,FR -3283656576,3283656591,EU +3283656576,3283656591,BE 3283656592,3283656599,FR -3283656600,3283656703,EU +3283656600,3283656703,BE 3283656704,3283664895,HU 3283664896,3283673087,UA 3283673088,3283681279,GB @@ -91240,7 +94728,6 @@ 3284041984,3284042239,SI 3284042240,3284042495,GB 3284042496,3284042751,AT -3284042752,3284043007,GB 3284043008,3284043263,DE 3284043264,3284043519,EE 3284043520,3284043775,DE @@ -91366,7 +94853,6 @@ 3284127232,3284127743,NL 3284127744,3284128255,RU 3284128256,3284128767,GB -3284128768,3284129279,CZ 3284129280,3284129791,UA 3284129792,3284130303,DE 3284130304,3284130815,GB @@ -91496,20 +94982,17 @@ 3285057536,3285065727,IT 3285065728,3285073919,RU 3285073920,3285074687,GB -3285074688,3285075199,NL -3285075200,3285076607,EU +3285074688,3285076607,NL 3285076608,3285076767,BE -3285076768,3285078111,EU +3285076768,3285078111,NL 3285078112,3285078143,GB -3285078144,3285078175,EU +3285078144,3285078175,NL 3285078176,3285078191,GB -3285078192,3285079423,EU +3285078192,3285079423,NL 3285079424,3285079551,DE -3285079552,3285079807,EU -3285079808,3285079935,NL -3285079936,3285079967,EU +3285079552,3285079967,NL 3285079968,3285079999,DE -3285080000,3285082111,EU +3285080000,3285082111,NL 3285082112,3285084159,AT 3285084160,3285085183,LU 3285085184,3285086207,GB @@ -91568,6 +95051,7 @@ 3285333504,3285334015,GB 3285334016,3285334527,NL 3285334528,3285335039,DE +3285335040,3285335551,PL 3285335552,3285336063,SE 3285336064,3285352447,IT 3285352448,3285368831,RU @@ -91625,11 +95109,7 @@ 3285453056,3285453119,EU 3285453120,3285453415,GB 3285453416,3285453423,EU -3285453424,3285453439,GB -3285453440,3285453567,EU -3285453568,3285453623,GB -3285453624,3285453631,EU -3285453632,3285454047,GB +3285453424,3285454047,GB 3285454048,3285454079,EU 3285454080,3285454175,GB 3285454176,3285454207,EU @@ -91827,8 +95307,8 @@ 3285472000,3285472127,DE 3285472128,3285472159,EU 3285472160,3285472175,DE -3285472176,3285472191,EU -3285472192,3285472223,DE +3285472176,3285472183,EU +3285472184,3285472223,DE 3285472224,3285472255,EU 3285472256,3285472287,DE 3285472288,3285472367,EU @@ -91906,8 +95386,8 @@ 3285479424,3285479807,CH 3285479808,3285480447,EU 3285480448,3285480575,CH -3285480576,3285480735,EU -3285480736,3285480767,CH +3285480576,3285480719,EU +3285480720,3285480767,CH 3285480768,3285480775,EU 3285480776,3285480895,CH 3285480896,3285480959,EU @@ -92110,7 +95590,7 @@ 3285516224,3285516287,GR 3285516288,3285516543,DK 3285516544,3285516671,NO -3285516672,3285516687,EU +3285516672,3285516687,BE 3285516688,3285516691,NL 3285516692,3285516695,IT 3285516696,3285516703,NL @@ -92119,17 +95599,17 @@ 3285516736,3285516799,DE 3285516800,3285516927,GB 3285516928,3285516991,PL -3285516992,3285517023,EU +3285516992,3285517023,BE 3285517024,3285517055,SE 3285517056,3285517215,GB 3285517216,3285517247,AT 3285517248,3285518335,GB 3285518336,3285518351,NL 3285518352,3285518367,ES -3285518368,3285518463,EU +3285518368,3285518463,BE 3285518464,3285518591,ES 3285518592,3285518847,CH -3285518848,3285519103,EU +3285518848,3285519103,BE 3285519104,3285519359,FR 3285519360,3285519615,DE 3285519616,3285520127,GB @@ -92140,20 +95620,19 @@ 3285520576,3285520639,DE 3285520640,3285520767,NL 3285520768,3285520895,GB -3285520896,3285521167,EU +3285520896,3285521167,BE 3285521168,3285521407,GB -3285521408,3285521535,BE -3285521536,3285521695,EU +3285521408,3285521695,BE 3285521696,3285521791,GB -3285521792,3285522175,EU +3285521792,3285522175,BE 3285522176,3285523071,GB -3285523072,3285523079,EU +3285523072,3285523079,BE 3285523080,3285523087,ES 3285523088,3285523199,CH 3285523200,3285523231,ZA -3285523232,3285523327,EU +3285523232,3285523327,BE 3285523328,3285523335,FI -3285523336,3285523359,EU +3285523336,3285523359,BE 3285523360,3285523391,GB 3285523392,3285523711,FR 3285523712,3285523967,CH @@ -92164,106 +95643,89 @@ 3285524176,3285524191,CH 3285524192,3285524223,BE 3285524224,3285524351,GB -3285524352,3285524479,EU +3285524352,3285524479,BE 3285524480,3285524735,DK 3285524736,3285524863,GB -3285524864,3285524879,EU -3285524880,3285524895,BE +3285524864,3285524895,BE 3285524896,3285524927,ES 3285524928,3285524991,GB -3285524992,3285525247,EU +3285524992,3285525247,BE 3285525248,3285525503,CH -3285525504,3285525759,EU -3285525760,3285526015,BE +3285525504,3285526015,BE 3285526016,3285526023,IL -3285526024,3285526035,EU +3285526024,3285526035,BE 3285526036,3285526039,FR -3285526040,3285526047,EU +3285526040,3285526047,BE 3285526048,3285526079,CZ -3285526080,3285526143,EU +3285526080,3285526143,BE 3285526144,3285526175,HU -3285526176,3285526271,EU -3285526272,3285526335,BE -3285526336,3285526383,EU +3285526176,3285526383,BE 3285526384,3285526399,PT 3285526400,3285526527,CH 3285526528,3285526783,ES 3285526784,3285526815,CH -3285526816,3285526823,EU -3285526824,3285526847,BE +3285526816,3285526847,BE 3285526848,3285526911,CH 3285526912,3285527295,GB -3285527296,3285527423,EU +3285527296,3285527423,BE 3285527424,3285527427,GB -3285527428,3285527431,EU +3285527428,3285527431,BE 3285527432,3285527439,FR 3285527440,3285527455,LU 3285527456,3285527487,IL -3285527488,3285527495,EU +3285527488,3285527495,BE 3285527496,3285527503,DE 3285527504,3285527519,JP -3285527520,3285527551,EU +3285527520,3285527551,BE 3285527552,3285527615,IL 3285527616,3285527679,GB -3285527680,3285527807,EU +3285527680,3285527807,BE 3285527808,3285527811,GB 3285527812,3285527815,PL -3285527816,3285527855,EU +3285527816,3285527855,BE 3285527856,3285527871,FR -3285527872,3285527967,EU +3285527872,3285527967,BE 3285527968,3285527999,DE -3285528000,3285528319,EU +3285528000,3285528319,BE 3285528320,3285528447,DE 3285528448,3285528575,FR -3285528576,3285528703,BE -3285528704,3285528735,EU -3285528736,3285528799,BE +3285528576,3285528799,BE 3285528800,3285528831,GB -3285528832,3285528839,BE -3285528840,3285528847,EU +3285528832,3285528847,BE 3285528848,3285528863,ZA -3285528864,3285528883,EU +3285528864,3285528883,BE 3285528884,3285528887,FR -3285528888,3285528895,EU +3285528888,3285528895,BE 3285528896,3285528911,GB -3285528912,3285528927,BE -3285528928,3285528931,EU +3285528912,3285528931,BE 3285528932,3285528935,FR -3285528936,3285528943,EU +3285528936,3285528943,BE 3285528944,3285529071,GB -3285529072,3285529087,EU -3285529088,3285529151,BE +3285529072,3285529151,BE 3285529152,3285529183,DE 3285529184,3285529199,NL 3285529200,3285529215,IL 3285529216,3285529247,CH 3285529248,3285529263,GB -3285529264,3285529279,EU -3285529280,3285529311,BE -3285529312,3285529343,EU +3285529264,3285529343,BE 3285529344,3285529599,IT 3285529600,3285529631,NO 3285529632,3285529663,IE 3285529664,3285529679,LI 3285529680,3285529687,FI 3285529688,3285529695,IT -3285529696,3285529711,BE -3285529712,3285529727,EU +3285529696,3285529727,BE 3285529728,3285529855,GB 3285529856,3285529951,LU 3285529952,3285529983,GR 3285529984,3285529999,CZ -3285530000,3285530143,EU +3285530000,3285530143,BE 3285530144,3285530175,GB 3285530176,3285530183,NL -3285530184,3285530211,EU -3285530212,3285530215,BE +3285530184,3285530215,BE 3285530216,3285530223,GB 3285530224,3285530271,FR -3285530272,3285530303,EU -3285530304,3285530335,BE -3285530336,3285530367,EU -3285530368,3285530399,BE +3285530272,3285530399,BE 3285530400,3285530431,NL 3285530432,3285530463,IT 3285530464,3285530495,DE @@ -92272,24 +95734,23 @@ 3285530576,3285530583,GB 3285530584,3285530591,BE 3285530592,3285530607,GB -3285530608,3285530623,BE -3285530624,3285530655,EU +3285530608,3285530655,BE 3285530656,3285530687,ZA 3285530688,3285530719,GB -3285530720,3285530723,EU +3285530720,3285530723,BE 3285530724,3285530727,GB 3285530728,3285530735,DE 3285530736,3285530739,GB -3285530740,3285530743,EU +3285530740,3285530743,BE 3285530744,3285530751,GB 3285530752,3285530767,IT 3285530768,3285530783,DE -3285530784,3285530815,EU +3285530784,3285530815,BE 3285530816,3285530831,GB -3285530832,3285530879,EU +3285530832,3285530879,BE 3285530880,3285530911,CH 3285530912,3285530975,GB -3285530976,3285530983,EU +3285530976,3285530983,BE 3285530984,3285530991,IE 3285530992,3285531007,GB 3285531008,3285531023,FR @@ -92297,60 +95758,57 @@ 3285531040,3285531071,ES 3285531072,3285531103,NL 3285531104,3285531119,FR -3285531120,3285531127,BE -3285531128,3285531263,EU +3285531120,3285531263,BE 3285531264,3285531311,GB 3285531312,3285531327,DK -3285531328,3285531343,EU +3285531328,3285531343,BE 3285531344,3285531351,GB 3285531352,3285531355,FR 3285531356,3285531359,ES -3285531360,3285531367,EU +3285531360,3285531367,BE 3285531368,3285531375,DE -3285531376,3285531379,EU -3285531380,3285531383,BE +3285531376,3285531383,BE 3285531384,3285531391,DE 3285531392,3285531423,BE 3285531424,3285531455,DE -3285531456,3285531495,EU +3285531456,3285531495,BE 3285531496,3285531503,NL 3285531504,3285531519,FR -3285531520,3285531535,EU +3285531520,3285531535,BE 3285531536,3285531551,DE 3285531552,3285531567,IL -3285531568,3285531615,EU +3285531568,3285531615,BE 3285531616,3285531647,NL 3285531648,3285531903,BE 3285531904,3285532159,GB 3285532160,3285532223,BE 3285532224,3285532231,ES -3285532232,3285532287,EU -3285532288,3285532415,BE +3285532232,3285532415,BE 3285532416,3285532687,IT 3285532688,3285532703,DE -3285532704,3285532711,EU +3285532704,3285532711,BE 3285532712,3285532719,RU 3285532720,3285532735,IT 3285532736,3285532799,CH 3285532800,3285532831,DE 3285532832,3285532847,FI 3285532848,3285532863,IT -3285532864,3285532895,EU +3285532864,3285532895,BE 3285532896,3285532959,IT -3285532960,3285532975,BE -3285532976,3285533047,EU +3285532960,3285533039,BE +3285533040,3285533047,NL 3285533048,3285533055,BE 3285533056,3285533059,NL -3285533060,3285533087,EU +3285533060,3285533087,BE 3285533088,3285533103,IT 3285533104,3285533119,LU -3285533120,3285533127,EU +3285533120,3285533127,BE 3285533128,3285533135,SE 3285533136,3285533151,GB 3285533152,3285533183,FR 3285533184,3285533311,IT 3285533312,3285533343,SE -3285533344,3285533367,EU +3285533344,3285533367,BE 3285533368,3285533375,CH 3285533376,3285533471,GB 3285533472,3285533503,BE @@ -92363,17 +95821,15 @@ 3285533952,3285534079,IL 3285534080,3285534095,IT 3285534096,3285534111,TR -3285534112,3285534143,EU +3285534112,3285534143,BE 3285534144,3285534207,IT 3285534208,3285534463,PT 3285534464,3285534479,NL -3285534480,3285534495,BE -3285534496,3285534527,EU +3285534480,3285534527,BE 3285534528,3285534559,FR 3285534560,3285534591,IT 3285534592,3285534627,GB -3285534628,3285534631,EU -3285534632,3285534639,BE +3285534628,3285534639,BE 3285534640,3285534655,GB 3285534656,3285534719,IT 3285534720,3285534751,GB @@ -92384,61 +95840,60 @@ 3285534816,3285534831,HU 3285534832,3285534927,IE 3285534928,3285534943,GB -3285534944,3285534975,EU +3285534944,3285534975,BE 3285534976,3285535103,IT -3285535104,3285535119,BE -3285535120,3285535123,EU +3285535104,3285535123,BE 3285535124,3285535127,ES -3285535128,3285535131,EU +3285535128,3285535131,BE 3285535132,3285535135,NL 3285535136,3285535139,FR -3285535140,3285535143,EU +3285535140,3285535143,BE 3285535144,3285535147,GR 3285535148,3285535151,CZ 3285535152,3285535155,SE -3285535156,3285535231,EU +3285535156,3285535231,BE 3285535232,3285535743,NO 3285535744,3285535871,IT 3285535872,3285535903,FR 3285535904,3285535907,DK 3285535908,3285535911,NO -3285535912,3285535919,EU +3285535912,3285535919,BE 3285535920,3285535927,NL -3285535928,3285535951,EU +3285535928,3285535951,BE 3285535952,3285535967,GB -3285535968,3285535999,EU +3285535968,3285535999,BE 3285536000,3285536063,GB -3285536064,3285536079,EU +3285536064,3285536079,BE 3285536080,3285536095,IT 3285536096,3285536111,GB -3285536112,3285536255,EU +3285536112,3285536255,BE 3285536256,3285536511,GB 3285536512,3285536543,LU 3285536544,3285536575,DE 3285536576,3285536607,IL -3285536608,3285536703,EU +3285536608,3285536703,BE 3285536704,3285536735,GB 3285536736,3285536739,IT 3285536740,3285536743,GB 3285536744,3285536747,DE 3285536748,3285536751,AT -3285536752,3285536755,EU +3285536752,3285536755,BE 3285536756,3285536759,IL -3285536760,3285536767,EU +3285536760,3285536767,BE 3285536768,3285536959,DK 3285536960,3285536991,ES 3285536992,3285537023,GB 3285537024,3285537087,IL 3285537088,3285537127,GB -3285537128,3285537135,EU +3285537128,3285537135,BE 3285537136,3285537143,DK 3285537144,3285537151,GB 3285537152,3285537167,DK 3285537168,3285537175,CH -3285537176,3285537183,EU +3285537176,3285537183,BE 3285537184,3285537215,DE 3285537216,3285537231,GB -3285537232,3285537535,EU +3285537232,3285537535,BE 3285537536,3285537599,RU 3285537600,3285537615,FR 3285537616,3285537631,BE @@ -92451,7 +95906,7 @@ 3285538048,3285538175,NL 3285538176,3285538183,DE 3285538184,3285538187,LU -3285538188,3285538207,EU +3285538188,3285538207,BE 3285538208,3285538239,LU 3285538240,3285538271,NO 3285538272,3285538287,FI @@ -92462,14 +95917,13 @@ 3285538328,3285538335,BE 3285538336,3285538351,GB 3285538352,3285538367,LU -3285538368,3285538375,EU +3285538368,3285538375,BE 3285538376,3285538383,AT -3285538384,3285538399,EU +3285538384,3285538399,BE 3285538400,3285538431,DK -3285538432,3285538559,EU -3285538560,3285538623,BE +3285538432,3285538623,BE 3285538624,3285538687,LU -3285538688,3285538719,EU +3285538688,3285538719,BE 3285538720,3285538751,DE 3285538752,3285538755,IT 3285538756,3285538759,FR @@ -92478,10 +95932,10 @@ 3285538768,3285538783,CZ 3285538784,3285538815,BE 3285538816,3285538847,CH -3285538848,3285538879,EU +3285538848,3285538879,BE 3285538880,3285539071,ES 3285539072,3285539327,NL -3285539328,3285539583,EU +3285539328,3285539583,BE 3285539584,3285539711,IE 3285539712,3285539839,GB 3285539840,3285539967,IT @@ -92489,38 +95943,38 @@ 3285540032,3285540095,ZA 3285540096,3285540103,GB 3285540104,3285540107,IT -3285540108,3285540111,EU +3285540108,3285540111,BE 3285540112,3285540127,IL 3285540128,3285540159,ZA 3285540160,3285540191,FI 3285540192,3285540207,CH 3285540208,3285540215,IE -3285540216,3285540219,EU +3285540216,3285540219,BE 3285540220,3285540223,ZA 3285540224,3285540351,CZ 3285540352,3285540415,PT 3285540416,3285540423,ZA -3285540424,3285540447,EU +3285540424,3285540447,BE 3285540448,3285540479,DE 3285540480,3285540607,NL -3285540608,3285540671,EU +3285540608,3285540671,BE 3285540672,3285540735,DE -3285540736,3285540863,EU +3285540736,3285540863,BE 3285540864,3285540871,FR -3285540872,3285540879,EU +3285540872,3285540879,BE 3285540880,3285541375,FR 3285541376,3285541391,GB 3285541392,3285541439,FR 3285541440,3285541519,GB 3285541520,3285541527,BG -3285541528,3285541535,EU +3285541528,3285541535,BE 3285541536,3285541551,FR -3285541552,3285541567,EU +3285541552,3285541567,BE 3285541568,3285541599,GB -3285541600,3285541631,EU +3285541600,3285541631,BE 3285541632,3285541663,ES 3285541664,3285541695,FR -3285541696,3285541759,EU +3285541696,3285541759,BE 3285541760,3285541887,FR 3285541888,3285541919,GB 3285541920,3285541951,FR @@ -92534,32 +95988,32 @@ 3285543424,3285543679,SE 3285543680,3285543743,AT 3285543744,3285543759,FR -3285543760,3285543775,EU +3285543760,3285543775,BE 3285543776,3285543791,IT 3285543792,3285543795,ES -3285543796,3285543799,EU +3285543796,3285543799,BE 3285543800,3285543807,FR 3285543808,3285543871,NL 3285543872,3285543935,FR -3285543936,3285544191,EU +3285543936,3285544191,BE 3285544192,3285544255,IL 3285544256,3285544319,DE 3285544320,3285544335,ES 3285544336,3285544351,NL -3285544352,3285544383,EU +3285544352,3285544383,BE 3285544384,3285544479,FR 3285544480,3285544511,ES 3285544512,3285544639,FR 3285544640,3285544703,BE 3285544704,3285544959,FR 3285544960,3285545215,GB -3285545216,3285545343,EU +3285545216,3285545343,BE 3285545344,3285545379,GB -3285545380,3285545471,EU +3285545380,3285545471,BE 3285545472,3285545727,SE 3285545728,3285545983,FI 3285545984,3285545999,IT -3285546000,3285546007,EU +3285546000,3285546007,BE 3285546008,3285546015,IT 3285546016,3285546063,ES 3285546064,3285546071,IT @@ -92568,7 +96022,7 @@ 3285546240,3285546367,ZA 3285546368,3285546495,FR 3285546496,3285546559,NL -3285546560,3285546623,EU +3285546560,3285546623,BE 3285546624,3285546671,FR 3285546672,3285546687,SE 3285546688,3285546751,GB @@ -92583,15 +96037,15 @@ 3285547264,3285547519,LU 3285547520,3285547775,NL 3285547776,3285547903,ES -3285547904,3285548031,EU +3285547904,3285548031,BE 3285548032,3285548287,FR 3285548288,3285548543,DE 3285548544,3285548607,FR 3285548608,3285548639,LI -3285548640,3285548647,EU +3285548640,3285548647,BE 3285548648,3285548655,LI 3285548656,3285548735,GB -3285548736,3285548767,EU +3285548736,3285548767,BE 3285548768,3285548799,LU 3285548800,3285548831,IT 3285548832,3285548839,GB @@ -92601,46 +96055,43 @@ 3285549024,3285549039,PT 3285549040,3285549055,FR 3285549056,3285549183,DE -3285549184,3285549215,EU +3285549184,3285549215,BE 3285549216,3285549247,CH 3285549248,3285549279,DE 3285549280,3285549311,GB 3285549312,3285549695,DE -3285549696,3285549719,EU +3285549696,3285549719,BE 3285549720,3285549727,GB 3285549728,3285549735,SE -3285549736,3285549767,EU +3285549736,3285549767,BE 3285549768,3285549775,FI 3285549776,3285549791,DE 3285549792,3285549823,LU 3285549824,3285549871,DE 3285549872,3285549887,DK 3285549888,3285549951,DE -3285549952,3285550335,EU +3285549952,3285550335,BE 3285550336,3285550463,GB 3285550464,3285550527,DE 3285550528,3285550591,IT 3285550592,3285550847,FR 3285550848,3285550943,IT 3285550944,3285550975,NL -3285550976,3285551007,EU +3285550976,3285551007,BE 3285551008,3285551039,CH 3285551040,3285551071,DE -3285551072,3285551103,EU +3285551072,3285551103,BE 3285551104,3285551359,DE -3285551360,3285551375,BE -3285551376,3285551391,EU +3285551360,3285551391,BE 3285551392,3285551423,DE 3285551424,3285551487,DK -3285551488,3285551519,BE -3285551520,3285551551,EU +3285551488,3285551551,BE 3285551552,3285551615,DE 3285551616,3285551647,GB 3285551648,3285551679,FR 3285551680,3285551807,GB 3285551808,3285551839,RU -3285551840,3285551871,EU -3285551872,3285552127,BE +3285551840,3285552127,BE 3285552128,3285552191,DE 3285552192,3285552255,ZA 3285552256,3285552287,CZ @@ -92649,61 +96100,60 @@ 3285552384,3285552511,DE 3285552512,3285552639,GB 3285552640,3285552927,DE -3285552928,3285552959,EU +3285552928,3285552959,BE 3285552960,3285553023,FR -3285553024,3285553039,EU +3285553024,3285553039,BE 3285553040,3285553055,EG -3285553056,3285553087,EU +3285553056,3285553087,BE 3285553088,3285553151,IT 3285553152,3285553215,DE -3285553216,3285553247,EU +3285553216,3285553247,BE 3285553248,3285553263,PL 3285553264,3285553727,DE 3285553728,3285553759,CH 3285553760,3285553767,GB 3285553768,3285553775,ZA 3285553776,3285553791,FR -3285553792,3285553855,EU +3285553792,3285553855,BE 3285553856,3285553887,ZA 3285553888,3285553919,DE 3285553920,3285554047,CH 3285554048,3285554127,DE -3285554128,3285554143,EU +3285554128,3285554143,BE 3285554144,3285554175,GB 3285554176,3285554431,AT -3285554432,3285554687,EU +3285554432,3285554687,BE 3285554688,3285554703,DE -3285554704,3285554719,EU +3285554704,3285554719,BE 3285554720,3285554751,FR -3285554752,3285554815,EU +3285554752,3285554815,BE 3285554816,3285554943,CH 3285554944,3285555199,LU 3285555200,3285555231,AT 3285555232,3285555263,NL 3285555264,3285555327,FR 3285555328,3285555455,IL -3285555456,3285555711,EU +3285555456,3285555711,BE 3285555712,3285555967,LU 3285555968,3285556223,IT -3285556224,3285556479,EU +3285556224,3285556479,BE 3285556480,3285556735,DE 3285556736,3285556767,CH -3285556768,3285556771,EU -3285556772,3285556775,BE +3285556768,3285556775,BE 3285556776,3285556779,NL -3285556780,3285556799,EU +3285556780,3285556799,BE 3285556800,3285556863,DE -3285556864,3285556991,EU +3285556864,3285556991,BE 3285556992,3285557055,GB 3285557056,3285557119,NL 3285557120,3285557247,DE 3285557248,3285557363,NL -3285557364,3285557375,EU +3285557364,3285557375,BE 3285557376,3285557519,NL 3285557520,3285557535,FI 3285557536,3285557575,NL 3285557576,3285557579,SE -3285557580,3285557583,EU +3285557580,3285557583,BE 3285557584,3285557599,NL 3285557600,3285557631,BE 3285557632,3285557791,NL @@ -92714,19 +96164,18 @@ 3285557920,3285557951,FR 3285557952,3285558015,DE 3285558016,3285558271,NL -3285558272,3285558399,BE -3285558400,3285558463,EU +3285558272,3285558463,BE 3285558464,3285558591,NL -3285558592,3285558655,EU +3285558592,3285558655,BE 3285558656,3285558783,IT 3285558784,3285559039,GB -3285559040,3285559167,EU +3285559040,3285559167,BE 3285559168,3285559231,NL -3285559232,3285559295,EU +3285559232,3285559295,BE 3285559296,3285559807,SE 3285559808,3285559839,IE 3285559840,3285559871,CH -3285559872,3285559887,EU +3285559872,3285559887,BE 3285559888,3285559903,SE 3285559904,3285559919,NL 3285559920,3285559935,SE @@ -92736,7 +96185,7 @@ 3285560384,3285560447,SE 3285560448,3285560479,LI 3285560480,3285560511,CH -3285560512,3285560575,EU +3285560512,3285560575,BE 3285560576,3285560831,DE 3285560832,3285561215,SE 3285561216,3285561343,NO @@ -92745,31 +96194,31 @@ 3285561472,3285561599,DK 3285561600,3285561619,NO 3285561620,3285561623,DE -3285561624,3285561647,EU +3285561624,3285561647,BE 3285561648,3285561663,NO -3285561664,3285561727,EU +3285561664,3285561727,BE 3285561728,3285561791,NO -3285561792,3285561919,EU +3285561792,3285561919,BE 3285561920,3285561951,CH 3285561952,3285561967,NO -3285561968,3285561983,EU +3285561968,3285561983,BE 3285561984,3285562111,FI 3285562112,3285562367,NO 3285562368,3285562751,FI 3285562752,3285562783,NL -3285562784,3285562815,EU +3285562784,3285562815,BE 3285562816,3285562879,IT 3285562880,3285562911,FI -3285562912,3285562943,EU +3285562912,3285562943,BE 3285562944,3285562975,DE 3285562976,3285562991,FI -3285562992,3285562999,EU +3285562992,3285562999,BE 3285563000,3285563007,GB 3285563008,3285563135,SE 3285563136,3285563391,FI -3285563392,3285563455,EU +3285563392,3285563455,BE 3285563456,3285563471,NL -3285563472,3285563487,EU +3285563472,3285563487,BE 3285563488,3285563519,SE 3285563520,3285563647,PL 3285563648,3285563903,CH @@ -92778,118 +96227,114 @@ 3285564160,3285564415,GB 3285564416,3285564511,CH 3285564512,3285564543,NO -3285564544,3285564671,EU +3285564544,3285564671,BE 3285564672,3285564735,CH 3285564736,3285564751,FR -3285564752,3285564767,EU +3285564752,3285564767,BE 3285564768,3285564799,SE -3285564800,3285564927,EU +3285564800,3285564927,BE 3285564928,3285565183,FR 3285565184,3285565439,NL 3285565440,3285565951,GB 3285565952,3285566015,FR 3285566016,3285566031,IT -3285566032,3285566047,EU +3285566032,3285566047,BE 3285566048,3285566079,CH 3285566080,3285566143,FR -3285566144,3285566207,EU +3285566144,3285566207,BE 3285566208,3285566495,RU 3285566496,3285566511,SE 3285566512,3285566527,FI 3285566528,3285566559,CH -3285566560,3285566575,EU +3285566560,3285566575,BE 3285566576,3285566591,CH 3285566592,3285566655,NL -3285566656,3285566847,EU +3285566656,3285566847,BE 3285566848,3285566975,FR 3285566976,3285567231,GB 3285567232,3285567487,PT 3285567488,3285568511,NL 3285568512,3285568671,DE 3285568672,3285568703,CH -3285568704,3285568751,EU +3285568704,3285568751,BE 3285568752,3285569023,DE -3285569024,3285569407,EU +3285569024,3285569407,BE 3285569408,3285569535,GB 3285569536,3285569791,DE 3285569792,3285570047,FI 3285570048,3285570175,FR -3285570176,3285570207,EU +3285570176,3285570207,BE 3285570208,3285570223,PL 3285570224,3285570239,NL -3285570240,3285570303,EU -3285570304,3285570559,BE +3285570240,3285570559,BE 3285570560,3285570815,SE 3285570816,3285571071,IT 3285571072,3285571327,DE 3285571328,3285571583,FI 3285571584,3285571711,FR 3285571712,3285571775,SE -3285571776,3285571791,BE -3285571792,3285571807,EU +3285571776,3285571807,BE 3285571808,3285571839,DE -3285571840,3285571903,EU +3285571840,3285571903,BE 3285571904,3285571967,SE -3285571968,3285572095,EU +3285571968,3285572095,BE 3285572096,3285572223,DE 3285572224,3285572351,FI 3285572352,3285572367,IR 3285572368,3285572383,ES -3285572384,3285572447,EU +3285572384,3285572447,BE 3285572448,3285572479,CH 3285572480,3285572607,FR 3285572608,3285572863,DK 3285572864,3285573119,IT 3285573120,3285573375,SE -3285573376,3285573535,EU +3285573376,3285573535,BE 3285573536,3285573567,CH 3285573568,3285573631,FR 3285573632,3285573887,NL 3285573888,3285573951,IL -3285573952,3285574143,EU +3285573952,3285574143,BE 3285574144,3285574399,RU 3285574400,3285574655,IL 3285574656,3285574911,GB 3285574912,3285575167,EU 3285575168,3285575423,ES 3285575424,3285575679,IL -3285575680,3285575935,EU +3285575680,3285575935,BE 3285575936,3285575999,DK -3285576000,3285576063,EU +3285576000,3285576063,BE 3285576064,3285576127,FR -3285576128,3285576159,EU +3285576128,3285576159,BE 3285576160,3285576191,DK -3285576192,3285576447,EU +3285576192,3285576447,BE 3285576448,3285576703,CZ 3285576704,3285576959,HU -3285576960,3285577215,EU +3285576960,3285577215,BE 3285577216,3285577471,ZA 3285577472,3285577599,IT -3285577600,3285577983,EU +3285577600,3285577983,BE 3285577984,3285578111,IT 3285578112,3285578239,DE -3285578240,3285578367,EU +3285578240,3285578367,BE 3285578368,3285578431,FR -3285578432,3285578495,EU +3285578432,3285578495,BE 3285578496,3285578751,DE -3285578752,3285579007,EU +3285578752,3285579007,BE 3285579008,3285579519,ES 3285579520,3285579775,FR 3285579776,3285580031,US 3285580032,3285580287,HU 3285580288,3285580415,DE -3285580416,3285580543,EU +3285580416,3285580543,BE 3285580544,3285580547,NL -3285580548,3285580651,EU +3285580548,3285580651,BE 3285580652,3285580655,SE -3285580656,3285580799,EU +3285580656,3285580799,BE 3285580800,3285580831,SE 3285580832,3285580847,PL -3285580848,3285580927,EU +3285580848,3285580927,BE 3285580928,3285581055,ZA -3285581056,3285581183,EU -3285581184,3285581311,BE -3285581312,3285581503,EU +3285581056,3285581503,BE 3285581504,3285581567,AT 3285581568,3285581599,FR 3285581600,3285581615,GB @@ -93012,8 +96457,7 @@ 3285916712,3285916719,CY 3285916720,3285916735,ES 3285916736,3285916799,GB -3285916800,3285916927,EU -3285916928,3285917183,YE +3285916800,3285917183,EU 3285917184,3285917439,ES 3285917440,3285917695,YE 3285917696,3285918719,EU @@ -93023,8 +96467,7 @@ 3285919488,3285919743,UA 3285919744,3285921791,QA 3285921792,3285921823,CZ -3285921824,3285921855,GB -3285921856,3285921919,EU +3285921824,3285921919,EU 3285921920,3285921983,GB 3285921984,3285922111,EU 3285922112,3285922175,FR @@ -93089,14 +96532,14 @@ 3285938432,3285938559,EU 3285938560,3285938607,GB 3285938608,3285938623,FR -3285938624,3285938631,EU +3285938624,3285938631,NG 3285938632,3285938639,ES 3285938640,3285938655,GB -3285938656,3285938687,EU +3285938656,3285938687,DE 3285938688,3285938943,ES -3285938944,3285938951,EU +3285938944,3285938951,NG 3285938952,3285938959,NL -3285938960,3285938975,EU +3285938960,3285938975,US 3285938976,3285939039,ES 3285939040,3285939199,EU 3285939200,3285939711,ES @@ -93131,7 +96574,7 @@ 3285947904,3285948159,NL 3285948160,3285948671,GB 3285948672,3285948927,SA -3285948928,3285949183,GB +3285948928,3285949183,NG 3285949184,3285949439,ES 3285949440,3285949695,DE 3285949696,3285949823,ES @@ -93254,6 +96697,7 @@ 3286334464,3286335487,BG 3286335488,3286336511,RU 3286336512,3286337535,DE +3286337536,3286338559,PL 3286338560,3286339583,RO 3286339584,3286340607,UA 3286340608,3286342655,DE @@ -93423,6 +96867,7 @@ 3286892544,3286893055,LI 3286893056,3286893567,RU 3286893568,3286894591,UA +3286894592,3286895103,PL 3286895104,3286895615,GB 3286895616,3286896127,DE 3286896128,3286896639,SE @@ -93432,7 +96877,7 @@ 3286898176,3286898687,HR 3286898688,3286899199,EU 3286899200,3286899711,IL -3286899712,3286900223,HU +3286899712,3286900223,DE 3286900224,3286900735,RO 3286900736,3286900991,BE 3286900992,3286901503,DE @@ -93610,6 +97055,7 @@ 3287218176,3287218431,DE 3287218432,3287218687,GB 3287218688,3287218943,RU +3287218944,3287219199,FR 3287219200,3287219455,DE 3287219456,3287219711,CH 3287219712,3287220223,SE @@ -93625,6 +97071,7 @@ 3287425024,3287427759,SE 3287427760,3287427775,GB 3287427776,3287433215,SE +3287433216,3287433727,PL 3287433728,3287434239,DE 3287434240,3287434751,PL 3287434752,3287435263,GB @@ -93691,7 +97138,7 @@ 3287464448,3287464703,PL 3287464704,3287464959,NL 3287464960,3287465215,SA -3287465216,3287465471,NO +3287465216,3287465471,SE 3287465472,3287465727,DE 3287465728,3287465983,FR 3287465984,3287467007,DK @@ -93749,9 +97196,7 @@ 3287555072,3287555583,GB 3287555584,3287556095,FR 3287556096,3287564287,TR -3287564288,3287564623,FI -3287564624,3287564655,AX -3287564656,3287572479,FI +3287564288,3287572479,FI 3287572480,3287578863,DE 3287578864,3287578879,LI 3287578880,3287580671,DE @@ -93813,7 +97258,6 @@ 3287668736,3287668991,SI 3287668992,3287669247,PL 3287669248,3287669503,LI -3287669504,3287669759,IE 3287669760,3287670015,RO 3287670016,3287670271,UA 3287670272,3287670527,PL @@ -94133,7 +97577,7 @@ 3288444928,3288449023,NG 3288449024,3288465407,SD 3288465408,3288465919,JM -3288465920,3288466175,ZA +3288465920,3288466175,BW 3288466176,3288466431,MU 3288466432,3288467455,SY 3288467456,3288469503,BI @@ -94295,9 +97739,7 @@ 3290447872,3290456063,AR 3290456064,3290460159,MZ 3290460160,3290464255,ML -3290464256,3290468351,PR -3290468352,3290468607,DO -3290468608,3290471487,PR +3290464256,3290471487,PR 3290471488,3290471551,DO 3290471552,3290472447,PR 3290472448,3290480639,ZA @@ -94308,9 +97750,11 @@ 3290488832,3290489343,NG 3290489344,3290489855,KE 3290489856,3290490367,EG +3290490880,3290492927,ZA 3290497024,3290955775,ZA 3290955776,3290980351,CR 3290980352,3290984447,ZA +3291004928,3291021311,NG 3291021312,3291029503,ZA 3291029504,3291033343,TZ 3291033344,3291033599,KE @@ -94325,6 +97769,13 @@ 3291201536,3291201791,KE 3291201792,3291202047,ZM 3291202048,3291202303,GH +3291202304,3291202559,ZA +3291202560,3291202815,GH +3291202816,3291203071,AO +3291203072,3291203327,EG +3291203328,3291203583,ZW +3291203584,3291203839,ZA +3291203840,3291204095,EG 3291217920,3291230207,ZA 3291230208,3291234303,GH 3291234304,3291242495,ZA @@ -94398,6 +97849,7 @@ 3291437568,3291437823,NA 3291437824,3291439103,ZA 3291447296,3291463679,CI +3291742208,3292004351,ZA 3300917248,3300921343,MU 3300925440,3300929535,MG 3300933632,3300950015,MU @@ -94520,12 +97972,15 @@ 3302954240,3302954495,KE 3302987264,3302987775,MU 3305111552,3307208703,TN +3313500160,3313762303,MA 3315597312,3316121599,EG 3316121600,3316645887,ZA +3316645888,3317170175,KE 3317694464,3318218751,EG 3318218752,3318743039,DZ 3319791616,3320053759,MU 3320053760,3320315903,ZA +3320578048,3320643583,ZA 3321886720,3321888767,MU 3321954304,3321970687,US 3322019840,3322023935,US @@ -94947,32 +98402,7 @@ 3330778880,3330779135,GB 3330779136,3330791423,US 3330791424,3330791679,CA -3330791680,3330883583,US -3330883584,3330884351,NL -3330884352,3330884863,US -3330884864,3330885119,GB -3330885120,3330888063,US -3330888064,3330888127,NL -3330888128,3330888191,US -3330888192,3330888703,AU -3330888704,3330888959,US -3330888960,3330889215,CH -3330889216,3330889471,GB -3330889472,3330890239,JP -3330890240,3330890751,BE -3330890752,3330891263,GB -3330891264,3330892287,US -3330892288,3330892543,FR -3330892544,3330893567,US -3330893568,3330893823,NL -3330893824,3330894079,CA -3330894080,3330894591,GB -3330894592,3330894847,DE -3330894848,3330897919,US -3330897920,3330898175,CA -3330898176,3330898431,DE -3330898432,3330898943,FR -3330898944,3331102463,US +3330791680,3331102463,US 3331102464,3331102719,CA 3331102720,3331194879,US 3331194880,3331260415,AU @@ -95309,10 +98739,7 @@ 3340898048,3340898303,CA 3340898304,3340925071,US 3340925072,3340925079,CA -3340925080,3340925199,US -3340925200,3340925207,RU -3340925208,3340925239,US -3340925240,3340925247,MX +3340925080,3340925247,US 3340925248,3340925255,AR 3340925256,3340925279,US 3340925280,3340925287,CA @@ -95402,7 +98829,10 @@ 3340926928,3340926935,ES 3340926936,3340926951,US 3340926952,3340926959,BR -3340926960,3341444863,US +3340926960,3341041663,US +3341058048,3341082623,US +3341082624,3341084671,CA +3341084672,3341444863,US 3341444864,3341445631,DE 3341445632,3341479935,US 3341479936,3341480447,DE @@ -95434,9 +98864,29 @@ 3341645056,3341645567,CA 3341645568,3341646079,US 3341646080,3341646591,CA -3341646592,3342139391,US +3341646592,3341762559,US +3341778944,3341807615,US +3341807616,3341808639,CA +3341808640,3341828095,US +3341844480,3341863935,US +3341863936,3341864959,AG +3341864960,3341867007,US +3341867008,3341869055,CA +3341869056,3342139391,US 3342139392,3342204927,CH -3342204928,3342598143,US +3342204928,3342483455,US +3342499840,3342505983,US +3342505984,3342507007,BB +3342507008,3342510079,US +3342510080,3342512127,CA +3342512128,3342516223,US +3342516224,3342517247,CA +3342517248,3342526463,US +3342526464,3342528511,CA +3342528512,3342548991,US +3342565376,3342567423,CA +3342567424,3342578687,US +3342579712,3342581759,CA 3342598144,3342603263,CA 3342603264,3342604799,US 3342604800,3342605311,CA @@ -95448,7 +98898,13 @@ 3343365632,3343372543,CA 3343373312,3343376383,US 3343380480,3343384575,CA -3343384576,3344171007,US +3343384576,3343922175,US +3343922176,3343922303,PA +3343922304,3343922975,US +3343922976,3343923007,PA +3343923008,3343923135,US +3343923136,3343923199,HK +3343923200,3344171007,US 3344171008,3344255999,CA 3344256000,3344257023,US 3344261120,3344268543,CA @@ -95745,8 +99201,8 @@ 3355052288,3355053311,CA 3355053312,3355053567,US 3355054080,3355260927,US -3355260928,3355262975,CA -3355262976,3355310591,US +3355260928,3355262719,CA +3355262720,3355310591,US 3355310592,3355311103,CA 3355312128,3355319295,US 3355319296,3355320319,CA @@ -95771,6 +99227,7 @@ 3355447296,3355447551,CU 3355447552,3355447807,AR 3355447808,3355448063,HT +3355448064,3355448319,AR 3355448320,3355449343,AN 3355449344,3355450367,CU 3355450368,3355451391,EC @@ -96000,6 +99457,7 @@ 3356070912,3356071423,BR 3356071424,3356072447,CL 3356072448,3356073215,CR +3356073216,3356073471,AR 3356073472,3356075263,BR 3356075264,3356076287,BO 3356076288,3356078079,BR @@ -96192,8 +99650,11 @@ 3356295168,3356297215,CL 3356297216,3356299263,BR 3356299264,3356305663,MX -3356305664,3356306431,AR -3356307456,3356328959,MX +3356305664,3356307455,AR +3356307456,3356316415,MX +3356316416,3356317695,AR +3356317696,3356328959,MX +3356328960,3356329983,HN 3356329984,3356332031,GF 3356332032,3356334079,CU 3356334080,3356336127,BO @@ -96223,10 +99684,15 @@ 3356368896,3356369407,BR 3356369408,3356369663,EC 3356369664,3356370175,BR +3356370176,3356370943,AR 3356370944,3356372991,CO 3356372992,3356375039,CU 3356375040,3356377087,HN -3356377088,3356389375,CL +3356377088,3356379647,CL +3356379648,3356380159,AR +3356380160,3356380927,CL +3356380928,3356381183,DO +3356381184,3356389375,CL 3356389376,3356389887,CO 3356389888,3356391423,CL 3356391424,3356393471,CO @@ -96540,7 +100006,8 @@ 3359249760,3359249791,BR 3359249792,3359249887,AR 3359249888,3359250175,US -3359250176,3359252039,AR +3359250176,3359252031,AR +3359252032,3359252039,US 3359252040,3359252047,IT 3359252048,3359252063,US 3359252064,3359252095,AR @@ -96552,7 +100019,7 @@ 3359257088,3359257103,BR 3359257104,3359257127,AR 3359257128,3359257135,BR -3359257136,3359257151,AR +3359257136,3359257151,US 3359257152,3359257183,BR 3359257184,3359257215,US 3359257216,3359257247,AR @@ -96916,6 +100383,7 @@ 3362476032,3362476287,HN 3362476288,3362476543,AR 3362476544,3362477055,CR +3362477056,3362478079,AN 3362478080,3362480127,AR 3362480128,3362484223,PE 3362484224,3362484735,AR @@ -96937,6 +100405,7 @@ 3362529280,3362533375,PA 3362537472,3362545663,AR 3362545664,3362549759,PE +3362549760,3362551807,AR 3362553856,3362557951,PY 3362562048,3362563071,BZ 3362563072,3362563199,PA @@ -97798,7 +101267,6 @@ 3392407552,3392409599,ID 3392409600,3392413695,JP 3392413696,3392413951,PK -3392413952,3392414207,HK 3392414208,3392414463,PH 3392414464,3392414719,HK 3392414720,3392415231,AU @@ -97976,6 +101444,7 @@ 3392928256,3392928767,TW 3392928768,3392929279,VN 3392929280,3392929535,PK +3392929536,3392929791,ID 3392929792,3392931839,MU 3392931840,3392933887,PH 3392933888,3392942079,JP @@ -97999,6 +101468,28 @@ 3392999424,3393003519,JP 3393003520,3393011711,PK 3393011712,3393019903,PH +3393019904,3393020159,ID +3393020160,3393020415,MN +3393020416,3393021439,ID +3393021440,3393021695,IN +3393021696,3393021951,HK +3393021952,3393022463,ID +3393022464,3393022975,AP +3393022976,3393023231,PH +3393023232,3393023487,AU +3393023488,3393023743,SG +3393023744,3393023999,IN +3393024000,3393024511,ID +3393024512,3393025023,NZ +3393025024,3393025279,AU +3393025280,3393025535,IN +3393025536,3393025791,PH +3393025792,3393026047,AU +3393026048,3393026559,HK +3393026560,3393026815,AU +3393026816,3393027071,PK +3393027072,3393027839,ID +3393027840,3393028095,PH 3393028096,3393060863,AU 3393060864,3393062911,FJ 3393062912,3393069055,ID @@ -98156,6 +101647,28 @@ 3393848320,3393849343,JP 3393849344,3393851391,CN 3393851392,3393855487,JP +3393855488,3393855743,AU +3393855744,3393855999,NZ +3393856000,3393856255,AU +3393856256,3393856511,HK +3393856768,3393857023,SG +3393857024,3393857535,NZ +3393857536,3393858047,HK +3393858048,3393858559,ID +3393858560,3393858815,AU +3393858816,3393859071,ID +3393859072,3393859327,AU +3393859328,3393859583,JP +3393859584,3393860095,AU +3393860096,3393860607,HK +3393860608,3393860863,AU +3393860864,3393861631,IN +3393861632,3393861887,VN +3393861888,3393862143,AU +3393862144,3393862655,VN +3393862656,3393862911,NZ +3393862912,3393863167,AU +3393863168,3393863679,HK 3393863680,3393865727,AU 3393865728,3393867775,ID 3393867776,3393880063,HK @@ -98451,6 +101964,7 @@ 3395156992,3395158015,CN 3395166208,3395170303,AU 3395170304,3395174399,JP +3395174400,3395174911,AU 3395182592,3395190783,SG 3395190784,3395198975,JP 3395198976,3395203071,MY @@ -99907,9 +103421,7 @@ 3410780160,3410788351,BD 3410788352,3410792447,IN 3410792448,3410796543,BD -3410796544,3410797567,KH 3410797568,3410798591,JP -3410798592,3410799615,IN 3410799616,3410800639,SG 3410800640,3410804735,IN 3410804736,3410821119,PH @@ -100461,7 +103973,6 @@ 3413557248,3413565439,CN 3413565440,3413569535,TW 3413569536,3413569791,SG -3413569792,3413570047,NZ 3413570048,3413570303,KH 3413570304,3413570559,AU 3413570560,3413571583,PH @@ -100496,14 +104007,14 @@ 3413593856,3413594111,KH 3413594112,3413595135,CN 3413595136,3413595391,NZ -3413595392,3413595647,AP +3413595392,3413595647,CN 3413595648,3413595903,AU 3413595904,3413596159,HK 3413596160,3413596671,AP 3413596672,3413597183,NP 3413597184,3413597695,AP 3413597696,3413597951,TW -3413597952,3413598207,AU +3413597952,3413602303,AU 3413639168,3413704703,SG 3413704704,3413737471,MY 3413737472,3413753855,TH @@ -100652,7 +104163,6 @@ 3415441408,3415474175,AU 3415474176,3415490559,CN 3415490560,3415491583,PK -3415494656,3415495679,PH 3415495680,3415496191,ID 3415496704,3415497727,MY 3415497728,3415497983,TW @@ -101824,9 +105334,7 @@ 3423161480,3423161487,HK 3423161488,3423161613,US 3423161614,3423161621,CA -3423161622,3423177471,US -3423177472,3423177727,CA -3423177728,3423182847,US +3423161622,3423182847,US 3423182848,3423183199,CA 3423183200,3423183231,BM 3423183232,3423183263,CA @@ -101848,9 +105356,7 @@ 3423208194,3423208383,AN 3423208384,3423221759,US 3423221760,3423222783,CA -3423222784,3423234751,US -3423234752,3423234783,CA -3423234784,3423235543,US +3423222784,3423235543,US 3423235544,3423235551,TR 3423235552,3423235559,US 3423235560,3423235563,TR @@ -101871,7 +105377,6 @@ 3423264864,3423265247,US 3423265248,3423265263,EC 3423265264,3423266815,US -3423266872,3423266879,US 3423268864,3423269135,CA 3423269136,3423269151,US 3423269152,3423269887,CA @@ -102136,54 +105641,12 @@ 3423401192,3423402943,US 3423402944,3423402951,RU 3423402952,3423412223,US -3423412240,3423412255,GR -3423412256,3423412287,TK -3423412288,3423412319,RU -3423412320,3423412335,CA -3423412416,3423412479,SA -3423412480,3423412495,CA -3423412496,3423412511,US -3423412544,3423412623,FR -3423412624,3423412639,NO -3423412656,3423412671,RU -3423412688,3423412703,CA -3423412704,3423412719,RU -3423412720,3423412727,US -3423412736,3423412751,CA -3423412752,3423412767,US -3423412768,3423412783,FI -3423412800,3423412815,US -3423412816,3423412831,GR -3423412848,3423412863,US -3423412928,3423412991,NL -3423413056,3423413071,US -3423413072,3423413135,CA -3423413152,3423413167,US -3423413184,3423413247,RS -3423413248,3423413279,US -3423413280,3423413295,SE -3423413312,3423413327,PT -3423413328,3423413343,US -3423413376,3423413759,US -3423414016,3423414143,CA -3423414144,3423414159,FR -3423414192,3423414207,US 3423414272,3423416319,US 3423417344,3423417470,US 3423417471,3423417480,AU -3423417481,3423417636,US -3423417637,3423417646,CA -3423417647,3423417715,US -3423417716,3423417725,BR -3423417726,3423417769,US -3423417770,3423417777,CA -3423417778,3423417954,US -3423417955,3423417964,GB -3423417965,3423417975,US +3423417481,3423417975,US 3423417976,3423417995,RO -3423417996,3423418172,US -3423418173,3423418180,JP -3423418181,3423462655,US +3423417996,3423462655,US 3423462656,3423462671,CA 3423462672,3423473663,US 3423473664,3423474655,CA @@ -102194,9 +105657,7 @@ 3423480320,3423480447,NG 3423480448,3423480527,A2 3423480528,3423480543,US -3423480544,3423480575,A2 -3423480576,3423480831,DM -3423480832,3423480927,A2 +3423480544,3423480927,A2 3423480928,3423480935,US 3423480936,3423480943,AO 3423480944,3423481007,A2 @@ -102209,9 +105670,9 @@ 3423481856,3423493631,US 3423493632,3423493887,RU 3423493888,3423493903,ID -3423493904,3423493911,ES -3423493912,3423493927,TT -3423493928,3423493967,US +3423493904,3423493911,US +3423493912,3423493919,TT +3423493920,3423493967,US 3423493968,3423493975,AT 3423493976,3423498079,US 3423498080,3423498087,CA @@ -102258,11 +105719,9 @@ 3423585536,3423585551,IR 3423585552,3423585631,CA 3423585632,3423585647,US -3423585648,3423585807,CA -3423585808,3423585823,US -3423585824,3423585839,CA -3423585840,3423585847,US -3423585848,3423585879,CA +3423585648,3423585775,CA +3423585776,3423585791,IR +3423585792,3423585879,CA 3423585880,3423585887,US 3423585888,3423585895,CA 3423585896,3423585903,NL @@ -102272,7 +105731,7 @@ 3423585928,3423585935,NZ 3423585936,3423585999,CA 3423586000,3423586007,US -3423586008,3423586015,PA +3423586008,3423586015,NZ 3423586016,3423586031,US 3423586032,3423586039,NZ 3423586040,3423586159,CA @@ -102320,42 +105779,7 @@ 3423858688,3423862783,CA 3423862784,3424334847,US 3424334848,3424335871,CA -3424335872,3424335903,US -3424335904,3424335911,CN -3424335912,3424335943,US -3424335944,3424335951,BY -3424335952,3424335983,US -3424335984,3424335991,GB -3424335992,3424336015,US -3424336016,3424336023,BY -3424336024,3424336087,US -3424336088,3424336111,CA -3424336112,3424336367,US -3424336368,3424336375,SE -3424336376,3424336495,US -3424336496,3424336511,CN -3424336512,3424336647,US -3424336648,3424336655,BY -3424336656,3424336703,US -3424336704,3424336711,SG -3424336712,3424336743,US -3424336744,3424336751,GB -3424336752,3424336775,US -3424336776,3424336783,BE -3424336784,3424336847,US -3424336848,3424336855,BR -3424336856,3424336871,US -3424336872,3424336879,IN -3424336880,3424337151,US -3424337152,3424337159,BY -3424337160,3424337175,US -3424337176,3424337183,SG -3424337184,3424337191,US -3424337192,3424337199,BY -3424337200,3424337255,US -3424337256,3424337263,IL -3424337264,3424337271,MX -3424337272,3424378879,US +3424335872,3424378879,US 3424378880,3424379135,PR 3424379136,3424493823,US 3424493824,3424494079,CA @@ -102376,7 +105800,9 @@ 3425875408,3425894399,CA 3425894400,3425912815,US 3425912816,3425912831,DO -3425912832,3425914159,US +3425912832,3425912847,US +3425912848,3425912863,BB +3425912864,3425914159,US 3425914160,3425914239,A2 3425914240,3425915807,US 3425915808,3425915823,NI @@ -102388,7 +105814,15 @@ 3426387968,3426388991,MX 3426388992,3426646015,US 3426646016,3426647039,CA -3426647040,3426744319,US +3426647040,3426680831,US +3426680832,3426682111,KN +3426682112,3426682367,US +3426682368,3426682879,KN +3426682880,3426683647,US +3426683648,3426683903,KN +3426683904,3426684159,US +3426684160,3426684415,KN +3426684416,3426744319,US 3426744320,3426746367,CA 3426746368,3427127295,US 3427127296,3427127551,CA @@ -102986,11 +106420,13 @@ 3434575360,3434575615,BR 3434575616,3434583039,US 3434583040,3434584063,NL -3434584064,3434807295,US -3434807296,3434831359,CA +3434584064,3434807551,US +3434807552,3434810111,CA +3434810112,3434810367,US +3434810368,3434831359,CA 3434831360,3434831615,US -3434831616,3434872831,CA -3434872832,3434907647,US +3434831616,3434872575,CA +3434872576,3434907647,US 3434907648,3434909695,PA 3434909696,3434913791,US 3434913792,3434914047,AG @@ -103010,7 +106446,7 @@ 3435069440,3435134975,CA 3435134976,3435507711,US 3435507712,3435511807,CA -3435528192,3436249087,US +3435511808,3436249087,US 3436249088,3436255743,CA 3436255744,3436256255,US 3436256256,3436282367,CA @@ -103046,18 +106482,26 @@ 3437292800,3437293055,CA 3437293056,3437296639,US 3437296640,3437296895,CA -3437296896,3437297663,US -3437297664,3437307391,CA +3437296896,3437297919,US +3437297920,3437307391,CA 3437307392,3437307903,US 3437307904,3437310975,CA 3437310976,3437311487,US 3437311488,3437331711,CA 3437331712,3437331967,US -3437331968,3437334015,CA +3437331968,3437332479,CA +3437332480,3437332735,US +3437332736,3437334015,CA 3437334016,3437334271,US -3437334272,3437341695,CA +3437334272,3437336063,CA +3437336064,3437336319,US +3437336320,3437341695,CA 3437341696,3437341951,US -3437341952,3437358847,CA +3437341952,3437343231,CA +3437343232,3437343487,US +3437343488,3437350911,CA +3437350912,3437351423,US +3437351424,3437358847,CA 3437358848,3437359103,US 3437359104,3437428735,CA 3437428736,3437691391,US @@ -103127,7 +106571,7 @@ 3437751808,3437752063,GB 3437752064,3437752319,ES 3437752320,3437752575,IE -3437752832,3437755135,US +3437752576,3437755135,US 3437755136,3437755647,JP 3437755648,3437755903,GB 3437755904,3437756159,US @@ -103320,10 +106764,20 @@ 3438084096,3438116863,CA 3438116864,3438215423,US 3438215424,3438215935,CA +3438215936,3438216191,US 3438216192,3438217983,CA 3438217984,3438218239,US 3438218240,3438218751,CA -3438219264,3438280703,CA +3438218752,3438219263,US +3438219264,3438219519,CA +3438219520,3438219775,US +3438219776,3438246911,CA +3438246912,3438247167,US +3438247168,3438252543,CA +3438252544,3438252799,US +3438252800,3438261759,CA +3438261760,3438262015,US +3438262016,3438280703,CA 3438280704,3438542847,US 3438542848,3438544943,CA 3438544944,3438544959,TC @@ -103348,9 +106802,7 @@ 3438592264,3438600319,CA 3438600320,3438600351,US 3438600352,3438608383,CA -3438608384,3438689535,US -3438689536,3438689791,CA -3438689792,3438813183,US +3438608384,3438813183,US 3438813184,3438814207,GH 3438814208,3438895103,US 3438895104,3438896895,HN @@ -103449,7 +106901,11 @@ 3448399360,3448399871,CA 3448399872,3448411391,US 3448411392,3448411455,CA -3448411456,3448461311,US +3448411456,3448414271,US +3448414272,3448414295,JP +3448414296,3448414303,US +3448414304,3448414335,JP +3448414336,3448461311,US 3448461312,3448461391,GB 3448461392,3448461415,US 3448461416,3448461423,SG @@ -103488,8 +106944,12 @@ 3448545976,3448546007,AU 3448546008,3448546047,US 3448546048,3448546079,MY -3448546080,3448546111,SG -3448546112,3448556671,US +3448546080,3448546119,SG +3448546120,3448546175,US +3448546176,3448546207,SG +3448546208,3448546431,US +3448546432,3448546455,AU +3448546456,3448556671,US 3448556672,3448556735,GB 3448556736,3448556799,US 3448556800,3448556815,GB @@ -103499,7 +106959,9 @@ 3448559104,3448559359,GB 3448559360,3448563015,US 3448563016,3448563031,GB -3448563032,3449001245,US +3448563032,3448569055,US +3448569056,3448569087,MX +3448569088,3449001245,US 3449001246,3449001246,MC 3449001247,3449159679,US 3449159680,3449160703,CA @@ -103710,7 +107172,9 @@ 3450936320,3450936351,HK 3450936352,3450974255,US 3450974256,3450974271,GB -3450974272,3451170303,US +3450974272,3450986495,US +3450986496,3450986751,HK +3450986752,3451170303,US 3451170304,3451170559,VE 3451170560,3451187967,US 3451187968,3451188223,AU @@ -103784,7 +107248,7 @@ 3452678144,3452682239,BE 3452682240,3452715007,US 3452715008,3452723199,CA -3452731392,3452764159,US +3452723200,3452764159,US 3452764160,3452764439,CA 3452764440,3452764447,US 3452764448,3452764487,CA @@ -103836,9 +107300,7 @@ 3452936192,3452960767,CA 3452960768,3453026303,US 3453026304,3453028607,CA -3453029376,3453032447,US -3453032448,3453032703,CA -3453032704,3453039167,US +3453029376,3453039167,US 3453039168,3453039183,AU 3453039184,3453039199,US 3453039200,3453039215,CA @@ -104080,8 +107542,8 @@ 3453554880,3453555711,US 3453555712,3453555767,GB 3453555768,3453599999,US -3453600000,3453600511,GB -3453600512,3453607935,US +3453600000,3453600767,GB +3453600768,3453607935,US 3453607936,3453608959,KN 3453608960,3453609983,LC 3453609984,3453610495,AG @@ -104304,7 +107766,9 @@ 3455647488,3455647743,IT 3455647744,3455713279,US 3455713280,3455778815,CA -3455778816,3456303103,US +3455778816,3455871999,US +3455872000,3455872255,ZM +3455872256,3456303103,US 3456303104,3456311295,JP 3456311296,3456892927,US 3456892928,3456958463,CA @@ -104362,7 +107826,9 @@ 3458144032,3458144047,DE 3458144048,3458144111,US 3458144112,3458144119,CA -3458144120,3458195455,US +3458144120,3458144415,US +3458144416,3458144423,DE +3458144424,3458195455,US 3458195456,3458196479,SG 3458196480,3458765631,US 3458765632,3458765695,CA @@ -104563,30 +108029,29 @@ 3460161536,3460163583,PR 3460163584,3460374527,US 3460374528,3460375551,MX -3460375552,3460408359,US -3460408360,3460408367,DE -3460408368,3460409951,US -3460409952,3460409967,DE -3460409968,3460413535,US -3460413536,3460413543,DE -3460413544,3460453631,US +3460375552,3460453631,US 3460453632,3460453887,BS 3460453888,3460507647,US 3460507648,3460507903,MX -3460507904,3460854911,US +3460507904,3460854439,US +3460854440,3460854447,CA +3460854448,3460854831,US +3460854832,3460854847,VE +3460854848,3460854911,US 3460854912,3460854943,GB -3460854944,3460855023,US -3460855024,3460855031,BR -3460855032,3460855247,US +3460854944,3460855247,US 3460855248,3460855255,AU -3460855256,3460855271,US +3460855256,3460855263,VE +3460855264,3460855271,US 3460855272,3460855279,GB 3460855280,3460855287,CA 3460855288,3460855311,US 3460855312,3460855319,CA 3460855320,3460855463,US 3460855464,3460855471,SA -3460855472,3460855535,US +3460855472,3460855495,US +3460855496,3460855503,CA +3460855504,3460855535,US 3460855536,3460855543,MX 3460855544,3460855551,AU 3460855552,3460855631,US @@ -104603,11 +108068,10 @@ 3460855864,3460855871,US 3460855872,3460855879,GB 3460855880,3460855887,GU -3460855888,3460855927,US -3460855928,3460855935,GB -3460855936,3460856007,US +3460855888,3460856007,US 3460856008,3460856015,CA -3460856016,3460856127,US +3460856016,3460856119,US +3460856120,3460856127,GB 3460856128,3460856135,JP 3460856136,3460856191,US 3460856192,3460856199,ZA @@ -104629,7 +108093,11 @@ 3460857056,3460857087,NZ 3460857088,3460857151,US 3460857152,3460857183,CA -3460857184,3460857599,US +3460857184,3460857431,US +3460857432,3460857439,VE +3460857440,3460857463,US +3460857464,3460857471,GB +3460857472,3460857599,US 3460857600,3460857855,AU 3460857856,3460891135,US 3460891136,3460891199,CL @@ -105096,35 +108564,13 @@ 3462340608,3462340863,CA 3462340864,3462350847,US 3462350848,3462351103,CA -3462351104,3462478559,US -3462478560,3462478591,IL -3462478592,3462478623,US -3462478624,3462478655,IL -3462478656,3462478943,US -3462478944,3462478975,IL -3462478976,3462571095,US +3462351104,3462571095,US 3462571096,3462571103,CA 3462571104,3462571663,US 3462571664,3462571671,CA 3462571672,3462593791,US 3462593792,3462594559,GN -3462594560,3462605823,US -3462605824,3462606847,UY -3462606848,3462606863,US -3462606864,3462606927,UY -3462606928,3462606943,US -3462606944,3462606991,UY -3462606992,3462607007,US -3462607008,3462607087,UY -3462607088,3462607135,US -3462607136,3462607167,UY -3462607168,3462607199,US -3462607200,3462607231,UY -3462607232,3462607263,US -3462607264,3462608799,UY -3462608800,3462608815,US -3462608816,3462608895,UY -3462608896,3462633727,US +3462594560,3462633727,US 3462633728,3462633799,BV 3462633800,3462633823,US 3462633824,3462633855,SG @@ -105194,7 +108640,13 @@ 3464185760,3464185791,PR 3464185792,3464190463,US 3464190464,3464190719,CA -3464190720,3464195543,US +3464190720,3464191799,US +3464191800,3464191807,AF +3464191808,3464191815,US +3464191816,3464191823,CA +3464191824,3464191831,US +3464191832,3464191847,CA +3464191848,3464195543,US 3464195544,3464195551,IT 3464195552,3464195887,US 3464195888,3464195895,PR @@ -105206,9 +108658,7 @@ 3464196160,3464196175,US 3464196176,3464196183,AU 3464196184,3464196191,IT -3464196192,3464196287,US -3464196288,3464196295,SG -3464196296,3464208383,US +3464196192,3464208383,US 3464208384,3464216575,CA 3464216576,3464309903,US 3464309904,3464309911,CA @@ -105293,9 +108743,7 @@ 3464768768,3464768895,CA 3464768896,3464769535,US 3464769536,3464773631,CA -3464773632,3464799695,US -3464799696,3464799703,JP -3464799704,3464802303,US +3464773632,3464802303,US 3464802304,3464806399,CA 3464806400,3465154559,US 3465154560,3465158655,BS @@ -105309,7 +108757,9 @@ 3465413120,3465413127,HK 3465413128,3465413375,US 3465413376,3465413383,HK -3465413384,3465510911,US +3465413384,3465462783,US +3465462784,3465463039,GB +3465463040,3465510911,US 3465510912,3465543679,JP 3465543680,3465982991,US 3465982992,3465983007,GB @@ -105574,8 +109024,7 @@ 3468082432,3468082687,NO 3468082688,3468083311,US 3468083312,3468083327,IN -3468083328,3468083391,BR -3468083392,3468083663,US +3468083328,3468083663,US 3468083664,3468083679,ID 3468083680,3468083967,US 3468083968,3468084223,AU @@ -105686,9 +109135,7 @@ 3468128256,3468296191,US 3468296192,3468309503,CA 3468309504,3468309759,US -3468309760,3468313471,CA -3468313472,3468313599,US -3468313600,3468319999,CA +3468309760,3468319999,CA 3468320000,3468320255,US 3468320256,3468320351,CA 3468320352,3468320383,US @@ -105730,7 +109177,9 @@ 3468460032,3468468223,BM 3468468224,3468545791,US 3468545792,3468546047,SG -3468546048,3468623871,US +3468546048,3468619007,US +3468619008,3468619263,CA +3468619264,3468623871,US 3468623872,3468624527,CA 3468624528,3468624543,US 3468624544,3468624551,CA @@ -105753,7 +109202,9 @@ 3468628512,3468628607,US 3468628608,3468628927,CA 3468628928,3468628991,US -3468628992,3468631583,CA +3468628992,3468629311,CA +3468629312,3468629319,US +3468629320,3468631583,CA 3468631584,3468631615,US 3468631616,3468631679,CA 3468631680,3468631695,US @@ -105794,20 +109245,15 @@ 3470139392,3470143487,US 3470147584,3470148095,US 3470148096,3470148351,CA -3470148352,3470148607,US -3470148608,3470148863,CR +3470148352,3470148863,US 3470148864,3470149119,CA 3470149120,3470150655,US 3470150656,3470150911,CA 3470150912,3470151935,US 3470151936,3470152703,CA -3470152704,3470153215,US -3470153216,3470153471,CA -3470153472,3470154495,US -3470154496,3470154751,CA -3470154752,3470155007,US -3470155008,3470155775,CA -3470155776,3470184454,US +3470152704,3470153983,US +3470153984,3470154239,CA +3470154240,3470184454,US 3470184455,3470184458,LK 3470184459,3470184460,RU 3470184461,3470184476,US @@ -106289,30 +109735,27 @@ 3470360800,3470360807,CA 3470360808,3470361039,US 3470361040,3470361055,CA -3470361056,3470361615,US -3470361616,3470361623,AF -3470361624,3470361655,US +3470361056,3470361655,US 3470361656,3470361671,CA 3470361672,3470361703,US 3470361704,3470361711,AF 3470361712,3470361935,US 3470361936,3470361951,CA -3470361952,3470361959,CL -3470361960,3470361983,US +3470361952,3470361983,US 3470361984,3470361991,CA 3470361992,3470362111,US 3470362112,3470362119,CA 3470362120,3470362127,AU -3470362128,3470362159,US +3470362128,3470362135,US +3470362136,3470362143,NL +3470362144,3470362159,US 3470362160,3470362167,AF -3470362168,3470362175,US -3470362176,3470362191,CA -3470362192,3470362263,US +3470362168,3470362263,US 3470362264,3470362271,NZ 3470362272,3470362319,US 3470362320,3470362335,AF -3470362336,3470362447,US -3470362448,3470362479,CA +3470362336,3470362455,US +3470362456,3470362479,CA 3470362480,3470362495,US 3470362496,3470362503,CA 3470362504,3470362559,US @@ -106341,9 +109784,7 @@ 3470364416,3470364479,CA 3470364480,3470364495,HN 3470364496,3470364503,CA -3470364504,3470364527,US -3470364528,3470364535,CA -3470364536,3470458879,US +3470364504,3470458879,US 3470458880,3470475263,KR 3470475264,3470558207,US 3470558208,3470559231,HK @@ -106448,7 +109889,8 @@ 3470646920,3470646935,US 3470646936,3470646943,CA 3470646944,3470646959,BR -3470646960,3470646991,US +3470646960,3470646983,US +3470646984,3470646991,AR 3470646992,3470646999,CN 3470647000,3470651391,US 3470651392,3470655487,CA @@ -106587,7 +110029,11 @@ 3470754304,3470754559,PE 3470754560,3470755839,US 3470755840,3470756095,ZA -3470756096,3470761983,US +3470756096,3470757887,US +3470757888,3470760959,KN +3470760960,3470761215,US +3470761216,3470761727,KN +3470761728,3470761983,US 3470761984,3470762751,CA 3470762752,3470762759,NL 3470762760,3470767871,CA @@ -106599,9 +110045,7 @@ 3470794752,3470802943,PA 3470802944,3470873288,US 3470873289,3470873296,MX -3470873297,3470873584,US -3470873585,3470873592,NA -3470873593,3470875817,US +3470873297,3470875817,US 3470875818,3470875827,JP 3470875828,3470876402,US 3470876403,3470876410,IN @@ -106637,57 +110081,11 @@ 3473040896,3473041407,BM 3473041408,3473096192,US 3473096193,3473096447,PH -3473096448,3473109007,US -3473109008,3473109023,UY -3473109024,3473109039,US -3473109040,3473109071,UY -3473109072,3473109087,US -3473109088,3473109151,UY -3473109152,3473109167,US -3473109168,3473109183,UY -3473109184,3473109215,US -3473109216,3473109247,UY -3473109248,3473109279,US -3473109280,3473109311,UY -3473109312,3473109407,US -3473109408,3473109471,UY -3473109472,3473109487,US -3473109488,3473109495,UY -3473109496,3473109535,US -3473109536,3473109543,UY -3473109544,3473109567,US -3473109568,3473109695,UY -3473109696,3473109791,US -3473109792,3473110271,UY -3473110272,3473110303,US -3473110304,3473110383,UY -3473110384,3473110399,US -3473110400,3473110431,UY -3473110432,3473110495,US -3473110496,3473110783,UY -3473110784,3473110791,US -3473110792,3473110815,UY -3473110816,3473110831,US -3473110832,3473111007,UY -3473111008,3473111167,US -3473111168,3473112575,UY -3473112576,3473112639,US -3473112640,3473112703,UY -3473112704,3473112831,US -3473112832,3473112863,UY -3473112864,3473112895,US -3473112896,3473112959,UY -3473112960,3473276927,US +3473096448,3473276927,US 3473276928,3473342463,CA 3473342464,3473375495,US 3473375496,3473375503,NZ -3473375504,3473375671,US -3473375672,3473375679,GB -3473375680,3473377279,US -3473377280,3473377535,GB -3473377536,3473378559,US -3473378560,3473378575,DE -3473378576,3473381311,US +3473375504,3473381311,US 3473381312,3473381343,DE 3473381344,3473703551,US 3473703552,3473703679,CA @@ -106768,7 +110166,9 @@ 3475745536,3475752703,US 3475752704,3475752959,AN 3475752960,3475881983,US -3475881984,3475884031,CA +3475881984,3475883487,CA +3475883488,3475883519,US +3475883520,3475884031,CA 3475884032,3475884287,US 3475884288,3475884319,CA 3475884320,3475884327,US @@ -106783,9 +110183,7 @@ 3476076320,3476076351,JO 3476076352,3476111359,US 3476111360,3476111871,CA -3476111872,3476221951,US -3476221952,3476223999,UY -3476224000,3476265855,US +3476111872,3476265855,US 3476265856,3476265919,EG 3476265920,3476348927,US 3476348928,3476349183,CA @@ -106815,9 +110213,7 @@ 3476721320,3476721327,GB 3476721328,3476721679,US 3476721680,3476721687,IT -3476721688,3476721703,US -3476721704,3476721711,SI -3476721712,3476721743,US +3476721688,3476721743,US 3476721744,3476721759,CA 3476721760,3476721799,US 3476721800,3476721807,GB @@ -106836,11 +110232,7 @@ 3476722528,3476722543,AU 3476722544,3476722591,US 3476722592,3476722607,GB -3476722608,3476722695,US -3476722696,3476722703,CA -3476722704,3476722727,US -3476722728,3476722735,BR -3476722736,3476722759,US +3476722608,3476722759,US 3476722760,3476722767,IN 3476722768,3476722775,US 3476722776,3476722783,GB @@ -106850,22 +110242,17 @@ 3476725184,3476725215,ZA 3476725216,3476725247,US 3476725248,3476725255,CA -3476725256,3476725263,NL -3476725264,3476725287,US -3476725288,3476725295,NL +3476725256,3476725295,US 3476725296,3476725303,CA -3476725304,3476725359,NL +3476725304,3476725351,US +3476725352,3476725359,NL 3476725360,3476725367,US 3476725368,3476725375,CA -3476725376,3476725383,VE -3476725384,3476725399,US +3476725376,3476725399,US 3476725400,3476725415,CA 3476725416,3476725423,US 3476725424,3476725431,GB -3476725432,3476725439,NL -3476725440,3476725455,US -3476725456,3476725463,NL -3476725464,3476732373,US +3476725432,3476732373,US 3476732374,3476732377,MX 3476732378,3476881407,US 3476881408,3476946943,CA @@ -106893,9 +110280,7 @@ 3478323392,3478323399,CA 3478323400,3478331519,US 3478331520,3478331647,GB -3478331648,3478331839,US -3478331840,3478331847,DK -3478331848,3478332991,US +3478331648,3478332991,US 3478332992,3478332999,CA 3478333000,3478347903,US 3478347904,3478348031,MX @@ -106912,9 +110297,7 @@ 3478364272,3478372351,US 3478372352,3478380543,MX 3478380544,3479207935,US -3479207936,3479214079,CA -3479214080,3479214335,US -3479214336,3479240703,CA +3479207936,3479240703,CA 3479240704,3479289919,US 3479289920,3479289951,BD 3479289952,3479290063,US @@ -106929,7 +110312,9 @@ 3479290368,3479290431,BD 3479290432,3479290487,US 3479290488,3479290495,GB -3479290496,3479290631,US +3479290496,3479290583,US +3479290584,3479290591,CA +3479290592,3479290631,US 3479290632,3479290639,GB 3479290640,3479290743,US 3479290744,3479290751,EC @@ -106974,7 +110359,9 @@ 3479294032,3479294039,BD 3479294040,3479294223,US 3479294224,3479294231,TH -3479294232,3479294487,US +3479294232,3479294419,US +3479294420,3479294423,CA +3479294424,3479294487,US 3479294488,3479294495,MX 3479294496,3479294527,US 3479294528,3479294543,BD @@ -107099,9 +110486,7 @@ 3480251072,3480256511,CA 3480256512,3480284159,US 3480284160,3480284671,CA -3480284672,3480416063,US -3480416064,3480416095,PA -3480416096,3480444927,US +3480284672,3480444927,US 3480444928,3480446335,CA 3480446336,3480446463,US 3480446464,3480446575,CA @@ -107255,8 +110640,8 @@ 3480612096,3480612351,LU 3480612352,3480613631,DE 3480613632,3480839423,US -3480839424,3480840191,GB -3480840192,3480907263,US +3480839424,3480839935,GB +3480839936,3480907263,US 3480907264,3480907775,FR 3480907776,3480968191,US 3480968192,3480968447,AU @@ -107310,7 +110695,9 @@ 3483296005,3483296005,BE 3483296006,3483435007,US 3483435008,3483533311,CA -3483533312,3483631615,US +3483533312,3483552511,US +3483552512,3483552607,GB +3483552608,3483631615,US 3483631616,3483697151,CA 3483697152,3483791359,US 3483791360,3483791407,PR @@ -107335,26 +110722,18 @@ 3483877376,3483893759,CA 3483893760,3484013055,US 3484013056,3484013567,DE -3484013568,3484319743,US -3484320256,3484320815,US -3484320816,3484320823,DE -3484320832,3484321279,US -3484321792,3484450815,US +3484013568,3484450815,US 3484450816,3484451839,CA 3484451840,3484451871,US 3484451872,3484455263,CA 3484455264,3484455295,US -3484455296,3484455359,CA -3484455360,3484455391,US -3484455392,3484455807,CA +3484455296,3484455807,CA 3484455808,3484455871,US 3484455872,3484456191,CA 3484456192,3484456703,US 3484456704,3484457727,CA 3484457728,3484457983,US -3484457984,3484458239,CA -3484458240,3484458495,US -3484458496,3484458783,CA +3484457984,3484458783,CA 3484458784,3484458791,US 3484458792,3484458807,CA 3484458808,3484458815,US @@ -107387,7 +110766,9 @@ 3484460800,3484461079,CA 3484461080,3484461095,US 3484461096,3484461103,CA -3484461104,3484461199,US +3484461104,3484461135,US +3484461136,3484461143,CA +3484461144,3484461199,US 3484461200,3484461231,CA 3484461232,3484461263,US 3484461264,3484461271,CA @@ -107400,13 +110781,11 @@ 3484462104,3484462143,US 3484462144,3484462159,CA 3484462160,3484462175,US -3484462176,3484462199,CA -3484462200,3484462215,US -3484462216,3484462263,CA -3484462264,3484462271,US -3484462272,3484462279,CA -3484462280,3484462303,US -3484462304,3484462975,CA +3484462176,3484462207,CA +3484462208,3484462215,US +3484462216,3484462279,CA +3484462280,3484462295,US +3484462296,3484462975,CA 3484462976,3484463039,US 3484463040,3484463151,CA 3484463152,3484463183,US @@ -107444,11 +110823,7 @@ 3484472184,3484472199,US 3484472200,3484472223,CA 3484472224,3484472263,US -3484472264,3484472271,CA -3484472272,3484472279,US -3484472280,3484472295,CA -3484472296,3484472303,US -3484472304,3484472311,CA +3484472264,3484472311,CA 3484472312,3484472319,US 3484472320,3484472839,CA 3484472840,3484472855,US @@ -107766,7 +111141,9 @@ 3486646016,3486646143,JP 3486646144,3486646271,US 3486646272,3486662655,CA -3486662656,3486699519,US +3486662656,3486677055,US +3486677056,3486677071,CA +3486677072,3486699519,US 3486699520,3486699775,CA 3486699776,3486700399,US 3486700400,3486700407,CA @@ -107797,11 +111174,7 @@ 3487858688,3487859199,KY 3487859200,3487861759,BM 3487861760,3487862015,KY -3487862016,3487862271,BM -3487862272,3487862783,KY -3487862784,3487863039,BM -3487863040,3487863807,KY -3487863808,3487875071,BM +3487862016,3487875071,BM 3487875072,3487891455,US 3487891456,3487907839,CA 3487907840,3487969791,US @@ -107893,13 +111266,7 @@ 3489969152,3489969663,PR 3489969664,3490041503,US 3490041504,3490041535,CA -3490041536,3490072831,US -3490072832,3490073279,CA -3490073280,3490073311,US -3490073312,3490073375,CA -3490073376,3490073599,US -3490073600,3490074622,CA -3490074623,3490228735,US +3490041536,3490228735,US 3490228736,3490229247,CO 3490229248,3490263039,US 3490263040,3490267135,CO @@ -107915,7 +111282,9 @@ 3490732432,3490732447,CA 3490732448,3490786047,US 3490786048,3490786303,PR -3490786304,3490879231,US +3490786304,3490796799,US +3490796800,3490797055,CA +3490797056,3490879231,US 3490879232,3490879487,PR 3490879488,3490922495,US 3490922496,3490924543,CO @@ -107988,8 +111357,7 @@ 3492151296,3492167679,CA 3492167680,3492188799,US 3492188800,3492188831,CH -3492188832,3492208639,US -3492216832,3492472039,US +3492188832,3492472039,US 3492472040,3492472047,GB 3492472048,3492646623,US 3492646624,3492646639,IL @@ -108025,25 +111393,12 @@ 3493081600,3493082623,PY 3493082624,3493089023,US 3493089024,3493089279,A2 -3493089280,3493089311,BO -3493089312,3493089343,US -3493089344,3493090815,BO -3493090816,3493091327,US +3493089280,3493091327,US 3493091328,3493092351,BO 3493092352,3493092607,NA -3493092608,3493135167,US -3493135168,3493135199,CY -3493135200,3493135871,US -3493135872,3493136127,CA -3493136128,3493138207,US +3493092608,3493138207,US 3493138208,3493138239,DE -3493138240,3493139711,US -3493139712,3493139775,CA -3493139776,3493139839,US -3493139840,3493139935,CA -3493139936,3493140127,US -3493140128,3493140159,CA -3493140160,3493141279,US +3493138240,3493141279,US 3493141280,3493141311,CY 3493141312,3493244927,US 3493244928,3493249023,PR @@ -108055,7 +111410,11 @@ 3493874688,3493875711,BM 3493875712,3493881855,US 3493881856,3493882879,CA -3493882880,3493901311,US +3493882880,3493886715,US +3493886716,3493886719,BZ +3493886720,3493901023,US +3493901024,3493901031,HK +3493901032,3493901311,US 3493901312,3493901567,AE 3493901568,3493901599,IL 3493901600,3493901759,US @@ -108068,9 +111427,11 @@ 3493902216,3493902223,CA 3493902224,3493903551,US 3493903552,3493903567,KW -3493903568,3493907199,US +3493903568,3493906431,US +3493906944,3493907199,US 3493907200,3493907231,GB -3493907232,3493914111,US +3493907232,3493907263,US +3493907328,3493914111,US 3493914112,3493914367,CA 3493914368,3493936127,US 3493936128,3493937151,CA @@ -108085,47 +111446,14 @@ 3493991424,3493998591,US 3493998592,3494000639,AI 3494000640,3494003711,US -3494003712,3494003967,CA -3494003968,3494003983,US -3494003984,3494003991,SA -3494003992,3494003999,US -3494004000,3494004047,CA -3494004048,3494004055,US -3494004056,3494004095,CA -3494004096,3494004111,US -3494004112,3494004127,CA -3494004128,3494004159,BR -3494004160,3494004183,US -3494004184,3494004290,CA -3494004291,3494004312,US -3494004313,3494004319,CA -3494004320,3494004351,FR -3494004352,3494004383,US -3494004384,3494004735,CA +3494003712,3494004735,CA 3494004736,3494009855,US 3494009856,3494010879,CA 3494010880,3494011231,US 3494011232,3494011247,HK 3494011248,3494014975,US 3494014976,3494017023,CA -3494017024,3494035455,US -3494035712,3494035791,US -3494035792,3494035807,BY -3494035808,3494035823,CY -3494035824,3494035887,US -3494035888,3494035904,RU -3494035905,3494035967,ES -3494035968,3494036031,US -3494036032,3494036047,CA -3494036048,3494036063,RU -3494036064,3494036255,US -3494036256,3494036287,CA -3494036288,3494036319,US -3494036320,3494036351,RU -3494036352,3494036417,EE -3494036418,3494036431,US -3494036432,3494036439,RU -3494036480,3494044671,US +3494017024,3494044671,US 3494044672,3494045695,CA 3494045696,3494049791,US 3494049792,3494051839,CA @@ -108136,7 +111464,15 @@ 3494088704,3494090751,CA 3494090752,3494094847,US 3494094848,3494095871,CA -3494095872,3494102623,US +3494095872,3494101319,US +3494101320,3494101327,GB +3494101328,3494101377,US +3494101378,3494101385,JM +3494101386,3494101407,US +3494101408,3494101415,CO +3494101416,3494101429,US +3494101430,3494101437,GB +3494101438,3494102623,US 3494102624,3494102639,SB 3494102640,3494102735,US 3494102736,3494102751,VI @@ -108157,7 +111493,15 @@ 3494110162,3494114303,US 3494115328,3494115471,US 3494115472,3494115487,AU -3494115488,3494116407,US +3494115488,3494115495,US +3494115496,3494115503,CA +3494115504,3494115983,US +3494115984,3494115991,AU +3494115992,3494116007,US +3494116008,3494116015,GB +3494116016,3494116375,US +3494116376,3494116383,GB +3494116384,3494116407,US 3494116408,3494116415,CA 3494116416,3494116431,US 3494116432,3494116439,GB @@ -108208,7 +111552,9 @@ 3494206848,3494206887,CA 3494206888,3494206911,US 3494206912,3494206943,CA -3494206944,3494228319,US +3494206944,3494228031,US +3494228032,3494228095,AU +3494228096,3494228319,US 3494228320,3494228335,RU 3494228336,3494228495,US 3494228496,3494228511,CA @@ -108261,8 +111607,8 @@ 3494299688,3494299695,SC 3494299696,3494299727,US 3494299728,3494299735,SC -3494299736,3494300359,US -3494300360,3494300383,TW +3494299736,3494300367,US +3494300368,3494300383,TW 3494300384,3494300927,US 3494300928,3494301055,TW 3494301056,3494301247,US @@ -108286,10 +111632,16 @@ 3494313552,3494316031,US 3494316032,3494317055,CA 3494317056,3494336511,US -3494336512,3494337535,CA +3494336512,3494337023,CA +3494337024,3494337087,US +3494337088,3494337135,CA +3494337136,3494337151,US +3494337152,3494337535,CA 3494337536,3494342655,US 3494342656,3494344703,CA -3494344704,3494350079,US +3494344704,3494349223,US +3494349224,3494349231,GB +3494349232,3494350079,US 3494350080,3494350087,AU 3494350088,3494350095,US 3494350096,3494350103,CA @@ -108407,96 +111759,8 @@ 3494605824,3494606847,CA 3494606848,3494610943,US 3494610944,3494611967,CA -3494611968,3494624263,US -3494624264,3494624271,DE -3494624272,3494624279,US -3494624280,3494624287,GB -3494624288,3494624295,ES -3494624296,3494624319,US -3494624320,3494624327,CR -3494624328,3494624335,SA -3494624336,3494624343,MY -3494624344,3494624351,CA -3494624352,3494624367,US -3494624368,3494624375,CA -3494624376,3494624383,LT -3494624384,3494624391,UA -3494624392,3494624399,GB -3494624400,3494624407,US -3494624408,3494624415,CA -3494624416,3494624423,RU -3494624424,3494624439,US -3494624440,3494624447,NL -3494624448,3494624455,CA -3494624456,3494624463,ES -3494624464,3494624471,US -3494624472,3494624479,ZA -3494624480,3494624527,US -3494624528,3494624535,CA -3494624536,3494624543,US -3494624544,3494624551,CA -3494624552,3494624591,US -3494624592,3494624599,RU -3494624600,3494624607,IL -3494624608,3494624631,US -3494624632,3494624639,ZA -3494624640,3494624647,GB -3494624648,3494624655,MK -3494624656,3494624671,US -3494624672,3494624679,BY -3494624680,3494624687,US -3494624688,3494624695,JP -3494624696,3494624703,NL -3494624704,3494624711,DE -3494624712,3494624719,US -3494624720,3494624727,ZA -3494624728,3494624735,SG -3494624736,3494624751,US -3494624752,3494624759,DE -3494624760,3494624767,RU -3494624768,3494624775,US -3494624776,3494624791,CA -3494624792,3494624799,US -3494624800,3494624807,RU -3494624808,3494624815,CA -3494624816,3494624823,US -3494624824,3494624831,CA -3494624832,3494624855,US -3494624856,3494624863,CA -3494624864,3494624871,US -3494624872,3494624879,CA -3494624880,3494624887,US -3494624888,3494624903,CA -3494624904,3494624911,JP -3494624912,3494624919,DE -3494624920,3494624935,US -3494624936,3494624943,CA -3494624944,3494624951,US -3494624952,3494624959,CA -3494624960,3494624975,AU -3494624976,3494624983,RU -3494624984,3494624991,CA -3494624992,3494625047,US -3494625048,3494625055,CA -3494625056,3494625063,UA -3494625064,3494625071,NL -3494625072,3494625111,US -3494625112,3494625119,VG -3494625120,3494625127,IT -3494625128,3494625143,US -3494625144,3494625151,AU -3494625152,3494625159,US -3494625160,3494625167,UA -3494625168,3494625183,US -3494625184,3494625199,CA -3494625200,3494625207,UA -3494625208,3494625223,US -3494625224,3494625231,CA -3494625232,3494625247,US -3494625248,3494625255,RO -3494625256,3494625263,US -3494625264,3494625271,AE -3494625272,3494625279,AU +3494611968,3494624255,US +3494624256,3494625279,CA 3494625280,3494627327,US 3494627328,3494628351,BM 3494628352,3494651903,US @@ -108534,11 +111798,14 @@ 3494698792,3494698799,CA 3494698800,3494698843,US 3494698844,3494698847,EG -3494698848,3494698887,US +3494698848,3494698879,US +3494698880,3494698887,IN 3494698888,3494698895,EG 3494698896,3494700031,US 3494700032,3494701055,CA -3494701056,3494712319,US +3494701056,3494705319,US +3494705320,3494705327,MX +3494705328,3494712319,US 3494712320,3494713343,CA 3494713344,3494727679,US 3494727680,3494729727,CA @@ -108546,33 +111813,46 @@ 3494730752,3494731775,CA 3494731776,3494743039,US 3494743040,3494744063,CA -3494744064,3494744703,US +3494744064,3494744399,US +3494744400,3494744407,AU +3494744408,3494744703,US 3494744704,3494744711,DK 3494744712,3494745151,US 3494745152,3494745159,AU 3494745160,3494745303,US 3494745304,3494745311,AU -3494745312,3494745919,US +3494745312,3494745879,US +3494745880,3494745887,GB +3494745888,3494745919,US 3494745920,3494745927,CN -3494745928,3494757375,US +3494745928,3494745951,US +3494745952,3494745959,GB +3494745960,3494746019,US +3494746020,3494746023,AU +3494746024,3494757375,US 3494757376,3494758399,CA 3494758400,3494763007,US 3494763008,3494763015,ES 3494763016,3494763047,US 3494763048,3494763055,JP -3494763056,3494763063,US +3494763056,3494763063,AU 3494763064,3494763071,MX 3494763072,3494763119,US 3494763120,3494763127,DE 3494763128,3494763143,US 3494763144,3494763151,ES -3494763152,3494763903,US +3494763152,3494763199,US +3494763200,3494763207,KY +3494763208,3494763903,US 3494763904,3494763919,AU -3494763920,3494764295,US +3494763920,3494763983,US +3494763984,3494763999,AU +3494764000,3494764295,US 3494764296,3494764303,CA 3494764304,3494764343,US 3494764344,3494764351,GB -3494764352,3494764383,US +3494764352,3494764375,US +3494764376,3494764383,AU 3494764384,3494764391,GB 3494764392,3494764447,US 3494764448,3494764463,GB @@ -108602,13 +111882,25 @@ 3494866944,3494867967,CA 3494867968,3494893567,US 3494893568,3494894591,CA -3494894592,3494917119,US -3494917120,3494917631,CA -3494917632,3494928383,US +3494894592,3494906367,US +3494906368,3494906431,IL +3494906432,3494917119,US +3494917120,3494918143,CA +3494918144,3494928383,US 3494928384,3494930431,CA -3494930432,3494938623,US +3494930432,3494935746,US +3494935747,3494935747,GB +3494935748,3494936002,US +3494936003,3494936003,GB +3494936004,3494936258,US +3494936259,3494936259,GB +3494936260,3494936514,US +3494936515,3494936515,GB +3494936516,3494938623,US 3494938624,3494939647,CA -3494939648,3494964223,US +3494939648,3494950655,US +3494950656,3494950911,PH +3494950912,3494964223,US 3494964224,3494965247,PR 3494965248,3494968319,US 3494968320,3494972415,CA @@ -108651,40 +111943,69 @@ 3495136504,3495136847,US 3495136848,3495136855,PR 3495136856,3495153663,US -3495153664,3495154303,CA -3495154304,3495154431,US -3495154432,3495154751,CA -3495154752,3495154759,US -3495154760,3495154823,CA -3495154824,3495154831,US -3495154832,3495154839,CA -3495154840,3495154847,US -3495154848,3495155711,CA +3495153664,3495155711,CA 3495155712,3495157039,US 3495157040,3495157047,SE 3495157048,3495164239,US 3495164240,3495164247,CA -3495164248,3495192575,US +3495164248,3495190527,US 3495192576,3495193599,CA 3495193600,3495215103,US 3495215104,3495217151,VI 3495217152,3495219199,VC -3495219200,3495251967,US +3495219200,3495235663,US +3495235664,3495235671,BR +3495235672,3495235679,AU +3495235680,3495235687,BR +3495235688,3495235695,IN +3495235696,3495235703,FR +3495235704,3495235775,US +3495235776,3495235783,MY +3495235784,3495235791,HR +3495235792,3495235799,US +3495235800,3495235807,ES +3495235808,3495235823,US +3495235824,3495235831,GB +3495235832,3495235903,US +3495235904,3495235911,CA +3495235912,3495235991,US +3495235992,3495235999,CA +3495236000,3495236015,US +3495236016,3495236023,GB +3495236024,3495236111,US +3495236112,3495236119,CZ +3495236120,3495236135,US +3495236136,3495236143,CR +3495236144,3495236367,US +3495236368,3495236375,CA +3495236376,3495251967,US 3495251968,3495254015,CA 3495254016,3495260159,US 3495260160,3495261183,CA -3495261184,3495286783,US +3495261184,3495276287,US +3495276288,3495276351,IN +3495276352,3495286783,US 3495286784,3495288831,CA -3495288832,3495292927,US -3495292928,3495292943,GB -3495292944,3495331839,US +3495288832,3495331839,US 3495331840,3495332863,A2 3495332864,3495333887,CA 3495333888,3495349247,US 3495349248,3495350271,CA 3495350272,3495358463,US 3495358464,3495359487,CA -3495359488,3495367679,US +3495359488,3495362623,US +3495362624,3495362631,BD +3495362632,3495362639,AR +3495362640,3495362711,US +3495362712,3495362719,AR +3495362720,3495362727,US +3495362728,3495362735,A2 +3495362736,3495362751,SG +3495362752,3495363019,US +3495363020,3495363023,AR +3495363024,3495363399,US +3495363400,3495363407,BD +3495363408,3495367679,US 3495367680,3495368703,CA 3495368704,3495370239,US 3495370240,3495370495,CA @@ -108692,12 +112013,30 @@ 3495370752,3495372799,BS 3495372800,3495375871,US 3495375872,3495376895,CA -3495376896,3495399423,US +3495376896,3495393429,US +3495393430,3495393445,AU +3495393446,3495399423,US 3495399424,3495400447,KN 3495400448,3495401471,US 3495403520,3495412735,US 3495412736,3495413759,CA -3495413760,3495429119,US +3495413760,3495424033,US +3495424034,3495424042,IN +3495424043,3495424286,US +3495424287,3495424308,IN +3495424309,3495424321,US +3495424322,3495424346,IN +3495424347,3495424355,US +3495424356,3495424381,IN +3495424382,3495424629,US +3495424630,3495424637,IN +3495424638,3495424789,US +3495424790,3495424797,IN +3495424798,3495424865,US +3495424866,3495424878,IN +3495424879,3495424913,US +3495424914,3495424919,IN +3495424920,3495429119,US 3495429120,3495430143,CA 3495430144,3495440799,US 3495440800,3495440815,PL @@ -108733,13 +112072,35 @@ 3495526400,3495527423,CA 3495527424,3495542783,US 3495542784,3495544831,A2 -3495544832,3495549183,US -3495549184,3495549302,CA -3495549303,3495549334,US -3495549335,3495549439,CA -3495549440,3495549727,US -3495549728,3495549760,CA -3495549761,3495549809,US +3495544832,3495547092,US +3495547093,3495547093,BD +3495547094,3495547102,US +3495547103,3495547103,BD +3495547104,3495547426,US +3495547427,3495547427,BD +3495547428,3495547445,US +3495547446,3495547447,BD +3495547448,3495547471,US +3495547472,3495547479,GB +3495547480,3495547605,US +3495547606,3495547606,BD +3495547607,3495548205,US +3495548206,3495548207,ID +3495548208,3495548544,US +3495548545,3495548545,BD +3495548546,3495548549,US +3495548550,3495548550,BD +3495548551,3495548586,US +3495548587,3495548588,LK +3495548589,3495548635,US +3495548636,3495548637,BD +3495548638,3495548640,US +3495548641,3495548648,BD +3495548649,3495549238,US +3495549239,3495549302,CA +3495549303,3495549366,US +3495549367,3495549430,CA +3495549431,3495549809,US 3495549810,3495549813,IN 3495549814,3495549917,US 3495549918,3495549923,CA @@ -108765,9 +112126,7 @@ 3495657552,3495657567,GB 3495657568,3495658015,US 3495658016,3495658023,IN -3495658024,3495658039,US -3495658040,3495658047,CO -3495658048,3495658319,US +3495658024,3495658319,US 3495658320,3495658327,IN 3495658328,3495673855,US 3495673856,3495674623,GP @@ -108783,82 +112142,76 @@ 3495718912,3495719151,A2 3495719152,3495720959,CA 3495720960,3495724031,US -3495724032,3495727103,CA +3495724032,3495724735,CA +3495724736,3495724799,US +3495724800,3495727103,CA 3495727104,3495740415,US 3495740416,3495741439,CA 3495741440,3495749631,US -3495749632,3495750655,CA +3495749632,3495749735,CA +3495749736,3495749745,US +3495749746,3495749767,CA +3495749768,3495749777,US +3495749778,3495749785,CA +3495749786,3495749829,GB +3495749830,3495749908,CA +3495749909,3495749933,GB +3495749934,3495749941,CA +3495749942,3495749951,US +3495749952,3495749959,CA +3495749960,3495749990,GB +3495749991,3495749991,CA +3495749992,3495750021,GB +3495750022,3495750026,CA +3495750027,3495750051,US +3495750052,3495750074,CA +3495750075,3495750109,GB +3495750110,3495750189,CA +3495750190,3495750204,PA +3495750205,3495750267,CA +3495750268,3495750277,US +3495750278,3495750302,CA +3495750303,3495750327,US +3495750328,3495750343,CA +3495750344,3495750378,AU +3495750379,3495750434,CA +3495750435,3495750444,AU +3495750445,3495750655,CA 3495750656,3495781311,US 3495781312,3495781375,CA -3495781376,3495815167,US -3495815168,3495817215,CA +3495781376,3495812879,US +3495812880,3495812895,GB +3495812896,3495815167,US +3495815168,3495815615,CA +3495815616,3495815619,US +3495815620,3495817215,CA 3495817216,3495828479,US 3495828480,3495829503,CA 3495829504,3495847935,US 3495847936,3495849983,CA -3495849984,3495862271,US +3495849984,3495859394,US +3495859395,3495859395,GB +3495859396,3495859650,US +3495859651,3495859651,GB +3495859652,3495862271,US 3495862272,3495864319,CA -3495864320,3495865343,GP -3495865344,3495866367,CA +3495864320,3495864831,DM +3495864832,3495865343,GP +3495865344,3495865599,CA +3495865600,3495865631,BD +3495865632,3495866207,CA +3495866208,3495866239,BD +3495866240,3495866359,CA +3495866360,3495866363,US +3495866364,3495866367,CA 3495866368,3495868415,VC 3495868416,3495871487,US 3495871488,3495872511,CA -3495872512,3495882799,US -3495882800,3495882807,AM -3495882808,3495882815,US -3495882816,3495882823,RU -3495882824,3495882863,US -3495882864,3495882871,AU -3495882872,3495882895,US -3495882896,3495882911,CN -3495882912,3495882927,JP -3495882928,3495882983,US -3495882984,3495882991,AU -3495882992,3495882999,CA -3495883000,3495883215,US -3495883216,3495883223,AU -3495883224,3495883287,US -3495883288,3495883295,GB -3495883296,3495883311,US -3495883312,3495883319,TR -3495883320,3495883327,SA -3495883328,3495883367,US -3495883368,3495883375,AU -3495883376,3495883391,US -3495883392,3495883399,IN -3495883400,3495883407,US -3495883408,3495883415,EG -3495883416,3495883439,US -3495883440,3495883447,GB -3495883448,3495883479,US -3495883480,3495883487,BR -3495883488,3495883503,CN -3495883504,3495883615,US -3495883616,3495883623,AU -3495883624,3495883631,US -3495883632,3495883647,GM -3495883648,3495883759,US -3495883760,3495883775,CN -3495883776,3495884119,US -3495884120,3495884127,CA -3495884128,3495884239,US -3495884240,3495884247,AU -3495884248,3495884263,US -3495884264,3495884271,IN -3495884272,3495884287,CN -3495884288,3495884447,US -3495884448,3495884463,AU -3495884464,3495884479,US -3495884480,3495884487,BY -3495884488,3495884519,US -3495884520,3495884527,IN -3495884528,3495884543,US -3495884544,3495884551,RO -3495884552,3495884679,US -3495884680,3495884687,AU -3495884688,3495884719,US -3495884720,3495884735,CA -3495884736,3495896063,US +3495872512,3495881119,US +3495881120,3495881151,PA +3495881152,3495881471,US +3495881472,3495881727,PA +3495881728,3495896063,US 3495896064,3495897087,PR 3495897088,3495930879,US 3495930880,3495931903,CA @@ -108881,7 +112234,11 @@ 3496202304,3496205839,US 3496205840,3496205855,ID 3496205856,3496205871,CA -3496205872,3496296447,US +3496205872,3496220995,US +3496220996,3496220997,GB +3496220998,3496221014,US +3496221015,3496221016,GB +3496221017,3496296447,US 3496296448,3496312831,CA 3496312832,3496468479,US 3496468480,3496476671,CA @@ -109101,49 +112458,13 @@ 3497164288,3497164295,GB 3497164296,3497164799,US 3497164800,3497181183,CA -3497181184,3497222407,US -3497222408,3497222415,IN -3497222416,3497222463,US -3497222464,3497222479,IN -3497222480,3497223791,US -3497223792,3497223807,CH -3497223808,3497223839,US -3497223840,3497223871,CH -3497223872,3497223879,US -3497223880,3497223887,ID -3497223888,3497224255,US -3497224256,3497224319,IN -3497224320,3497224831,US -3497224832,3497224863,CH -3497224864,3497225375,US -3497225376,3497225383,CN -3497225384,3497225471,US -3497225472,3497225535,IN -3497225536,3497226295,US +3497181184,3497226295,US 3497226296,3497226303,SG 3497226304,3497226391,US 3497226392,3497226399,IR 3497226400,3497226687,US 3497226688,3497226719,GB -3497226720,3497226783,US -3497226784,3497226815,CH -3497226816,3497226831,US -3497226832,3497226847,CH -3497226848,3497226943,US -3497226944,3497226959,CH -3497226960,3497227023,US -3497227024,3497227039,GB -3497227040,3497227231,US -3497227232,3497227247,CH -3497227248,3497227255,CN -3497227256,3497227263,CH -3497227264,3497227391,US -3497227392,3497227407,CN -3497227408,3497227527,US -3497227528,3497227535,CN -3497227536,3497228079,US -3497228080,3497228087,CN -3497228088,3497233407,US +3497226720,3497233407,US 3497233408,3497233663,CN 3497233664,3497263815,US 3497263816,3497263823,GB @@ -109338,9 +112659,7 @@ 3502202648,3502202655,PR 3502202656,3502207535,US 3502207536,3502207543,PR -3502207544,3502418175,US -3502418176,3502418431,GU -3502418432,3502439167,US +3502207544,3502439167,US 3502439168,3502439423,PK 3502439424,3502470143,US 3502470144,3502471167,MX @@ -109352,9 +112671,7 @@ 3502545664,3502545919,BS 3502545920,3502683135,US 3502683136,3502683391,MC -3502683392,3502929663,US -3502929664,3502929919,GU -3502929920,3502993407,US +3502683392,3502993407,US 3502993408,3502993919,NL 3502993920,3503027327,US 3503027328,3503027359,GB @@ -109385,9 +112702,7 @@ 3503478784,3503479039,DE 3503479040,3503738879,US 3503738880,3503740927,CO -3503740928,3503757823,US -3503757824,3503758335,GU -3503758336,3503826087,US +3503740928,3503826087,US 3503826088,3503826095,PR 3503826096,3503890431,US 3503890432,3503894527,CO @@ -109403,9 +112718,7 @@ 3504207872,3504208127,CA 3504208128,3504223743,US 3504223744,3504223999,RO -3504224000,3504521215,US -3504521216,3504521727,GU -3504521728,3504889343,US +3504224000,3504889343,US 3504889344,3504889855,PK 3504889856,3504922623,US 3504922624,3504923391,PH @@ -109454,7 +112767,9 @@ 3506043136,3506044927,PA 3506044928,3506052543,US 3506052544,3506052559,DE -3506052560,3506135263,US +3506052560,3506058815,US +3506058816,3506058823,AF +3506058824,3506135263,US 3506135264,3506135295,GB 3506135296,3506177967,US 3506177968,3506177983,DE @@ -109478,9 +112793,7 @@ 3507025408,3507025663,IQ 3507025664,3507101919,US 3507101920,3507101935,IL -3507101936,3507134591,US -3507134592,3507134607,GB -3507134608,3507290111,US +3507101936,3507290111,US 3507290112,3507355647,AR 3507355648,3507479079,US 3507479080,3507479080,CA @@ -109488,12 +112801,12 @@ 3507479109,3507479109,CA 3507479110,3507482153,US 3507482154,3507482155,CA -3507482156,3507540015,US +3507482156,3507485103,US +3507485104,3507485119,CA +3507485120,3507540015,US 3507540016,3507540031,IN 3507540032,3507585023,US -3507585024,3507586623,CA -3507586624,3507586655,US -3507586656,3507598911,CA +3507585024,3507598911,CA 3507598912,3507598943,US 3507598944,3507601407,CA 3507601408,3507634335,US @@ -110249,27 +113562,19 @@ 3509775904,3509775919,AU 3509775920,3509775943,US 3509775944,3509775951,IT -3509775952,3509775975,US -3509775976,3509775983,GB -3509775984,3509776023,US +3509775952,3509776023,US 3509776024,3509776031,CA 3509776032,3509776047,US 3509776048,3509776055,SA 3509776056,3509776095,US 3509776096,3509776103,AU 3509776104,3509776111,US -3509776112,3509776127,IT -3509776128,3509776224,US -3509776225,3509776256,CA -3509776257,3509776288,TC -3509776289,3509776352,US -3509776353,3509776382,GB -3509776383,3509777159,US +3509776112,3509776119,IT +3509776120,3509777159,US 3509777160,3509777167,CN 3509777168,3509777175,RU -3509777176,3509777199,US -3509777200,3509777207,GB -3509777208,3509777215,CA +3509777176,3509777207,US +3509777208,3509777215,IN 3509777216,3509777223,TH 3509777224,3509777271,US 3509777272,3509777279,IT @@ -110283,9 +113588,7 @@ 3509778400,3509778431,NL 3509778432,3509778703,US 3509778704,3509778711,CA -3509778712,3509778847,US -3509778848,3509778855,CA -3509778856,3509778903,US +3509778712,3509778903,US 3509778904,3509778911,RU 3509778912,3509778919,US 3509778920,3509778927,GB @@ -110303,55 +113606,31 @@ 3509830408,3509830415,GB 3509830416,3509830943,US 3509830944,3509830951,BE -3509830952,3509831039,US -3509831040,3509831047,DE -3509831048,3509831135,US +3509830952,3509831135,US 3509831136,3509831143,IN -3509831144,3509831287,US -3509831288,3509831295,GB -3509831296,3509831303,US -3509831304,3509831311,CO -3509831312,3509831319,CN -3509831320,3509831535,US +3509831144,3509831535,US 3509831536,3509831551,LB 3509831552,3509831615,US 3509831616,3509831647,IL 3509831648,3509831735,US 3509831736,3509831743,AT -3509831744,3509831799,US -3509831800,3509831807,DO +3509831744,3509831807,US 3509831808,3509831815,IN 3509831816,3509831823,CA 3509831824,3509831831,US 3509831832,3509831839,GB -3509831840,3509831959,US -3509831960,3509831967,CA -3509831968,3509832079,US -3509832080,3509832087,CN -3509832088,3509833103,US +3509831840,3509833103,US 3509833104,3509833111,IN 3509833112,3509833535,US 3509833536,3509833543,CA 3509833544,3509833551,IN 3509833552,3509833567,US 3509833568,3509833599,PH -3509833600,3509833623,US -3509833624,3509833631,GR -3509833632,3509833703,US +3509833600,3509833703,US 3509833704,3509833711,ZA -3509833712,3509834095,US -3509834096,3509834103,IL -3509834104,3509834111,US +3509833712,3509834111,US 3509834112,3509834143,IL -3509834144,3509834167,US -3509834168,3509834175,BR -3509834176,3509834287,US -3509834288,3509834303,IN -3509834304,3509834399,US -3509834400,3509834407,BD -3509834408,3509834431,US -3509834432,3509834463,JP -3509834464,3509834495,US +3509834144,3509834495,US 3509834496,3509834503,NO 3509834504,3509834519,US 3509834520,3509834527,BD @@ -110361,9 +113640,7 @@ 3509834832,3509834847,CO 3509834848,3509835103,US 3509835104,3509835111,GB -3509835112,3509836375,US -3509836376,3509836383,GR -3509836384,3509837167,US +3509835112,3509837167,US 3509837168,3509837175,GB 3509837176,3509837623,US 3509837624,3509837639,GB @@ -110826,7 +114103,11 @@ 3510897443,3510897443,IE 3510897444,3510935551,US 3510935552,3510943743,CA -3510943744,3511140351,US +3510943744,3511129087,US +3511129088,3511129183,CA +3511129184,3511129199,US +3511129200,3511131135,CA +3511131136,3511132159,US 3511140352,3511156735,CA 3511156736,3511331199,US 3511331200,3511331231,CA @@ -110852,9 +114133,7 @@ 3512011904,3512012095,US 3512012096,3512012159,GB 3512012160,3512012175,MX -3512012176,3512012191,US -3512012192,3512012223,BR -3512012224,3512012255,US +3512012176,3512012255,US 3512012256,3512012287,GB 3512012288,3512013583,US 3512013584,3512013599,CA @@ -111459,8 +114738,8 @@ 3512695840,3512695871,GB 3512695872,3512696831,US 3512696832,3512699647,SE -3512699648,3512701951,US -3512701952,3512705023,SE +3512699648,3512699903,US +3512699904,3512705023,SE 3512705024,3512844287,US 3512844288,3512844543,CA 3512844544,3512844607,A1 @@ -111535,66 +114814,16 @@ 3514590720,3514591103,SV 3514591104,3514591487,US 3514591488,3514592255,NI -3514592256,3514597375,SV -3514597376,3514763423,US -3514763424,3514763439,PA -3514763440,3514763711,US -3514763712,3514763727,VE -3514763728,3514763775,US -3514763776,3514763791,PA -3514763792,3514764047,US -3514764048,3514764063,PA -3514764064,3514765823,US -3514765824,3514765855,PA -3514765856,3514765919,US -3514765920,3514765951,VE -3514765952,3514766111,US -3514766112,3514766143,VE -3514766144,3514766207,US -3514766208,3514766271,PA -3514766272,3514766303,US -3514766304,3514766335,PA -3514766336,3514766463,US -3514766464,3514766495,PA -3514766496,3514766879,US -3514766880,3514766911,PA -3514766912,3514767199,US -3514767200,3514767231,VE -3514767232,3514767455,US -3514767456,3514767487,VE -3514767488,3514768127,US -3514768128,3514768191,VE -3514768192,3514769023,US -3514769024,3514769151,PA -3514769152,3514769215,US -3514769216,3514769279,PA -3514769280,3514775295,US -3514775296,3514775551,PA -3514775552,3514776063,US -3514776064,3514776319,VE -3514776320,3514776343,US -3514776344,3514776351,VE -3514776352,3514776407,US -3514776408,3514776415,VE -3514776416,3514781695,US -3514781696,3514782719,VE -3514782720,3514787583,US -3514787584,3514787839,PA -3514787840,3514791679,US -3514791680,3514793983,PA -3514793984,3514826751,US +3514592256,3514593279,SV +3514593280,3514596863,US +3514596864,3514597375,SV +3514597376,3514826751,US 3514826752,3514843135,CA 3514843136,3515114247,US 3515114248,3515114255,AU 3515114256,3515149567,US 3515149568,3515149583,AU -3515149584,3515154943,US -3515154944,3515155199,CA -3515155200,3515155455,US -3515155456,3515155711,CA -3515155712,3515166719,US -3515166720,3515166975,CA -3515166976,3515170991,US +3515149584,3515170991,US 3515170992,3515170999,KR 3515171000,3515185151,US 3515185152,3515185407,CA @@ -111604,9 +114833,7 @@ 3515358976,3515359231,MX 3515359232,3515452639,US 3515452640,3515452655,KR -3515452656,3515452775,US -3515452776,3515452783,JP -3515452784,3515453055,US +3515452656,3515453055,US 3515453056,3515453071,JP 3515453072,3515453679,US 3515453680,3515453687,JP @@ -111615,9 +114842,7 @@ 3515454080,3515454095,US 3515454096,3515454111,JP 3515454112,3515454143,US -3515454144,3515454159,JP -3515454160,3515454167,US -3515454168,3515454207,JP +3515454144,3515454207,JP 3515454208,3515454399,US 3515454400,3515454463,JP 3515454464,3515455311,US @@ -111725,9 +114950,7 @@ 3517116416,3517120511,CA 3517120512,3517233151,US 3517233152,3517235199,GU -3517235200,3517308927,US -3517308928,3517313023,CA -3517313024,3517382655,US +3517235200,3517382655,US 3517382656,3517383679,CA 3517383680,3517383935,US 3517383936,3517384447,CA @@ -112022,25 +115245,27 @@ 3517546496,3517562879,CA 3517562880,3517596671,US 3517596672,3517596927,NO -3517596928,3517597183,SE +3517596928,3517597183,IE 3517597184,3517597695,US 3517597696,3517598207,SE 3517598208,3517598463,IE 3517598464,3517598591,SE 3517598592,3517599231,US -3517599232,3517600767,SE +3517599232,3517599263,BG +3517599264,3517600767,SE 3517600768,3517601279,US 3517601280,3517602047,SE 3517602048,3517602303,DE 3517602304,3517602559,US 3517602560,3517602623,SE 3517602624,3517602815,US -3517602816,3517603071,SE -3517603072,3517603615,US +3517602816,3517603327,SE +3517603328,3517603615,US 3517603616,3517603647,DE -3517603648,3517603839,US -3517603840,3517603903,SE -3517603904,3517603967,MA +3517603648,3517603711,US +3517603712,3517603775,SE +3517603776,3517603839,US +3517603840,3517603967,SE 3517603968,3517604031,DE 3517604032,3517604095,SE 3517604096,3517604351,US @@ -112062,8 +115287,8 @@ 3517609856,3517610047,US 3517610048,3517610191,SE 3517610192,3517610199,US -3517610200,3517610207,SE -3517610208,3517610495,US +3517610200,3517610239,SE +3517610240,3517610495,US 3517610496,3517611263,IE 3517611264,3517611295,SE 3517611296,3517611303,US @@ -112102,7 +115327,8 @@ 3518076672,3518076927,PA 3518076928,3518077103,US 3518077104,3518077111,GB -3518077112,3518374719,US +3518077112,3518078975,US +3518083072,3518374719,US 3518374720,3518374783,IN 3518374784,3518380223,US 3518380224,3518380287,DE @@ -112123,95 +115349,51 @@ 3518759408,3518759423,CY 3518759424,3518760511,US 3518760512,3518760575,AU -3518760576,3518760703,HU +3518760576,3518760647,HU +3518760648,3518760655,US +3518760656,3518760703,HU 3518760704,3518762495,US 3518762496,3518762751,GB -3518762752,3518764047,US -3518764048,3518764223,GB -3518764224,3518764671,US +3518762752,3518764671,US 3518764672,3518764703,NL 3518764704,3518765311,US 3518765312,3518765567,CA 3518765568,3518766879,US 3518766880,3518766911,TH -3518766912,3518890831,US -3518890832,3518890839,IT -3518890840,3518891175,US -3518891176,3518891183,GB -3518891184,3518891767,US -3518891768,3518891775,BG -3518891776,3518892039,US -3518892040,3518892047,GT -3518892048,3518892223,US +3518766912,3518892223,US 3518892224,3518892231,CL 3518892232,3518892415,US 3518892416,3518892423,GB -3518892424,3518894095,US -3518894096,3518894103,KW -3518894104,3518894343,US -3518894344,3518894351,MY -3518894352,3518894439,US +3518892424,3518894439,US 3518894440,3518894447,TR -3518894448,3518895719,US -3518895720,3518895727,PH -3518895728,3518895775,US +3518894448,3518895775,US 3518895776,3518895783,CA 3518895784,3518895791,TH -3518895792,3518895799,US -3518895800,3518895807,AR -3518895808,3518896215,US +3518895792,3518896215,US 3518896216,3518896223,CA 3518896224,3518896231,US 3518896232,3518896239,CN -3518896240,3518896519,US -3518896520,3518896527,AE -3518896528,3518896543,US -3518896544,3518896551,BD -3518896552,3518896895,US +3518896240,3518896895,US 3518896896,3518896903,GB -3518896904,3518897071,US -3518897072,3518897079,IT -3518897080,3518897119,US +3518896904,3518897119,US 3518897120,3518897127,IT -3518897128,3518897423,US -3518897424,3518897431,IN -3518897432,3518897879,US -3518897880,3518897887,AM -3518897888,3518898015,US -3518898016,3518898023,IN -3518898024,3518898143,US +3518897128,3518898143,US 3518898144,3518898151,BR -3518898152,3518898167,US -3518898168,3518898175,RO -3518898176,3518903175,US -3518903176,3518903183,BR -3518903184,3518903191,US +3518898152,3518903191,US 3518903192,3518903199,JP -3518903200,3518903399,US -3518903400,3518903407,PK -3518903408,3518903871,US +3518903200,3518903871,US 3518903872,3518903879,PK 3518903880,3518903927,US 3518903928,3518903935,RU -3518903936,3518903959,US -3518903960,3518903967,GB -3518903968,3518903999,US -3518904000,3518904007,ES -3518904008,3518904015,US +3518903936,3518904015,US 3518904016,3518904031,EG 3518904032,3518911743,US 3518911744,3518911999,GB 3518912000,3518912511,US 3518912512,3518912767,IN -3518912768,3518919031,US -3518919032,3518919039,GT -3518919040,3518919095,US -3518919096,3518919103,BD -3518919104,3518921447,US +3518912768,3518921447,US 3518921448,3518921455,CN -3518921456,3518921479,US -3518921480,3518921487,BD -3518921488,3518929535,US +3518921456,3518929535,US 3518929536,3518929599,CA 3518929600,3518995695,US 3518995696,3518995703,GB @@ -112230,9 +115412,7 @@ 3519352904,3519381503,US 3519381504,3519397887,CA 3519397888,3519406079,US -3519406080,3519406111,IT -3519406112,3519406127,US -3519406128,3519406143,DE +3519406080,3519406143,IT 3519406144,3519406207,US 3519406208,3519406215,SA 3519406216,3519406255,US @@ -112295,9 +115475,7 @@ 3519411392,3519411711,US 3519411712,3519411967,AR 3519411968,3519412223,DE -3519412224,3519412463,US -3519412464,3519412479,GB -3519412480,3519412519,US +3519412224,3519412519,US 3519412520,3519412527,RU 3519412528,3519412735,US 3519412736,3519412751,RU @@ -112307,42 +115485,15 @@ 3519413760,3519414271,CA 3519414272,3519417087,US 3519417088,3519417151,IT -3519417152,3519417215,DE -3519417216,3519420767,US +3519417152,3519417183,DE +3519417184,3519420767,US 3519420768,3519420775,HK 3519420776,3519422495,US 3519422496,3519422527,CA 3519422528,3519475711,US 3519475712,3519476223,BH 3519476224,3519477759,A2 -3519477760,3519566871,US -3519566872,3519566879,IE -3519566880,3519566943,US -3519566944,3519566951,GB -3519566952,3519567087,US -3519567088,3519567096,IE -3519567097,3519567679,US -3519567680,3519567687,GB -3519567688,3519567727,US -3519567728,3519567735,LB -3519567736,3519567759,US -3519567760,3519567767,JP -3519567768,3519567831,US -3519567832,3519567863,LB -3519567864,3519568911,US -3519568912,3519568919,FR -3519568920,3519568927,LB -3519568928,3519568991,US -3519568992,3519568999,GB -3519569000,3519569071,US -3519569072,3519569079,LB -3519569080,3519569103,US -3519569104,3519569111,GB -3519569112,3519569127,US -3519569128,3519569135,GB -3519569136,3519569727,US -3519569728,3519569735,JP -3519569736,3519578367,US +3519477760,3519578367,US 3519578368,3519578623,NA 3519578624,3519578879,US 3519578880,3519579135,CA @@ -112376,8 +115527,7 @@ 3519590912,3519590927,GB 3519590928,3519590943,EE 3519590944,3519590959,AG -3519590960,3519591055,US -3519591056,3519591071,MT +3519590960,3519591071,US 3519591072,3519591087,IM 3519591088,3519591167,US 3519591168,3519591423,GB @@ -112766,15 +115916,13 @@ 3520937984,3520954367,CA 3520954368,3520956155,US 3520956156,3520956159,CH -3520956160,3520958783,US -3520958784,3520958847,CA -3520958848,3520966111,US -3520966112,3520966119,CA -3520966120,3520978943,US +3520956160,3520978943,US 3520978944,3520979711,BZ 3520979712,3520999423,US 3520999424,3521003519,CA -3521003520,3521007103,US +3521003520,3521003583,US +3521003584,3521003647,IL +3521003648,3521007103,US 3521007104,3521007111,IN 3521007112,3521011743,US 3521011744,3521011751,PK @@ -112787,9 +115935,7 @@ 3521013560,3521013567,GB 3521013568,3521013951,US 3521013952,3521013959,AU -3521013960,3521014103,US -3521014104,3521014111,NL -3521014112,3521014127,US +3521013960,3521014127,US 3521014128,3521014135,GR 3521014136,3521014143,CA 3521014144,3521028095,US @@ -112851,10 +115997,8 @@ 3521835904,3521835967,CA 3521835968,3521836351,US 3521836352,3521836415,IL -3521836416,3521836503,US -3521836504,3521836511,IL -3521836512,3521836687,US -3521836688,3521836703,CA +3521836416,3521836687,US +3521836688,3521836703,GB 3521836704,3521904639,US 3521904640,3521921023,JM 3521921024,3521933321,US @@ -112923,26 +116067,19 @@ 3522121216,3522121471,US 3522121472,3522121983,LY 3522121984,3522122239,AW -3522122240,3522131455,US -3522131456,3522131487,PE -3522131488,3522131519,RS -3522131520,3522131711,US +3522122240,3522131711,US 3522131712,3522131743,GB 3522131744,3522131775,DE 3522131776,3522131807,BR 3522131808,3522132479,US 3522132480,3522132543,CO -3522132544,3522132575,TR +3522132544,3522132575,US 3522132576,3522132607,UA 3522132608,3522132639,CA -3522132640,3522132671,PE +3522132640,3522132671,BO 3522132672,3522132703,BR 3522132704,3522132735,LK -3522132736,3522132767,US -3522132768,3522132799,RO -3522132800,3522133567,US -3522133568,3522133568,PT -3522133569,3522133599,US +3522132736,3522133599,US 3522133600,3522133631,JP 3522133632,3522133639,US 3522133640,3522133647,DE @@ -112959,15 +116096,7 @@ 3522759592,3522759599,CA 3522759600,3522763263,US 3522763264,3522763519,CA -3522763520,3522768895,US -3522768896,3522769151,CA -3522769152,3522769919,US -3522769920,3522770175,CA -3522770176,3522807807,US -3522807808,3522807815,JP -3522807816,3522820863,US -3522820864,3522821119,CA -3522821120,3522854911,US +3522763520,3522854911,US 3522854912,3522859999,CA 3522860000,3522860031,IN 3522860032,3522871295,CA @@ -113384,9 +116513,7 @@ 3556769792,3556774399,DE 3556774400,3556786175,EU 3556786176,3556794367,RU -3556794368,3556795647,ES -3556795648,3556795679,IT -3556795680,3556797767,ES +3556794368,3556797767,ES 3556797768,3556797775,GB 3556797776,3556797839,ES 3556797840,3556797847,PT @@ -113513,7 +116640,9 @@ 3557244928,3557253119,IT 3557253120,3557261311,RU 3557261312,3557277695,DE -3557277696,3557285887,NL +3557277696,3557280334,NL +3557280335,3557280336,IN +3557280337,3557285887,NL 3557285888,3557294079,RU 3557294080,3557302271,DE 3557302272,3557310463,UA @@ -113553,8 +116682,8 @@ 3557341552,3557341559,EU 3557341560,3557341567,BE 3557341568,3557341663,EU -3557341664,3557341679,BE -3557341680,3557341951,EU +3557341664,3557341695,BE +3557341696,3557341951,EU 3557341952,3557342479,BE 3557342480,3557342495,EU 3557342496,3557342511,BE @@ -113586,8 +116715,8 @@ 3557360624,3557360639,JE 3557360640,3557360680,GB 3557360681,3557360687,JE -3557360688,3557360807,GB -3557360808,3557360895,JE +3557360688,3557360815,GB +3557360816,3557360895,JE 3557360896,3557360927,GB 3557360928,3557360943,JE 3557360944,3557360959,GB @@ -113615,7 +116744,11 @@ 3557363456,3557363471,GB 3557363472,3557363479,JE 3557363480,3557363655,GB -3557363656,3557363783,JE +3557363656,3557363663,JE +3557363664,3557363671,GB +3557363672,3557363679,JE +3557363680,3557363687,GB +3557363688,3557363783,JE 3557363784,3557363791,GB 3557363792,3557364223,JE 3557364224,3557364479,GB @@ -113638,14 +116771,14 @@ 3557364896,3557364927,JE 3557364928,3557364959,GB 3557364960,3557364991,JE -3557364992,3557365055,GB -3557365056,3557365103,JE +3557364992,3557365087,GB +3557365088,3557365103,JE 3557365104,3557365111,GB 3557365112,3557365119,JE 3557365120,3557365183,GB 3557365184,3557365247,JE -3557365248,3557365407,GB -3557365408,3557365503,JE +3557365248,3557365423,GB +3557365424,3557365503,JE 3557365504,3557365511,GB 3557365512,3557365519,JE 3557365520,3557365551,GB @@ -113736,23 +116869,21 @@ 3557834752,3557842943,IR 3557842944,3557851135,FI 3557851136,3557859327,HU -3557859328,3557867519,SE +3557859328,3557860831,SE +3557860832,3557860847,FI +3557860848,3557867519,SE 3557867520,3557875711,RU 3557875712,3557883903,DE 3557883904,3557892095,RU 3557892096,3557900287,IE 3557900288,3557916671,AT 3557916672,3557924863,NO -3557924864,3557933055,AX +3557924864,3557933055,FI 3557933056,3557941247,IT 3557941248,3557945183,DE 3557945184,3557945199,GB 3557945200,3557957631,DE -3557957632,3557960975,SI -3557960976,3557960983,AE -3557960984,3557961375,SI -3557961376,3557961407,AE -3557961408,3557965823,SI +3557957632,3557965823,SI 3557965824,3557974015,DE 3557974016,3557982207,CH 3557982208,3557990399,NO @@ -113761,7 +116892,13 @@ 3558006784,3558014975,GB 3558014976,3558023167,RU 3558023168,3558023199,GB -3558023200,3558030655,DE +3558023200,3558023343,DE +3558023344,3558023359,GB +3558023360,3558024383,DE +3558024384,3558024415,GB +3558024416,3558028063,DE +3558028064,3558028071,CH +3558028072,3558030655,DE 3558030656,3558030659,CH 3558030660,3558031359,DE 3558031360,3558039551,GB @@ -113859,15 +116996,14 @@ 3558288424,3558288447,GB 3558288448,3558288483,US 3558288484,3558288487,GB -3558288488,3558288495,GU -3558288496,3558288639,US +3558288488,3558288639,US 3558288640,3558288671,BE 3558288672,3558288687,DE 3558288688,3558288703,BE 3558288704,3558288719,GB 3558288720,3558288895,BE -3558288896,3558289103,FR -3558289104,3558289119,GB +3558288896,3558289111,FR +3558289112,3558289119,GB 3558289120,3558289151,FR 3558289152,3558289407,GB 3558289408,3558289663,NL @@ -113909,11 +117045,11 @@ 3558292288,3558292543,NL 3558292544,3558292607,GB 3558292608,3558292735,NL -3558292736,3558292871,GB -3558292872,3558292879,NL -3558292880,3558292895,GB -3558292896,3558293087,NL -3558293088,3558293247,GB +3558292736,3558292863,GB +3558292864,3558293143,NL +3558293144,3558293151,GB +3558293152,3558293199,NL +3558293200,3558293247,GB 3558293248,3558293503,NL 3558293504,3558301695,RU 3558301696,3558310319,DE @@ -114031,13 +117167,11 @@ 3558719488,3558735871,IL 3558735872,3558736127,GB 3558736128,3558736639,GG -3558736640,3558737023,GB -3558737024,3558737151,GG +3558736640,3558737055,GB +3558737056,3558737151,GG 3558737152,3558737279,GB 3558737280,3558737919,GG -3558737920,3558738431,GB -3558738432,3558738687,GG -3558738688,3558738751,GB +3558737920,3558738751,GB 3558738752,3558738943,GG 3558738944,3558738991,GB 3558738992,3558739007,GG @@ -114247,7 +117381,8 @@ 3559006208,3559014399,RU 3559014400,3559016191,DE 3559016192,3559016207,GB -3559016208,3559022591,DE +3559016208,3559016215,JP +3559016216,3559022591,DE 3559022592,3559030783,RU 3559030784,3559038720,ES 3559038721,3559038975,US @@ -114268,13 +117403,11 @@ 3559088376,3559088379,GB 3559088380,3559089023,BE 3559089024,3559089027,GB -3559089028,3559089055,BE -3559089056,3559089063,DE -3559089064,3559089407,BE +3559089028,3559089351,BE +3559089352,3559089359,GB +3559089360,3559089407,BE 3559089408,3559089411,GB -3559089412,3559089423,BE -3559089424,3559089427,GB -3559089428,3559089439,BE +3559089412,3559089439,BE 3559089440,3559089443,GB 3559089444,3559089447,BE 3559089448,3559089451,GB @@ -114293,11 +117426,15 @@ 3559089656,3559089659,GB 3559089660,3559090071,BE 3559090072,3559090079,NL -3559090080,3559090439,BE +3559090080,3559090127,BE +3559090128,3559090135,GB +3559090136,3559090439,BE 3559090440,3559090443,GB 3559090444,3559090463,BE 3559090464,3559090467,GB -3559090468,3559090483,BE +3559090468,3559090471,BE +3559090472,3559090479,GB +3559090480,3559090483,BE 3559090484,3559090487,GB 3559090488,3559090587,BE 3559090588,3559090591,GB @@ -114307,7 +117444,9 @@ 3559090776,3559090779,GB 3559090780,3559090803,BE 3559090804,3559090807,GB -3559090808,3559090863,BE +3559090808,3559090831,BE +3559090832,3559090839,GB +3559090840,3559090863,BE 3559090864,3559090871,GB 3559090872,3559090895,BE 3559090896,3559090899,GB @@ -114325,9 +117464,13 @@ 3559091204,3559091207,GB 3559091208,3559091211,BE 3559091212,3559091215,GB -3559091216,3559091423,BE +3559091216,3559091223,BE +3559091224,3559091231,GB +3559091232,3559091423,BE 3559091424,3559091427,GB -3559091428,3559091507,BE +3559091428,3559091439,BE +3559091440,3559091447,ES +3559091448,3559091507,BE 3559091508,3559091511,GB 3559091512,3559091535,BE 3559091536,3559091543,GB @@ -114337,16 +117480,22 @@ 3559091592,3559091615,GB 3559091616,3559091631,BE 3559091632,3559091639,LU -3559091640,3559092159,BE +3559091640,3559091855,BE +3559091856,3559091863,GB +3559091864,3559092159,BE 3559092160,3559092160,GB 3559092161,3559092222,BE 3559092223,3559092223,GB -3559092224,3559092735,BE +3559092224,3559092295,BE +3559092296,3559092303,GB +3559092304,3559092399,BE +3559092400,3559092407,GB +3559092408,3559092735,BE 3559092736,3559092739,GB 3559092740,3559092799,BE 3559092800,3559092803,GB -3559092804,3559092855,BE -3559092856,3559092863,GB +3559092804,3559092847,BE +3559092848,3559092863,GB 3559092864,3559092871,BE 3559092872,3559092895,GB 3559092896,3559092939,BE @@ -114358,7 +117507,9 @@ 3559093000,3559093007,BE 3559093008,3559093015,GB 3559093016,3559093023,FR -3559093024,3559093063,BE +3559093024,3559093047,BE +3559093048,3559093055,GB +3559093056,3559093063,BE 3559093064,3559093071,FR 3559093072,3559093075,BE 3559093076,3559093079,GB @@ -114415,7 +117566,8 @@ 3559094320,3559094335,GB 3559094336,3559094423,BE 3559094424,3559094447,GB -3559094448,3559094527,BE +3559094448,3559094455,ES +3559094456,3559094527,BE 3559094528,3559095039,GB 3559095040,3559095055,BE 3559095056,3559095063,GB @@ -114449,7 +117601,6 @@ 3559096320,3559103231,RO 3559103232,3559103487,GB 3559103488,3559104511,RO -3559104512,3559112703,UA 3559112704,3559120895,IT 3559120896,3559129087,GB 3559129088,3559137279,BG @@ -114502,7 +117653,6 @@ 3559186432,3559194623,RU 3559194624,3559202815,SE 3559202816,3559211007,DE -3559211008,3559219199,GR 3559219200,3559227391,SE 3559227392,3559235583,DK 3559235584,3559243775,DE @@ -114558,14 +117708,18 @@ 3559491440,3559491455,ES 3559491456,3559491647,NL 3559491648,3559491711,ES -3559491712,3559491839,NL +3559491712,3559491727,NL +3559491728,3559491735,ES +3559491736,3559491839,NL 3559491840,3559491871,ES 3559491872,3559491903,GB 3559491904,3559491967,ES 3559491968,3559492003,NL 3559492004,3559492007,ES 3559492008,3559492013,NL -3559492014,3559492031,ES +3559492014,3559492015,ES +3559492016,3559492023,NL +3559492024,3559492031,ES 3559492032,3559493151,NL 3559493152,3559493167,ES 3559493168,3559493247,NL @@ -114589,7 +117743,19 @@ 3559586304,3559587839,DE 3559587840,3559596031,KW 3559596032,3559604223,BG -3559604224,3559612415,DE +3559604224,3559607983,DE +3559607984,3559607999,LU +3559608000,3559608079,DE +3559608080,3559608095,LU +3559608096,3559608135,DE +3559608136,3559608143,LU +3559608144,3559611135,DE +3559611136,3559611391,GB +3559611392,3559611583,DE +3559611584,3559611647,LU +3559611648,3559611731,DE +3559611732,3559611735,NL +3559611736,3559612415,DE 3559612416,3559620607,IT 3559620608,3559628799,CH 3559628800,3559636991,GB @@ -114682,15 +117848,15 @@ 3559902176,3559902187,EE 3559902188,3559902191,UA 3559902192,3559902207,EE -3559902208,3559902623,UA -3559902624,3559902631,EE -3559902632,3559902975,UA +3559902208,3559902975,UA 3559902976,3559903231,EE -3559903232,3559903743,UA +3559903232,3559903487,UA +3559903488,3559903551,EE +3559903552,3559903743,UA 3559903744,3559904023,EE 3559904024,3559904255,UA -3559904256,3559904383,EE -3559904384,3559904607,UA +3559904256,3559904511,EE +3559904512,3559904607,UA 3559904608,3559904639,EE 3559904640,3559905019,UA 3559905020,3559905031,EE @@ -114700,20 +117866,24 @@ 3559905144,3559905151,UA 3559905152,3559905155,EE 3559905156,3559905159,UA -3559905160,3559905247,EE +3559905160,3559905225,EE +3559905226,3559905231,UA +3559905232,3559905247,EE 3559905248,3559905255,UA 3559905256,3559905297,EE 3559905298,3559905299,UA -3559905300,3559905307,EE -3559905308,3559905535,UA +3559905300,3559905317,EE +3559905318,3559905319,LT +3559905320,3559905323,EE +3559905324,3559905535,UA 3559905536,3559905623,EE 3559905624,3559905631,UA -3559905632,3559905951,EE -3559905952,3559905983,UA +3559905632,3559905975,EE +3559905976,3559905983,UA 3559905984,3559906257,EE -3559906258,3559906263,UA -3559906264,3559906783,EE -3559906784,3559906815,UA +3559906258,3559906259,UA +3559906260,3559906799,EE +3559906800,3559906815,UA 3559906816,3559906975,EE 3559906976,3559907071,UA 3559907072,3559907327,EE @@ -114773,7 +117943,7 @@ 3560316928,3560325119,NL 3560325120,3560333311,DK 3560333312,3560341503,RO -3560349696,3560357887,GB +3560341504,3560357887,GB 3560357888,3560366079,GR 3560366080,3560366687,CH 3560366688,3560366695,IT @@ -114832,9 +118002,7 @@ 3560742632,3560742911,DE 3560742912,3560751103,AT 3560751104,3560767487,DE -3560767488,3560832255,NL -3560832256,3560832511,GB -3560832512,3560832791,NL +3560767488,3560832791,NL 3560832792,3560832799,BE 3560832800,3560833023,NL 3560833024,3560841215,GB @@ -115606,7 +118774,7 @@ 3560943160,3560943160,NO 3560943161,3560943161,BE 3560943162,3560943162,GR -3560943163,3560943163,CH +3560943163,3560943163,DE 3560943164,3560943164,PL 3560943165,3560943165,FR 3560943166,3560943166,GB @@ -116091,7 +119259,7 @@ 3560943761,3560943761,GB 3560943762,3560943762,IT 3560943763,3560943763,FR -3560943764,3560943764,PL +3560943764,3560943764,DE 3560943765,3560943765,SE 3560943766,3560943766,CY 3560943767,3560943768,DE @@ -116762,9 +119930,7 @@ 3560947044,3560947067,US 3560947068,3560947071,AR 3560947072,3560947075,BR -3560947076,3560947087,US -3560947088,3560947091,PR -3560947092,3560947095,US +3560947076,3560947095,US 3560947096,3560947099,MX 3560947100,3560947107,US 3560947108,3560947111,DE @@ -116772,8 +119938,7 @@ 3560947124,3560947127,CO 3560947128,3560947143,US 3560947144,3560947147,DE -3560947148,3560947151,PR -3560947152,3560947159,US +3560947148,3560947159,US 3560947160,3560947163,PR 3560947164,3560947191,US 3560947192,3560947195,VE @@ -116823,7 +119988,8 @@ 3560947688,3560947711,JP 3560947712,3560950839,SE 3560950840,3560950843,CZ -3560950844,3560950863,SE +3560950844,3560950847,FI +3560950848,3560950863,SE 3560950864,3560950867,DK 3560950868,3560950871,ES 3560950872,3560950956,SE @@ -116832,7 +119998,9 @@ 3560951028,3560951031,DK 3560951032,3560951039,SE 3560951040,3560951043,NO -3560951044,3560951088,SE +3560951044,3560951083,SE +3560951084,3560951087,DK +3560951088,3560951088,SE 3560951089,3560951090,PL 3560951091,3560951091,SE 3560951092,3560951095,IT @@ -116840,9 +120008,12 @@ 3560951104,3560951107,DE 3560951108,3560951111,DK 3560951112,3560951115,FR -3560951116,3560951195,SE +3560951116,3560951119,SE +3560951120,3560951123,CZ +3560951124,3560951195,SE 3560951196,3560951199,DK -3560951200,3560951207,SE +3560951200,3560951203,SE +3560951204,3560951207,AE 3560951208,3560951211,DK 3560951212,3560951215,IT 3560951216,3560951307,SE @@ -116879,7 +120050,10 @@ 3560951596,3560951599,CZ 3560951600,3560951679,SE 3560951680,3560951683,DE -3560951684,3560951807,SE +3560951684,3560951759,SE +3560951760,3560951763,DK +3560951764,3560951767,HU +3560951768,3560951807,SE 3560951808,3560951811,US 3560951812,3560951816,SE 3560951817,3560951818,ES @@ -117072,10 +120246,12 @@ 3561610240,3561610495,US 3561610496,3561610527,FR 3561610528,3561610719,GB -3561610720,3561611295,FR -3561611296,3561611559,GB +3561610720,3561611311,FR +3561611312,3561611559,GB 3561611560,3561611567,FR -3561611568,3561614175,GB +3561611568,3561612287,GB +3561612288,3561612415,FR +3561612416,3561614175,GB 3561614176,3561614199,FR 3561614200,3561614335,GB 3561614336,3561614591,FR @@ -117196,8 +120372,8 @@ 3561929856,3561929879,GB 3561929880,3561929919,NL 3561929920,3561929967,GB -3561929968,3561930335,NL -3561930336,3561930495,GB +3561929968,3561930239,NL +3561930240,3561930495,GB 3561930496,3561930511,NL 3561930512,3561930519,BE 3561930520,3561930527,FR @@ -117220,6 +120396,7 @@ 3561963144,3561963151,AU 3561963152,3561963519,DE 3561963520,3561971711,BE +3561971712,3561975807,CZ 3561975808,3561979903,UA 3561979904,3561988095,ES 3561988096,3562004479,DE @@ -117494,6 +120671,7 @@ 3562651648,3562659839,DE 3562659840,3562668031,SK 3562668032,3562676223,IT +3562676224,3562684415,UA 3562684416,3562692607,FI 3562692608,3562695375,UA 3562695376,3562695379,CZ @@ -117566,9 +120744,7 @@ 3563028480,3563036671,IR 3563036672,3563044863,BG 3563044864,3563053055,ES -3563053056,3563053503,GB -3563053504,3563053527,US -3563053528,3563061247,GB +3563053056,3563061247,GB 3563061248,3563061759,GH 3563061760,3563062527,NG 3563062528,3563067391,GH @@ -117579,7 +120755,7 @@ 3563068416,3563069183,NG 3563069184,3563069439,GH 3563069440,3563077631,HU -3563077632,3563085823,FR +3563077632,3563085823,SE 3563085824,3563094015,RU 3563094016,3563096255,DE 3563096256,3563096287,GB @@ -117802,8 +120978,8 @@ 3563851024,3563851135,ES 3563851136,3563851839,NL 3563851840,3563851903,ES -3563851904,3563851967,NL -3563851968,3563852095,ES +3563851904,3563852031,NL +3563852032,3563852095,ES 3563852096,3563852191,NL 3563852192,3563852207,GB 3563852208,3563852216,NL @@ -117859,9 +121035,7 @@ 3564024136,3564024143,IT 3564024144,3564024447,GB 3564024448,3564024463,IT -3564024464,3564024671,GB -3564024672,3564024783,IT -3564024784,3564027903,GB +3564024464,3564027903,GB 3564027904,3564041215,DE 3564041216,3564041727,RU 3564041728,3564044287,DE @@ -117903,7 +121077,9 @@ 3564185344,3564191743,UA 3564191744,3564199935,BE 3564199936,3564208127,RU -3564208128,3564216319,GB +3564208128,3564212735,GB +3564212736,3564213007,IE +3564213008,3564216319,GB 3564216320,3564224511,PT 3564224512,3564232703,GB 3564232704,3564240895,RU @@ -118059,9 +121235,7 @@ 3564363776,3564371967,UA 3564371968,3564380159,DE 3564380160,3564388351,FI -3564388352,3564392959,SE -3564392960,3564393087,NO -3564393088,3564396543,SE +3564388352,3564396543,SE 3564396544,3564404735,RU 3564404736,3564412927,BG 3564412928,3564421119,IL @@ -118144,7 +121318,9 @@ 3564560392,3564560399,CA 3564560400,3564560415,US 3564560416,3564560511,GB -3564560512,3564560607,US +3564560512,3564560527,US +3564560528,3564560543,GB +3564560544,3564560607,US 3564560608,3564560927,GB 3564560928,3564560959,US 3564560960,3564561039,GB @@ -118251,13 +121427,15 @@ 3564699648,3564716031,GB 3564716032,3564724223,IT 3564724224,3564732415,NL -3564732416,3564734287,DE +3564732416,3564733183,DE +3564733184,3564733439,GB +3564733440,3564734287,DE 3564734288,3564734303,GB 3564734304,3564734399,DE 3564734400,3564734431,GB 3564734432,3564734815,DE -3564734816,3564734819,GB -3564734820,3564734847,DE +3564734816,3564734823,GB +3564734824,3564734847,DE 3564734848,3564734975,GB 3564734976,3564736511,DE 3564736512,3564736527,GB @@ -118327,8 +121505,8 @@ 3564881160,3564881199,GB 3564881200,3564881203,FR 3564881204,3564881231,GB -3564881232,3564881263,NL -3564881264,3564881343,GB +3564881232,3564881247,NL +3564881248,3564881343,GB 3564881344,3564881359,NL 3564881360,3564881375,GB 3564881376,3564881439,NL @@ -118354,8 +121532,8 @@ 3564882144,3564882239,NL 3564882240,3564882255,GB 3564882256,3564882271,NL -3564882272,3564882399,GB -3564882400,3564882943,NL +3564882272,3564882431,GB +3564882432,3564882943,NL 3564882944,3564883007,GB 3564883008,3564883039,NL 3564883040,3564883071,GB @@ -118384,9 +121562,7 @@ 3564884560,3564884567,NL 3564884568,3564884735,GB 3564884736,3564885039,NL -3564885040,3564885087,GB -3564885088,3564885119,NL -3564885120,3564885215,GB +3564885040,3564885215,GB 3564885216,3564885343,NL 3564885344,3564885359,GB 3564885360,3564885367,NL @@ -118409,7 +121585,9 @@ 3564885776,3564885791,GB 3564885792,3564885799,NL 3564885800,3564885839,GB -3564885840,3564885887,NL +3564885840,3564885855,NL +3564885856,3564885871,GB +3564885872,3564885887,NL 3564885888,3564885919,GB 3564885920,3564885935,NL 3564885936,3564885951,GB @@ -118533,8 +121711,7 @@ 3564904448,3564912639,DE 3564912640,3564920831,BG 3564920832,3564922879,ES -3564922880,3564928511,US -3564928512,3564929023,RU +3564922880,3564929023,US 3564929024,3564937215,AT 3564937216,3564945407,RS 3564945408,3564947175,GB @@ -118746,14 +121923,14 @@ 3565036288,3565036543,GB 3565036544,3565037119,IE 3565037120,3565037135,GB -3565037136,3565037279,IE -3565037280,3565037567,GB +3565037136,3565037311,IE +3565037312,3565037567,GB 3565037568,3565037823,IE 3565037824,3565038591,GB 3565038592,3565038663,IE 3565038664,3565039615,GB -3565039616,3565041663,IE -3565041664,3565043711,GB +3565039616,3565042175,IE +3565042176,3565043711,GB 3565043712,3565047807,AT 3565047808,3565048063,LI 3565048064,3565051903,AT @@ -119253,10 +122430,7 @@ 3567165440,3567169535,RU 3567169536,3567173631,MK 3567173632,3567239167,GB -3567239168,3567250143,NL -3567250144,3567250175,EU -3567250176,3567250943,NL -3567250944,3567255551,EU +3567239168,3567255551,NL 3567255552,3567321087,PL 3567321088,3567323007,GB 3567323008,3567323023,CH @@ -119311,17 +122485,17 @@ 3567388608,3567388671,GB 3567388672,3567388927,CZ 3567388928,3567389183,DE -3567389184,3567389695,GB +3567389184,3567389311,GB +3567389312,3567389375,DE +3567389376,3567389695,GB 3567389696,3567390975,DE 3567390976,3567391107,GB 3567391108,3567391111,DE 3567391112,3567391147,GB 3567391148,3567391151,DE 3567391152,3567391231,GB -3567391232,3567391615,DE -3567391616,3567391759,GB -3567391760,3567391791,DE -3567391792,3567391807,GB +3567391232,3567391743,DE +3567391744,3567391807,GB 3567391808,3567391839,DE 3567391840,3567392767,GB 3567392768,3567393023,DE @@ -119353,8 +122527,10 @@ 3567399392,3567399423,GB 3567399424,3567399439,DE 3567399440,3567399487,GB -3567399488,3567399871,DE -3567399872,3567399935,GB +3567399488,3567399647,DE +3567399648,3567399679,GB +3567399680,3567399807,DE +3567399808,3567399935,GB 3567399936,3567400703,DE 3567400704,3567400735,GB 3567400736,3567400751,DE @@ -119573,7 +122749,9 @@ 3568848872,3568848879,GB 3568848880,3568876159,DE 3568876160,3568876287,ES -3568876288,3568916399,DE +3568876288,3568915791,DE +3568915792,3568915807,LU +3568915808,3568916399,DE 3568916400,3568916407,IT 3568916408,3568938311,DE 3568938312,3568938319,FI @@ -119599,9 +122777,7 @@ 3569238400,3569238527,AT 3569238528,3569239071,BE 3569239072,3569239103,LU -3569239104,3569239231,BE -3569239232,3569239263,LU -3569239264,3569239519,BE +3569239104,3569239519,BE 3569239520,3569239551,LU 3569239552,3569239983,BE 3569239984,3569239999,BN @@ -120620,9 +123796,7 @@ 3574153360,3574153367,AT 3574153368,3574153615,DE 3574153616,3574153623,AT -3574153624,3574153731,DE -3574153732,3574153735,HU -3574153736,3574155627,DE +3574153624,3574155627,DE 3574155628,3574155631,NL 3574155632,3574155727,DE 3574155728,3574155731,AT @@ -120723,9 +123897,9 @@ 3574917632,3574919359,DE 3574919360,3574919391,FR 3574919392,3574920223,DE -3574920224,3574920239,RO +3574920224,3574920239,LU 3574920240,3574920503,DE -3574920504,3574920511,RO +3574920504,3574920511,LU 3574920512,3574923263,DE 3574923264,3574939647,RU 3574939648,3574956031,SE @@ -120739,7 +123913,9 @@ 3575185408,3575250943,PL 3575250944,3575316479,IT 3575316480,3575349247,RU -3575349248,3575355231,ES +3575349248,3575351679,ES +3575351680,3575351687,NL +3575351688,3575355231,ES 3575355232,3575355247,GB 3575355248,3575360199,ES 3575360200,3575360207,FR @@ -120763,161 +123939,156 @@ 3575513088,3575545855,PT 3575545856,3575562239,FR 3575562240,3575578623,DE -3575578624,3575578879,EU +3575578624,3575578879,BE 3575578880,3575579135,AU -3575579136,3575579647,EU +3575579136,3575579647,BE 3575579648,3575579903,AU -3575579904,3575581439,EU +3575579904,3575581439,BE 3575581440,3575581567,GB 3575581568,3575581695,IT -3575581696,3575582207,EU +3575581696,3575582207,BE 3575582208,3575582463,CH 3575582464,3575582719,FR -3575582720,3575583103,EU +3575582720,3575583103,BE 3575583104,3575583111,HU 3575583112,3575583115,GB 3575583116,3575583119,FR -3575583120,3575583231,EU +3575583120,3575583231,BE 3575583232,3575583487,IT -3575583488,3575585791,EU +3575583488,3575585791,BE 3575585792,3575586047,EG 3575586048,3575586303,IT 3575586304,3575586815,BE 3575586816,3575587071,GB -3575587072,3575587199,EU -3575587200,3575587215,BE -3575587216,3575587231,EU +3575587072,3575587231,BE 3575587232,3575587247,NL 3575587248,3575587255,FR -3575587256,3575587263,EU +3575587256,3575587263,BE 3575587264,3575587271,CH -3575587272,3575587287,EU +3575587272,3575587287,BE 3575587288,3575587295,PL -3575587296,3575587319,EU +3575587296,3575587319,BE 3575587320,3575587323,PL -3575587324,3575587839,EU +3575587324,3575587839,BE 3575587840,3575588351,GB -3575588352,3575588863,EU +3575588352,3575588863,BE 3575588864,3575589887,A2 -3575589888,3575590399,EU +3575589888,3575590399,BE 3575590400,3575590911,A2 -3575590912,3575592447,EU -3575592448,3575592959,BE -3575592960,3575595007,EU +3575590912,3575595007,BE 3575595008,3575595519,GB -3575595520,3575596287,EU +3575595520,3575596287,BE 3575596288,3575596415,GB -3575596416,3575596543,EU +3575596416,3575596543,BE 3575596544,3575596799,FR -3575596800,3575622607,EU +3575596800,3575622607,BE 3575622608,3575622611,GB -3575622612,3575622655,EU +3575622612,3575622655,BE 3575622656,3575622815,GB -3575622816,3575622847,EU +3575622816,3575622847,BE 3575622848,3575622879,IT 3575622880,3575622911,FI 3575622912,3575623167,GB -3575623168,3575624703,EU +3575623168,3575624703,BE 3575624704,3575624831,FR 3575624832,3575624839,PT 3575624840,3575624863,GB 3575624864,3575624895,IL 3575624896,3575624911,GB -3575624912,3575624959,EU +3575624912,3575624959,BE 3575624960,3575624991,GB 3575624992,3575624999,IT 3575625000,3575625007,GB 3575625008,3575625023,NL 3575625024,3575625027,EG -3575625028,3575625035,EU +3575625028,3575625035,BE 3575625036,3575625039,GB -3575625040,3575625047,EU +3575625040,3575625047,BE 3575625048,3575625055,FI -3575625056,3575625071,EU +3575625056,3575625071,BE 3575625072,3575625087,PL -3575625088,3575625095,BE -3575625096,3575625103,EU +3575625088,3575625103,BE 3575625104,3575625151,GB -3575625152,3575625351,EU +3575625152,3575625351,BE 3575625352,3575625359,GB -3575625360,3575625375,EU +3575625360,3575625375,BE 3575625376,3575625407,IT -3575625408,3575625439,EU +3575625408,3575625439,BE 3575625440,3575625455,ES -3575625456,3575625471,EU +3575625456,3575625471,BE 3575625472,3575625503,NO -3575625504,3575625983,EU +3575625504,3575625983,BE 3575625984,3575625991,SE -3575625992,3575626047,EU +3575625992,3575626047,BE 3575626048,3575626111,FR -3575626112,3575626319,EU +3575626112,3575626319,BE 3575626320,3575626335,GB 3575626336,3575626351,ES 3575626352,3575626367,DE -3575626368,3575626503,EU +3575626368,3575626503,BE 3575626504,3575626511,CH -3575626512,3575626519,EU +3575626512,3575626519,BE 3575626520,3575626527,FR -3575626528,3575626567,EU +3575626528,3575626567,BE 3575626568,3575626575,RO -3575626576,3575626599,EU +3575626576,3575626599,BE 3575626600,3575626607,IE -3575626608,3575626631,EU +3575626608,3575626631,BE 3575626632,3575626639,GB 3575626640,3575626647,DE 3575626648,3575626655,IT -3575626656,3575627311,EU +3575626656,3575627311,BE 3575627312,3575627327,ES 3575627328,3575627335,SE -3575627336,3575627359,EU +3575627336,3575627359,BE 3575627360,3575627367,ES -3575627368,3575627423,EU +3575627368,3575627423,BE 3575627424,3575627431,DE -3575627432,3575627487,EU +3575627432,3575627487,BE 3575627488,3575627503,GB -3575627504,3575627711,EU +3575627504,3575627711,BE 3575627712,3575627775,GB 3575627776,3575628543,NL -3575628544,3575628631,EU +3575628544,3575628631,BE 3575628632,3575628639,GB -3575628640,3575628815,EU +3575628640,3575628815,BE 3575628816,3575628823,ES 3575628824,3575628831,FR -3575628832,3575629183,EU +3575628832,3575629183,BE 3575629184,3575629247,NL -3575629248,3575629279,EU +3575629248,3575629279,BE 3575629280,3575629287,GB -3575629288,3575629295,EU +3575629288,3575629295,BE 3575629296,3575629303,NL -3575629304,3575629823,EU +3575629304,3575629823,BE 3575629824,3575629855,GR 3575629856,3575629871,DE -3575629872,3575629935,EU +3575629872,3575629935,BE 3575629936,3575629951,FR -3575629952,3575630015,EU +3575629952,3575630015,BE 3575630016,3575630023,GR -3575630024,3575630063,EU +3575630024,3575630063,BE 3575630064,3575630079,ZA 3575630080,3575630335,BE 3575630336,3575630463,IT 3575630464,3575630591,CH 3575630592,3575630847,IL -3575630848,3575630975,EU +3575630848,3575630975,BE 3575630976,3575630991,FR -3575630992,3575631103,EU +3575630992,3575631103,BE 3575631104,3575631111,AT 3575631112,3575631119,CH 3575631120,3575631127,DE -3575631128,3575631135,EU +3575631128,3575631135,BE 3575631136,3575631143,HU -3575631144,3575631159,EU +3575631144,3575631159,BE 3575631160,3575631167,GB 3575631168,3575631199,NL 3575631200,3575631207,IE -3575631208,3575631223,EU +3575631208,3575631223,BE 3575631224,3575631231,IL 3575631232,3575631295,CH -3575631296,3575631615,EU +3575631296,3575631615,BE 3575631616,3575631631,SE 3575631632,3575631639,BE 3575631640,3575631647,CH @@ -120925,177 +124096,173 @@ 3575631664,3575631679,DE 3575631680,3575631695,SE 3575631696,3575631711,IT -3575631712,3575631759,EU +3575631712,3575631759,BE 3575631760,3575631775,ZA -3575631776,3575631791,EU +3575631776,3575631791,BE 3575631792,3575631799,ES 3575631800,3575631807,CZ -3575631808,3575631855,EU +3575631808,3575631855,BE 3575631856,3575631863,ZA -3575631864,3575631871,EU -3575631872,3575632639,IL +3575631864,3575631871,BE +3575631872,3575632127,IL +3575632128,3575632639,BE 3575632640,3575632655,NO -3575632656,3575632703,EU +3575632656,3575632703,BE 3575632704,3575632711,GB -3575632712,3575632783,EU +3575632712,3575632783,BE 3575632784,3575632791,GB -3575632792,3575632831,EU -3575632832,3575632847,BE +3575632792,3575632847,BE 3575632848,3575632863,CH -3575632864,3575632871,BE -3575632872,3575632879,EU +3575632864,3575632879,BE 3575632880,3575632895,DE -3575632896,3575632967,EU +3575632896,3575632967,BE 3575632968,3575632975,GB -3575632976,3575632991,EU +3575632976,3575632991,BE 3575632992,3575632999,IT -3575633000,3575633039,EU +3575633000,3575633039,BE 3575633040,3575633055,DE 3575633056,3575633063,SE 3575633064,3575633071,NL -3575633072,3575633087,EU +3575633072,3575633087,BE 3575633088,3575633119,GB -3575633120,3575633135,EU +3575633120,3575633135,BE 3575633136,3575633143,GB -3575633144,3575633599,EU +3575633144,3575633599,BE 3575633600,3575633663,NL -3575633664,3575633727,EU +3575633664,3575633727,BE 3575633728,3575633735,AT 3575633736,3575633743,IT -3575633744,3575633783,EU +3575633744,3575633783,BE 3575633784,3575633791,DE -3575633792,3575633887,EU +3575633792,3575633887,BE 3575633888,3575633895,SE -3575633896,3575633919,EU +3575633896,3575633919,BE 3575633920,3575633983,CH 3575633984,3575633991,DE -3575633992,3575633999,EU +3575633992,3575633999,BE 3575634000,3575634007,PT 3575634008,3575634015,DK 3575634016,3575634047,GB -3575634048,3575634175,BE -3575634176,3575634183,EU +3575634048,3575634183,BE 3575634184,3575634191,AT -3575634192,3575634255,EU +3575634192,3575634255,BE 3575634256,3575634271,IT -3575634272,3575634367,EU +3575634272,3575634367,BE 3575634368,3575634399,NO 3575634400,3575634431,GB -3575634432,3575634455,EU +3575634432,3575634455,BE 3575634456,3575634463,DE -3575634464,3575634495,EU +3575634464,3575634495,BE 3575634496,3575634511,FI 3575634512,3575634519,CH -3575634520,3575634591,EU +3575634520,3575634591,BE 3575634592,3575634599,ES -3575634600,3575634607,EU +3575634600,3575634607,BE 3575634608,3575634615,GB 3575634616,3575634623,DE -3575634624,3575634695,EU +3575634624,3575634695,BE 3575634696,3575634703,FI -3575634704,3575634711,EU +3575634704,3575634711,BE 3575634712,3575634719,DE -3575634720,3575634767,EU +3575634720,3575634767,BE 3575634768,3575634775,NO -3575634776,3575634783,EU +3575634776,3575634783,BE 3575634784,3575634791,FR 3575634792,3575634799,ES 3575634800,3575634807,BE 3575634808,3575634815,SE -3575634816,3575634879,EU +3575634816,3575634879,BE 3575634880,3575634911,GB 3575634912,3575634919,SE 3575634920,3575634927,GB 3575634928,3575634935,IT -3575634936,3575635015,EU +3575634936,3575635015,BE 3575635016,3575635023,CH 3575635024,3575635039,ES -3575635040,3575635055,EU +3575635040,3575635055,BE 3575635056,3575635063,CH -3575635064,3575635071,EU +3575635064,3575635071,BE 3575635072,3575635087,SE -3575635088,3575635103,EU +3575635088,3575635103,BE 3575635104,3575635119,PT 3575635120,3575635135,PL 3575635136,3575635151,DE 3575635152,3575635159,PT 3575635160,3575635167,DE 3575635168,3575635175,GB -3575635176,3575635199,EU +3575635176,3575635199,BE 3575635200,3575635455,NO 3575635456,3575635463,RU 3575635464,3575635471,GB -3575635472,3575635583,EU +3575635472,3575635583,BE 3575635584,3575635615,EG 3575635616,3575635631,FI -3575635632,3575635647,EU +3575635632,3575635647,BE 3575635648,3575635679,GB -3575635680,3575635695,EU +3575635680,3575635695,BE 3575635696,3575635703,GB -3575635704,3575635775,EU +3575635704,3575635775,BE 3575635776,3575635839,CH 3575635840,3575635847,GB 3575635848,3575635855,FR 3575635856,3575635871,TR -3575635872,3575635983,EU +3575635872,3575635983,BE 3575635984,3575635999,DE -3575636000,3575636143,EU +3575636000,3575636143,BE 3575636144,3575636151,HU -3575636152,3575636607,EU +3575636152,3575636607,BE 3575636608,3575636735,FR -3575636736,3575636807,EU +3575636736,3575636807,BE 3575636808,3575636815,GB -3575636816,3575636823,EU +3575636816,3575636823,BE 3575636824,3575636831,RU -3575636832,3575636855,EU +3575636832,3575636855,BE 3575636856,3575636863,DE -3575636864,3575636871,EU +3575636864,3575636871,BE 3575636872,3575636879,CZ -3575636880,3575636895,EU +3575636880,3575636895,BE 3575636896,3575636903,PL 3575636904,3575636911,CZ -3575636912,3575636927,EU +3575636912,3575636927,BE 3575636928,3575636959,DE -3575636960,3575636983,EU +3575636960,3575636983,BE 3575636984,3575636991,FR -3575636992,3575637039,EU +3575636992,3575637039,BE 3575637040,3575637055,DE -3575637056,3575637151,EU +3575637056,3575637151,BE 3575637152,3575637183,GB -3575637184,3575637367,EU -3575637368,3575637375,BE -3575637376,3575637407,EU +3575637184,3575637407,BE 3575637408,3575637439,LU 3575637440,3575637471,GB -3575637472,3575638103,EU +3575637472,3575638103,BE 3575638104,3575638111,GB -3575638112,3575638175,EU +3575638112,3575638175,BE 3575638176,3575638239,GB -3575638240,3575638263,EU +3575638240,3575638263,BE 3575638264,3575638271,PL -3575638272,3575638279,EU +3575638272,3575638279,BE 3575638280,3575638287,RU -3575638288,3575638303,EU +3575638288,3575638303,BE 3575638304,3575638335,NO -3575638336,3575638527,EU +3575638336,3575638527,BE 3575638528,3575638543,DE -3575638544,3575638559,EU +3575638544,3575638559,BE 3575638560,3575638591,GB -3575638592,3575638623,EU +3575638592,3575638623,BE 3575638624,3575638639,PL -3575638640,3575638719,EU +3575638640,3575638719,BE 3575638720,3575638735,NL 3575638736,3575638751,GR -3575638752,3575638767,EU +3575638752,3575638767,BE 3575638768,3575638783,SE -3575638784,3575638911,EU +3575638784,3575638911,BE 3575638912,3575638943,FR 3575638944,3575638975,GB -3575638976,3575639007,EU +3575638976,3575639007,BE 3575639008,3575639011,GB 3575639012,3575639023,IE 3575639024,3575639039,PL -3575639040,3575640063,EU +3575639040,3575640063,BE 3575640064,3575644159,TR 3575644160,3575709695,DK 3575709696,3575730175,AT @@ -121689,7 +124856,10 @@ 3576239040,3576239071,GB 3576239072,3576239087,FR 3576239088,3576239103,GB -3576239104,3576239663,FR +3576239104,3576239615,FR +3576239616,3576239623,GB +3576239624,3576239631,IT +3576239632,3576239663,FR 3576239664,3576239671,GB 3576239672,3576240039,FR 3576240040,3576240047,GB @@ -121707,7 +124877,9 @@ 3576241344,3576241351,GB 3576241352,3576241383,FR 3576241384,3576241399,GB -3576241400,3576241935,FR +3576241400,3576241855,FR +3576241856,3576241887,GB +3576241888,3576241935,FR 3576241936,3576241943,GB 3576241944,3576241951,FR 3576241952,3576241991,GB @@ -121748,8 +124920,10 @@ 3576249824,3576249831,FR 3576249832,3576249839,GB 3576249840,3576250623,FR -3576250624,3576250879,GB -3576250880,3576251407,FR +3576250624,3576251007,GB +3576251008,3576251039,FR +3576251040,3576251135,GB +3576251136,3576251407,FR 3576251408,3576251519,GB 3576251520,3576251583,FR 3576251584,3576251599,GB @@ -121757,9 +124931,7 @@ 3576251616,3576251647,GB 3576251648,3576252415,FR 3576252416,3576252671,GB -3576252672,3576254487,FR -3576254488,3576254495,GB -3576254496,3576254551,FR +3576252672,3576254551,FR 3576254552,3576254559,GB 3576254560,3576254607,FR 3576254608,3576254615,GB @@ -121947,9 +125119,7 @@ 3576261104,3576261111,GB 3576261112,3576261375,FR 3576261376,3576261631,GB -3576261632,3576261823,FR -3576261824,3576261887,GB -3576261888,3576261927,FR +3576261632,3576261927,FR 3576261928,3576261935,GB 3576261936,3576263439,FR 3576263440,3576263487,GB @@ -121963,7 +125133,9 @@ 3576263584,3576263599,GB 3576263600,3576263615,FR 3576263616,3576263623,GB -3576263624,3576263751,FR +3576263624,3576263679,FR +3576263680,3576263743,GB +3576263744,3576263751,FR 3576263752,3576263759,GB 3576263760,3576263791,FR 3576263792,3576263887,GB @@ -121981,12 +125153,14 @@ 3576264576,3576264623,GB 3576264624,3576264639,FR 3576264640,3576264687,GB -3576264688,3576265303,FR +3576264688,3576265287,FR +3576265288,3576265295,GB +3576265296,3576265303,FR 3576265304,3576265311,GB 3576265312,3576265327,FR 3576265328,3576265335,GB -3576265336,3576265359,FR -3576265360,3576265367,GB +3576265336,3576265343,FR +3576265344,3576265367,GB 3576265368,3576265375,FR 3576265376,3576265383,GB 3576265384,3576265399,FR @@ -122044,13 +125218,16 @@ 3576954880,3576987647,NO 3576987648,3577001983,GB 3577001984,3577003583,NL -3577003584,3577003743,GB -3577003744,3577003767,NL +3577003584,3577003711,GB +3577003712,3577003727,NL +3577003728,3577003735,GB +3577003736,3577003767,NL 3577003768,3577003771,GB 3577003772,3577003775,NL 3577003776,3577020415,GB 3577020416,3577085951,NL 3577085952,3577151487,DE +3577151488,3577167871,FR 3577167872,3577184255,ET 3577184256,3577217023,CH 3577217024,3577282559,FR @@ -122078,13 +125255,19 @@ 3577559776,3577559783,FR 3577559784,3577562391,DE 3577562392,3577562399,GB -3577562400,3577577231,DE +3577562400,3577567711,DE +3577567712,3577567719,IT +3577567720,3577577231,DE 3577577232,3577577247,US -3577577248,3577592431,DE +3577577248,3577580887,DE +3577580888,3577580895,DK +3577580896,3577592431,DE 3577592432,3577592447,FR 3577592448,3577592743,DE 3577592744,3577592751,IE -3577592752,3577608743,DE +3577592752,3577606599,DE +3577606600,3577606607,GB +3577606608,3577608743,DE 3577608744,3577608751,ES 3577608752,3577610367,DE 3577610368,3577610495,GB @@ -122145,9 +125328,7 @@ 3577625600,3577625823,EU 3577625824,3577625839,GB 3577625840,3577625855,DE -3577625856,3577626175,GB -3577626176,3577626239,EU -3577626240,3577626367,GB +3577625856,3577626367,GB 3577626368,3577626623,EU 3577626624,3577627135,FR 3577627136,3577627391,EU @@ -122332,7 +125513,9 @@ 3578920960,3578986495,IT 3578986496,3578988095,DE 3578988096,3578988099,CH -3578988100,3578996999,DE +3578988100,3578992959,DE +3578992960,3578992975,GB +3578992976,3578996999,DE 3578997000,3578997007,CH 3578997008,3578997935,DE 3578997936,3578997943,FR @@ -122362,7 +125545,9 @@ 3579193728,3579193815,NL 3579193816,3579193823,ES 3579193824,3579193855,NL -3579193856,3579194103,GB +3579193856,3579194039,GB +3579194040,3579194047,SE +3579194048,3579194103,GB 3579194104,3579194111,US 3579194112,3579197055,GB 3579197056,3579197183,US @@ -122374,7 +125559,11 @@ 3579205632,3579205887,IE 3579205888,3579210079,GB 3579210080,3579210087,BE -3579210088,3579221071,GB +3579210088,3579213247,GB +3579213248,3579213311,IT +3579213312,3579221023,GB +3579221024,3579221039,FR +3579221040,3579221071,GB 3579221072,3579221087,DE 3579221088,3579221103,GB 3579221104,3579221119,IT @@ -122628,9 +125817,7 @@ 3580254208,3580260351,DE 3580260352,3580265727,AT 3580265728,3580338175,SE -3580338176,3580338432,HR -3580338433,3580338687,SE -3580338688,3580339199,HR +3580338176,3580339199,HR 3580339200,3580362751,SE 3580362752,3580473375,GB 3580473376,3580473391,IE @@ -122780,9 +125967,12 @@ 3582091264,3582099455,QA 3582099456,3582107647,GB 3582107648,3582115839,NL -3582115840,3582120959,SE +3582115840,3582116863,SE +3582116864,3582117887,EE +3582117888,3582119423,LT +3582119424,3582120959,SE 3582120960,3582121983,EE -3582121984,3582124031,SE +3582121984,3582124031,LT 3582124032,3582125383,FI 3582125384,3582125391,AX 3582125392,3582132223,FI @@ -122820,7 +126010,9 @@ 3582222512,3582222527,DK 3582222528,3582222863,SE 3582222864,3582222879,NO -3582222880,3582223967,SE +3582222880,3582223087,SE +3582223088,3582223095,NL +3582223096,3582223967,SE 3582223968,3582223975,NO 3582223976,3582226599,SE 3582226600,3582226607,FI @@ -122834,7 +126026,20 @@ 3582287872,3582296063,DE 3582296064,3582304255,GB 3582304256,3582312447,UA -3582312448,3582320639,GB +3582312448,3582312703,GB +3582312704,3582312959,JE +3582312960,3582314495,GB +3582314496,3582314751,JE +3582314752,3582315775,GB +3582315776,3582316543,JE +3582316544,3582317055,GB +3582317056,3582317311,JE +3582317312,3582317567,GB +3582317568,3582318079,JE +3582318080,3582318591,GB +3582318592,3582318847,JE +3582318848,3582320383,GB +3582320384,3582320639,JE 3582320640,3582328831,CH 3582328832,3582337023,HU 3582337024,3582341119,ES @@ -123015,8 +126220,7 @@ 3582571136,3582571199,FR 3582571200,3582571303,EU 3582571304,3582571307,CH -3582571308,3582571311,FR -3582571312,3582571375,EU +3582571308,3582571375,EU 3582571376,3582571391,FR 3582571392,3582571407,EU 3582571408,3582571423,FR @@ -123025,16 +126229,14 @@ 3582571488,3582571647,EU 3582571648,3582571687,IE 3582571688,3582571691,EU -3582571692,3582571707,IE -3582571708,3582571727,EU -3582571728,3582571743,IE +3582571692,3582571719,IE +3582571720,3582571735,EU +3582571736,3582571743,IE 3582571744,3582571751,EU 3582571752,3582571839,IE 3582571840,3582571999,EU 3582572000,3582572015,IE -3582572016,3582572023,EU -3582572024,3582572031,IE -3582572032,3582572415,EU +3582572016,3582572415,EU 3582572416,3582572431,CH 3582572432,3582572447,EU 3582572448,3582572451,CH @@ -123072,9 +126274,7 @@ 3582573600,3582573615,CH 3582573616,3582573631,EU 3582573632,3582573695,CH -3582573696,3582573727,EU -3582573728,3582573759,CH -3582573760,3582573823,EU +3582573696,3582573823,EU 3582573824,3582573887,CH 3582573888,3582573895,EU 3582573896,3582573903,CH @@ -123090,15 +126290,7 @@ 3582590976,3582599167,FR 3582599168,3582607359,DE 3582607360,3582615551,RU -3582615552,3582618111,A2 -3582618112,3582618367,CY -3582618368,3582619647,A2 -3582619648,3582619903,CY -3582619904,3582620671,A2 -3582620672,3582622207,CY -3582622208,3582622591,A2 -3582622592,3582622719,LB -3582622720,3582623743,A2 +3582615552,3582623743,CY 3582623744,3582631935,FI 3582631936,3582640127,NO 3582640128,3582648319,RU @@ -123121,7 +126313,9 @@ 3582746624,3582754815,RU 3582754816,3582763007,GR 3582763008,3582771199,FI -3582771200,3582779391,CY +3582771200,3582772479,CY +3582772480,3582772735,GB +3582772736,3582779391,CY 3582779392,3582787583,RU 3582787584,3582795775,PT 3582795776,3582803967,ES @@ -123131,6 +126325,7 @@ 3582828544,3582836735,KZ 3582836736,3582853119,RU 3582853120,3582861311,SE +3582861312,3582869503,RU 3582869504,3582877695,NO 3582877696,3582885887,AT 3582885888,3582894079,TR @@ -123177,7 +126372,9 @@ 3583032160,3583032191,FR 3583032192,3583032319,IT 3583032320,3583032575,FR -3583032576,3583033343,IT +3583032576,3583032831,IT +3583032832,3583033087,SG +3583033088,3583033343,IT 3583033344,3583041535,FR 3583041536,3583049727,NL 3583049728,3583066111,RU @@ -123240,9 +126437,7 @@ 3583338032,3583338047,RS 3583338048,3583338143,ME 3583338144,3583338175,RS -3583338176,3583339519,ME -3583339520,3583339775,AL -3583339776,3583341039,ME +3583338176,3583341039,ME 3583341040,3583341055,AL 3583341056,3583342335,ME 3583342336,3583342591,RS @@ -123340,9 +126535,7 @@ 3583706224,3583706231,NA 3583706232,3583706295,UA 3583706296,3583706319,NA -3583706320,3583706375,UA -3583706376,3583706383,NA -3583706384,3583706463,UA +3583706320,3583706463,UA 3583706464,3583706471,NA 3583706472,3583706495,UA 3583706496,3583706511,NA @@ -123356,9 +126549,7 @@ 3583706592,3583706607,NA 3583706608,3583706615,UA 3583706616,3583706623,NA -3583706624,3583706647,UA -3583706648,3583706655,NA -3583706656,3583706679,UA +3583706624,3583706679,UA 3583706680,3583706687,NA 3583706688,3583706695,UA 3583706696,3583706711,NA @@ -123408,15 +126599,11 @@ 3583708041,3583708095,NA 3583708096,3583708167,UA 3583708168,3583708175,NA -3583708176,3583708183,UA -3583708184,3583708191,RU -3583708192,3583708223,UA -3583708224,3583708239,NA +3583708176,3583708231,UA +3583708232,3583708239,NA 3583708240,3583708423,UA 3583708424,3583708431,NA -3583708432,3583708455,UA -3583708456,3583708463,NA -3583708464,3583708479,UA +3583708432,3583708479,UA 3583708480,3583708543,NA 3583708544,3583708575,UA 3583708576,3583708583,NA @@ -123424,13 +126611,10 @@ 3583708608,3583708623,NA 3583708624,3583709447,UA 3583709448,3583709455,NA -3583709456,3583709463,DE -3583709464,3583709479,UA -3583709480,3583709487,US -3583709488,3583709503,UA -3583709504,3583709519,RU -3583709520,3583709527,UA -3583709528,3583709543,NA +3583709456,3583709503,UA +3583709504,3583709511,RU +3583709512,3583709535,UA +3583709536,3583709543,NA 3583709544,3583709551,UA 3583709552,3583709559,NA 3583709560,3583709575,UA @@ -123438,8 +126622,8 @@ 3583709584,3583709599,UA 3583709600,3583709607,NA 3583709608,3583709615,RU -3583709616,3583709623,UA -3583709624,3583709639,NA +3583709616,3583709631,UA +3583709632,3583709639,NA 3583709640,3583709663,UA 3583709664,3583709671,NA 3583709672,3583709699,UA @@ -123462,9 +126646,9 @@ 3583709912,3583709927,UA 3583709928,3583709943,NA 3583709944,3583710055,UA -3583710056,3583710063,NA -3583710064,3583710072,DE -3583710073,3583710087,NA +3583710056,3583710072,NA +3583710073,3583710079,UA +3583710080,3583710087,NA 3583710088,3583710103,UA 3583710104,3583710111,NA 3583710112,3583710119,UA @@ -123475,7 +126659,8 @@ 3583710240,3583710247,NA 3583710248,3583710319,UA 3583710320,3583710335,NA -3583710336,3583710375,UA +3583710336,3583710367,UA +3583710368,3583710375,AQ 3583710376,3583710383,NA 3583710384,3583710407,UA 3583710408,3583710415,NA @@ -123483,9 +126668,7 @@ 3583710456,3583710459,NA 3583710460,3583710519,UA 3583710520,3583710527,NA -3583710528,3583710535,UA -3583710536,3583710543,RU -3583710544,3583710631,UA +3583710528,3583710631,UA 3583710632,3583710639,NA 3583710640,3583710671,UA 3583710672,3583710679,NA @@ -123493,21 +126676,17 @@ 3583710704,3583710711,NA 3583710712,3583710743,UA 3583710744,3583710751,BE -3583710752,3583710759,US -3583710760,3583710823,UA +3583710752,3583710823,UA 3583710824,3583710831,NA -3583710832,3583710847,UA -3583710848,3583710855,IL +3583710832,3583710855,UA 3583710856,3583710863,NA 3583710864,3583710871,UA 3583710872,3583710879,NA 3583710880,3583710887,UA -3583710888,3583710911,NA -3583710912,3583710935,UA +3583710888,3583710903,NA +3583710904,3583710935,UA 3583710936,3583710943,NA -3583710944,3583710959,UA -3583710960,3583710967,NA -3583710968,3583710991,UA +3583710944,3583710991,UA 3583710992,3583710999,NA 3583711000,3583711007,UA 3583711008,3583711015,RU @@ -123538,22 +126717,16 @@ 3583711640,3583711695,UA 3583711696,3583711703,NA 3583711704,3583711711,UA -3583711712,3583711727,NA -3583711728,3583711759,UA -3583711760,3583711767,NA -3583711768,3583711783,UA +3583711712,3583711719,NA +3583711720,3583711783,UA 3583711784,3583711799,NA -3583711800,3583711807,UA -3583711808,3583711823,NA -3583711824,3583711831,UA -3583711832,3583711839,NA -3583711840,3583711871,UA +3583711800,3583711815,UA +3583711816,3583711823,NA +3583711824,3583711871,UA 3583711872,3583711879,NA 3583711880,3583712015,UA 3583712016,3583712031,NA -3583712032,3583712095,UA -3583712096,3583712111,NA -3583712112,3583712119,UA +3583712032,3583712119,UA 3583712120,3583712127,NA 3583712128,3583712159,UA 3583712160,3583712199,NA @@ -123561,21 +126734,14 @@ 3583712288,3583712295,NA 3583712296,3583712311,UA 3583712312,3583712319,NA -3583712320,3583712415,UA -3583712416,3583712423,NA -3583712424,3583712431,SG -3583712432,3583712439,UA -3583712440,3583712479,NA -3583712480,3583712591,UA -3583712592,3583712599,NA -3583712600,3583712623,UA +3583712320,3583712447,UA +3583712448,3583712479,NA +3583712480,3583712623,UA 3583712624,3583712631,NA -3583712632,3583712639,UA -3583712640,3583712647,NA -3583712648,3583712655,UA +3583712632,3583712655,UA 3583712656,3583712663,NA -3583712664,3583712703,UA -3583712704,3583712719,NA +3583712664,3583712711,UA +3583712712,3583712719,NA 3583712720,3583712727,UA 3583712728,3583712735,RU 3583712736,3583712743,NA @@ -123583,32 +126749,27 @@ 3583712760,3583712763,NA 3583712764,3583712775,UA 3583712776,3583712783,NA -3583712784,3583712839,UA -3583712840,3583712847,NA -3583712848,3583712911,UA -3583712912,3583712943,NA -3583712944,3583712959,UA -3583712960,3583712983,NA -3583712984,3583713007,UA +3583712784,3583712831,UA +3583712832,3583712847,AQ +3583712848,3583712927,UA +3583712928,3583712943,NA +3583712944,3583713007,UA 3583713008,3583713015,RU 3583713016,3583713031,UA 3583713032,3583713039,NA -3583713040,3583713063,UA -3583713064,3583713071,KP +3583713040,3583713071,UA 3583713072,3583713079,NA 3583713080,3583713103,UA 3583713104,3583713111,AZ -3583713112,3583713127,UA -3583713128,3583713135,IT -3583713136,3583713143,UA +3583713112,3583713143,UA 3583713144,3583713151,NA 3583713152,3583713167,UA 3583713168,3583713175,EG 3583713176,3583713183,UA 3583713184,3583713191,NA -3583713192,3583713223,UA -3583713224,3583713231,NA -3583713232,3583713279,UA +3583713192,3583713271,UA +3583713272,3583713275,RU +3583713276,3583713279,UA 3583713280,3583721471,CZ 3583721472,3583729663,DE 3583729664,3583737855,TR @@ -123621,9 +126782,9 @@ 3583742720,3583743487,DE 3583743488,3583743519,EU 3583743520,3583743551,FR -3583743552,3583743679,EU -3583743680,3583743711,GB -3583743712,3583743975,EU +3583743552,3583743615,EU +3583743616,3583743743,GB +3583743744,3583743975,EU 3583743976,3583743983,GB 3583743984,3583744067,EU 3583744068,3583744071,GB @@ -123769,9 +126930,7 @@ 3584295760,3584295767,PT 3584295768,3584295807,AT 3584295808,3584295815,PT -3584295816,3584295935,AT -3584295936,3584295943,AS -3584295944,3584303103,AT +3584295816,3584303103,AT 3584303104,3584311295,ES 3584311296,3584319487,DE 3584319488,3584327679,LT @@ -123895,7 +127054,37 @@ 3584929728,3584931375,CH 3584931376,3584931391,ES 3584931392,3584933887,CH -3584933888,3584942079,PL +3584933888,3584933919,SE +3584933920,3584933927,PL +3584933928,3584934079,SE +3584934080,3584934087,PL +3584934088,3584934167,SE +3584934168,3584934171,PL +3584934172,3584934219,SE +3584934220,3584934223,PL +3584934224,3584934431,SE +3584934432,3584934439,PL +3584934440,3584935487,SE +3584935488,3584935491,PL +3584935492,3584935735,SE +3584935736,3584935739,PL +3584935740,3584935775,SE +3584935776,3584935779,PL +3584935780,3584936227,SE +3584936228,3584936231,PL +3584936232,3584936327,SE +3584936328,3584936331,PL +3584936332,3584938607,SE +3584938608,3584938611,PL +3584938612,3584938711,SE +3584938712,3584938715,PL +3584938716,3584938719,SE +3584938720,3584938723,PL +3584938724,3584941111,SE +3584941112,3584941115,PL +3584941116,3584941131,SE +3584941132,3584941135,PL +3584941136,3584942079,SE 3584942080,3584950271,DK 3584950272,3584958463,UA 3584958464,3584966655,DE @@ -123986,7 +127175,9 @@ 3585531904,3585540095,AT 3585540096,3585542335,DE 3585542336,3585542351,TR -3585542352,3585548287,DE +3585542352,3585544903,DE +3585544904,3585544911,CH +3585544912,3585548287,DE 3585548288,3585556479,RU 3585556480,3585564671,DE 3585564672,3585572863,RU @@ -124076,6 +127267,7 @@ 3585716424,3585720319,AT 3585720320,3585728511,GB 3585728512,3585736703,SE +3585736704,3585744895,HR 3585744896,3585750335,FR 3585750336,3585750351,GB 3585750352,3585750367,DE @@ -124111,9 +127303,7 @@ 3585835952,3585835959,SO 3585835960,3585835967,TD 3585835968,3585835983,ER -3585835984,3585836007,NL -3585836008,3585836023,IQ -3585836024,3585836287,NL +3585835984,3585836287,NL 3585836288,3585836543,CH 3585836544,3585837055,DZ 3585837056,3585837567,IQ @@ -124174,7 +127364,9 @@ 3585937408,3585940479,NL 3585940480,3585940735,BE 3585940736,3585941503,NL -3585941504,3585949695,PL +3585941504,3585943135,PL +3585943136,3585943167,US +3585943168,3585949695,PL 3585949696,3585957887,KW 3585957888,3585966079,SE 3585966080,3585974271,CH @@ -124323,21 +127515,21 @@ 3586677488,3586677759,DE 3586677760,3586678015,GR 3586678016,3586678271,DE -3586678272,3586678335,FR -3586678336,3586678399,US +3586678272,3586678399,FR 3586678400,3586678415,GB -3586678416,3586678439,IE +3586678416,3586678431,FR +3586678432,3586678439,IE 3586678440,3586678447,FR 3586678448,3586678527,IE -3586678528,3586678671,FR +3586678528,3586678655,FR +3586678656,3586678671,CY 3586678672,3586678679,GB 3586678680,3586678687,MU 3586678688,3586678783,GB 3586678784,3586679039,IT 3586679040,3586679103,FR 3586679104,3586679167,DE -3586679168,3586679231,US -3586679232,3586679327,FR +3586679168,3586679327,FR 3586679328,3586679343,DK 3586679344,3586679359,FR 3586679360,3586679423,DE @@ -124443,23 +127635,57 @@ 3586916352,3586924031,IT 3586924032,3586924047,US 3586924048,3586924543,IT -3586924544,3586924831,AX -3586924832,3586924839,FI -3586924840,3586924879,AX -3586924880,3586924887,FI -3586924888,3586924967,AX -3586924968,3586924983,FI -3586924984,3586925439,AX -3586925440,3586925471,FI -3586925472,3586925567,AX +3586924544,3586924743,FI +3586924744,3586924751,AX +3586924752,3586924767,FI +3586924768,3586924799,AX +3586924800,3586924871,FI +3586924872,3586924879,AX +3586924880,3586924919,FI +3586924920,3586924927,AX +3586924928,3586924943,FI +3586924944,3586924959,AX +3586924960,3586924983,FI +3586924984,3586925055,AX +3586925056,3586925103,FI +3586925104,3586925135,AX +3586925136,3586925247,FI +3586925248,3586925263,AX +3586925264,3586925311,FI +3586925312,3586925375,AX +3586925376,3586925439,FI +3586925440,3586925503,AX +3586925504,3586925535,FI +3586925536,3586925567,AX 3586925568,3586925695,FI -3586925696,3586926591,AX +3586925696,3586925759,AX +3586925760,3586925791,FI +3586925792,3586925823,AX +3586925824,3586925831,FI +3586925832,3586925855,AX +3586925856,3586925887,FI +3586925888,3586925919,AX +3586925920,3586925983,FI +3586925984,3586926003,AX +3586926004,3586926015,FI +3586926016,3586926047,AX +3586926048,3586926079,FI +3586926080,3586926591,AX 3586926592,3586926847,SE -3586926848,3586928255,AX -3586928256,3586928287,FI -3586928288,3586928335,AX -3586928336,3586928351,FI -3586928352,3586932735,AX +3586926848,3586927103,FI +3586927104,3586927999,AX +3586928000,3586928127,FI +3586928128,3586928143,AX +3586928144,3586928159,FI +3586928160,3586928175,AX +3586928176,3586928223,FI +3586928224,3586928239,AX +3586928240,3586928287,FI +3586928288,3586928319,AX +3586928320,3586928335,FI +3586928336,3586928351,AX +3586928352,3586928639,FI +3586928640,3586932735,AX 3586932736,3586949119,LB 3586949120,3586965503,SE 3586965504,3586981887,NL @@ -124516,9 +127742,7 @@ 3587227648,3587227759,NL 3587227760,3587227775,GB 3587227776,3587227903,NL -3587227904,3587227919,GB -3587227920,3587227935,NL -3587227936,3587227967,GB +3587227904,3587227967,GB 3587227968,3587227983,DE 3587227984,3587228047,GB 3587228048,3587228087,NL @@ -124535,7 +127759,8 @@ 3587228928,3587229455,GB 3587229456,3587229823,NL 3587229824,3587229839,GB -3587229840,3587229871,NL +3587229840,3587229855,ES +3587229856,3587229871,NL 3587229872,3587229887,GB 3587229888,3587229920,NL 3587229921,3587229935,GB @@ -124617,23 +127842,25 @@ 3587237568,3587237887,GB 3587237888,3587238471,NL 3587238472,3587238479,GB -3587238480,3587238535,NL -3587238536,3587238543,GB -3587238544,3587238607,NL +3587238480,3587238527,NL +3587238528,3587238543,GB +3587238544,3587238575,NL +3587238576,3587238583,GB +3587238584,3587238607,NL 3587238608,3587238911,GB 3587238912,3587239303,NL 3587239304,3587239311,GB -3587239312,3587239791,NL -3587239792,3587239807,GB -3587239808,3587239871,NL -3587239872,3587239935,GB -3587239936,3587240015,NL -3587240016,3587240023,GB -3587240024,3587240087,NL +3587239312,3587239903,NL +3587239904,3587239935,GB +3587239936,3587240087,NL 3587240088,3587240095,GB 3587240096,3587240103,NL 3587240104,3587240107,GB -3587240108,3587240439,NL +3587240108,3587240271,NL +3587240272,3587240287,GB +3587240288,3587240359,NL +3587240360,3587240367,GB +3587240368,3587240439,NL 3587240440,3587240447,GB 3587240448,3587240511,NL 3587240512,3587240575,GB @@ -124783,10 +128010,9 @@ 3587375104,3587383295,TR 3587383296,3587391487,CZ 3587391488,3587407871,KZ -3587407872,3587408127,NL -3587408128,3587415039,BE -3587415040,3587422719,NL -3587422720,3587424255,BE +3587407872,3587408383,NL +3587408384,3587408895,BE +3587408896,3587424255,NL 3587424256,3587440639,DE 3587440640,3587457023,SE 3587457024,3587459263,GB @@ -124806,19 +128032,11 @@ 3587620864,3587637247,SE 3587637248,3587653631,FR 3587653632,3587670015,SK -3587670016,3587673763,IT -3587673764,3587673767,GB -3587673768,3587673787,IT -3587673788,3587673792,GB -3587673793,3587679135,IT +3587670016,3587679135,IT 3587679136,3587679143,ES 3587679144,3587683327,IT 3587683328,3587683359,FR -3587683360,3587683415,IT -3587683416,3587683416,GB -3587683417,3587685831,IT -3587685832,3587685839,GB -3587685840,3587686031,IT +3587683360,3587686031,IT 3587686032,3587686039,FR 3587686040,3587687591,IT 3587687592,3587687599,NL @@ -124846,9 +128064,7 @@ 3587850240,3587854335,NL 3587854336,3587866623,PL 3587866624,3587874815,FR -3587874816,3587877383,DE -3587877384,3587877391,US -3587877392,3587877407,DE +3587874816,3587877407,DE 3587877408,3587877439,NL 3587877440,3587878527,DE 3587878528,3587878559,AT @@ -124877,6 +128093,7 @@ 3588112384,3588128767,FR 3588128768,3588145151,HU 3588145152,3588153343,PL +3588153344,3588161535,RU 3588161536,3588227071,FR 3588227072,3588292607,BE 3588292608,3588308991,AT @@ -124900,9 +128117,7 @@ 3588521984,3588538367,PT 3588538368,3588544383,GB 3588544384,3588544391,IE -3588544392,3588547327,GB -3588547328,3588547583,IE -3588547584,3588550447,GB +3588544392,3588550447,GB 3588550448,3588550463,IE 3588550464,3588553983,GB 3588553984,3588554239,IE @@ -124972,11 +128187,13 @@ 3589034368,3589034431,NL 3589034432,3589034495,FR 3589034496,3589037055,ES -3589037056,3589037343,NL +3589037056,3589037183,BE +3589037184,3589037343,NL 3589037344,3589037375,SE 3589037376,3589037423,NL 3589037424,3589037439,ES -3589037440,3589037495,NL +3589037440,3589037487,NL +3589037488,3589037495,IT 3589037496,3589037503,CH 3589037504,3589037551,NL 3589037552,3589037559,BE @@ -125039,7 +128256,8 @@ 3589429248,3589429503,FR 3589429504,3589430271,GB 3589430272,3589430543,FR -3589430544,3589431295,GB +3589430544,3589430559,ES +3589430560,3589431295,GB 3589431296,3589431343,FR 3589431344,3589432319,GB 3589432320,3589432575,CH @@ -125065,7 +128283,9 @@ 3589436160,3589436415,GB 3589436416,3589436671,FR 3589436672,3589436799,PL -3589436800,3589439487,GB +3589436800,3589436927,GB +3589436928,3589437183,PL +3589437184,3589439487,GB 3589439488,3589444631,SE 3589444632,3589444639,NO 3589444640,3589455871,SE @@ -125081,8 +128301,8 @@ 3589554176,3589570559,PS 3589570560,3589570655,NL 3589570656,3589578751,GB -3589578752,3589579263,NL -3589579264,3589579775,GB +3589578752,3589579391,NL +3589579392,3589579775,GB 3589579776,3589580799,NL 3589580800,3589580895,GB 3589580896,3589581055,NL @@ -125119,7 +128339,7 @@ 3589680768,3589685247,FR 3589685248,3589718015,GB 3589718016,3589719343,BE -3589719344,3589719347,GB +3589719344,3589719347,LU 3589719348,3589719847,BE 3589719848,3589719855,AT 3589719856,3589719967,BE @@ -125136,16 +128356,14 @@ 3589720312,3589720575,BE 3589720576,3589720583,ES 3589720584,3589720599,FR -3589720600,3589720603,BE -3589720604,3589720607,GB -3589720608,3589720623,BE +3589720600,3589720623,BE 3589720624,3589720631,GB 3589720632,3589720639,FR 3589720640,3589720655,BE 3589720656,3589720663,ES 3589720664,3589720687,BE 3589720688,3589720695,GB -3589720696,3589720703,FR +3589720696,3589720703,ES 3589720704,3589720727,BE 3589720728,3589720735,GB 3589720736,3589720743,BE @@ -125173,9 +128391,7 @@ 3589721048,3589721055,ES 3589721056,3589721063,BE 3589721064,3589721071,GB -3589721072,3589721147,BE -3589721148,3589721151,GB -3589721152,3589721159,BE +3589721072,3589721159,BE 3589721160,3589721167,GB 3589721168,3589721231,BE 3589721232,3589721247,GB @@ -125195,9 +128411,7 @@ 3589721952,3589721967,GB 3589721968,3589722023,BE 3589722024,3589722031,FR -3589722032,3589722059,BE -3589722060,3589722063,GB -3589722064,3589722111,BE +3589722032,3589722111,BE 3589722112,3589722143,GB 3589722144,3589722159,BE 3589722160,3589722167,FR @@ -125209,19 +128423,16 @@ 3589722264,3589722271,GB 3589722272,3589722279,BE 3589722280,3589722287,FR -3589722288,3589722295,BE -3589722296,3589722299,GB -3589722300,3589722303,BE +3589722288,3589722303,BE 3589722304,3589722311,FR 3589722312,3589722319,GB 3589722320,3589722335,FR 3589722336,3589722343,BE 3589722344,3589722359,FR 3589722360,3589722383,BE -3589722384,3589722391,FR -3589722392,3589722395,BE -3589722396,3589722399,GB -3589722400,3589722439,BE +3589722384,3589722391,DE +3589722392,3589722431,BE +3589722432,3589722439,ES 3589722440,3589722447,GB 3589722448,3589722623,BE 3589722624,3589722631,GB @@ -125233,16 +128444,12 @@ 3589722792,3589722799,GB 3589722800,3589722835,BE 3589722836,3589722843,GB -3589722844,3589722859,BE -3589722860,3589722863,GB -3589722864,3589722943,BE +3589722844,3589722943,BE 3589722944,3589722951,GB 3589722952,3589722959,FR -3589722960,3589722979,BE -3589722980,3589722991,GB -3589722992,3589722995,BE -3589722996,3589722999,GB -3589723000,3589723023,BE +3589722960,3589722983,BE +3589722984,3589722991,GB +3589722992,3589723023,BE 3589723024,3589723031,FR 3589723032,3589723975,BE 3589723976,3589723983,FR @@ -125292,27 +128499,16 @@ 3589726488,3589726495,GB 3589726496,3589726535,BE 3589726536,3589726543,GB -3589726544,3589729743,BE +3589726544,3589727007,BE +3589727008,3589727015,FR +3589727016,3589729735,BE +3589729736,3589729743,ES 3589729744,3589729751,GB -3589729752,3589730071,BE -3589730072,3589730075,GB -3589730076,3589730087,BE +3589729752,3589730087,BE 3589730088,3589730095,GB 3589730096,3589730111,BE 3589730112,3589730119,GB -3589730120,3589730139,BE -3589730140,3589730143,GB -3589730144,3589731603,BE -3589731604,3589731607,GB -3589731608,3589731635,BE -3589731636,3589731639,GB -3589731640,3589731719,BE -3589731720,3589731723,GB -3589731724,3589731731,BE -3589731732,3589731735,GB -3589731736,3589731819,BE -3589731820,3589731823,GB -3589731824,3589733375,BE +3589730120,3589733375,BE 3589733376,3589733439,LU 3589733440,3589734399,BE 3589734400,3589742591,EG @@ -125410,22 +128606,18 @@ 3590151144,3590151151,HR 3590151152,3590154047,SI 3590154048,3590154063,HR -3590154064,3590155799,SI -3590155800,3590155807,HR +3590154064,3590155775,SI +3590155776,3590155807,HR 3590155808,3590155815,SI 3590155816,3590155823,HR -3590155824,3590156031,SI -3590156032,3590156287,RS -3590156288,3590156415,HR -3590156416,3590156423,SI -3590156424,3590156431,HR +3590155824,3590155871,SI +3590155872,3590156431,HR 3590156432,3590156447,SI -3590156448,3590156679,HR -3590156680,3590156687,SI +3590156448,3590156671,HR +3590156672,3590156687,SI 3590156688,3590156719,HR 3590156720,3590156727,SI -3590156728,3590156959,HR -3590156960,3590156991,AE +3590156728,3590156991,HR 3590156992,3590157039,SI 3590157040,3590157311,HR 3590157312,3590157343,RS @@ -125573,22 +128765,29 @@ 3590308048,3590308055,NG 3590308056,3590308063,A2 3590308064,3590308071,ZW -3590308072,3590308087,A2 +3590308072,3590308079,RW +3590308080,3590308087,TZ 3590308088,3590308095,AO -3590308096,3590308183,A2 -3590308184,3590308191,IQ +3590308096,3590308119,A2 +3590308120,3590308127,IQ +3590308128,3590308175,A2 +3590308176,3590308191,IQ 3590308192,3590308199,A2 -3590308200,3590308223,IQ -3590308224,3590308247,A2 -3590308248,3590308263,IQ -3590308264,3590308271,A2 -3590308272,3590308287,IQ +3590308200,3590308215,IQ +3590308216,3590308247,A2 +3590308248,3590308287,IQ 3590308288,3590308303,A2 3590308304,3590308311,SO 3590308312,3590308319,IQ -3590308320,3590308335,A2 -3590308336,3590308343,IQ -3590308344,3590308607,A2 +3590308320,3590308327,A2 +3590308328,3590308343,IQ +3590308344,3590308351,A2 +3590308352,3590308367,IQ +3590308368,3590308383,A2 +3590308384,3590308391,IQ +3590308392,3590308447,A2 +3590308448,3590308455,IQ +3590308456,3590308607,A2 3590308608,3590308735,NG 3590308736,3590308767,A2 3590308768,3590308775,RW @@ -125597,10 +128796,7 @@ 3590308800,3590308807,A2 3590308808,3590308815,ZM 3590308816,3590308823,KE -3590308824,3590308831,A2 -3590308832,3590308839,ZW -3590308840,3590308847,ET -3590308848,3590308855,A2 +3590308824,3590308855,A2 3590308856,3590308863,NG 3590308864,3590308951,A2 3590308952,3590308959,GH @@ -125623,49 +128819,107 @@ 3590309536,3590309543,SO 3590309544,3590309551,AM 3590309552,3590309575,A2 -3590309576,3590309583,NG +3590309576,3590309583,US 3590309584,3590309615,A2 3590309616,3590309623,UG -3590309624,3590309631,ZW -3590309632,3590309639,A2 -3590309640,3590309647,IQ -3590309648,3590309687,A2 -3590309688,3590309695,IQ -3590309696,3590309727,A2 -3590309728,3590309743,IQ -3590309744,3590309751,A2 -3590309752,3590309759,IQ -3590309760,3590309799,A2 +3590309624,3590309631,A2 +3590309632,3590309647,IQ +3590309648,3590309671,A2 +3590309672,3590309687,IQ +3590309688,3590309711,A2 +3590309712,3590309719,IQ +3590309720,3590309727,A2 +3590309728,3590309759,IQ +3590309760,3590309767,A2 +3590309768,3590309775,IQ +3590309776,3590309783,A2 +3590309784,3590309791,IQ +3590309792,3590309799,A2 3590309800,3590309807,IQ -3590309808,3590309831,A2 +3590309808,3590309815,A2 +3590309816,3590309823,IQ +3590309824,3590309831,A2 3590309832,3590309839,IQ -3590309840,3590309879,A2 +3590309840,3590309863,A2 +3590309864,3590309871,IQ +3590309872,3590309879,A2 3590309880,3590309887,IQ -3590309888,3590310159,A2 -3590310160,3590310167,IQ +3590309888,3590310143,A2 +3590310144,3590310167,IQ 3590310168,3590310175,A2 3590310176,3590310183,LR -3590310184,3590310191,IQ -3590310192,3590310279,A2 -3590310280,3590310287,IQ -3590310288,3590310288,A2 -3590310289,3590310303,IQ -3590310304,3590310327,A2 +3590310184,3590310207,IQ +3590310208,3590310215,SD +3590310216,3590310223,A2 +3590310224,3590310255,IQ +3590310256,3590310263,A2 +3590310264,3590310271,SD +3590310272,3590310279,A2 +3590310280,3590310303,IQ +3590310304,3590310311,A2 +3590310312,3590310319,IQ +3590310320,3590310327,A2 3590310328,3590310335,NG 3590310336,3590310343,IQ -3590310344,3590310391,A2 -3590310392,3590310399,IQ -3590310400,3590310655,A2 +3590310344,3590310351,A2 +3590310352,3590310367,IQ +3590310368,3590310383,A2 +3590310384,3590310391,IQ +3590310392,3590310655,A2 3590310656,3590310911,GB -3590310912,3590311247,A2 -3590311248,3590311255,NG -3590311256,3590311423,A2 +3590310912,3590310919,IQ +3590310920,3590310951,A2 +3590310952,3590310959,IQ +3590310960,3590310967,A2 +3590310968,3590311007,IQ +3590311008,3590311015,A2 +3590311016,3590311023,IQ +3590311024,3590311031,A2 +3590311032,3590311039,IQ +3590311040,3590311055,A2 +3590311056,3590311063,IQ +3590311064,3590311079,A2 +3590311080,3590311087,IQ +3590311088,3590311119,A2 +3590311120,3590311135,IQ +3590311136,3590311143,A2 +3590311144,3590311151,IQ +3590311152,3590311159,A2 +3590311160,3590311167,IQ +3590311168,3590311175,A2 +3590311176,3590311183,CD +3590311184,3590311199,A2 +3590311200,3590311207,SD +3590311208,3590311215,CD +3590311216,3590311223,AO +3590311224,3590311231,CD +3590311232,3590311239,AO +3590311240,3590311255,A2 +3590311256,3590311263,ZW +3590311264,3590311271,A2 +3590311272,3590311279,SD +3590311280,3590311287,NG +3590311288,3590311295,A2 +3590311296,3590311303,LR +3590311304,3590311311,NG +3590311312,3590311319,CD +3590311320,3590311327,CI +3590311328,3590311335,CD +3590311336,3590311343,SD +3590311344,3590311351,A2 +3590311352,3590311359,CD +3590311360,3590311367,CI +3590311368,3590311383,CD +3590311384,3590311391,NG +3590311392,3590311423,A2 3590311424,3590311679,GB 3590311680,3590311935,YT 3590311936,3590312703,MW 3590312704,3590312799,A2 3590312800,3590312807,KE -3590312808,3590312895,A2 +3590312808,3590312815,A2 +3590312816,3590312823,US +3590312824,3590312895,A2 3590312896,3590312903,ZA 3590312904,3590312911,AO 3590312912,3590312919,NG @@ -125684,13 +128938,15 @@ 3590314720,3590314727,TG 3590314728,3590314735,UG 3590314736,3590314743,NG -3590314744,3590314823,A2 +3590314744,3590314767,A2 +3590314768,3590314775,US +3590314776,3590314823,A2 3590314824,3590314831,ZW 3590314832,3590314887,A2 3590314888,3590314895,NG 3590314896,3590314903,A2 3590314904,3590314911,KE -3590314912,3590314927,GH +3590314912,3590314927,A2 3590314928,3590314943,NG 3590314944,3590314967,A2 3590314968,3590314973,YT @@ -125705,7 +128961,9 @@ 3590316080,3590316087,LB 3590316088,3590316127,A2 3590316128,3590316151,NG -3590316152,3590316231,A2 +3590316152,3590316191,A2 +3590316192,3590316199,IQ +3590316200,3590316231,A2 3590316232,3590316239,LB 3590316240,3590316271,A2 3590316272,3590316279,IQ @@ -125717,9 +128975,7 @@ 3590316664,3590316671,LY 3590316672,3590316727,A2 3590316728,3590316735,LB -3590316736,3590316815,A2 -3590316816,3590316831,IQ -3590316832,3590317055,A2 +3590316736,3590317055,A2 3590317056,3590317311,NG 3590317312,3590317343,AO 3590317344,3590317439,A2 @@ -125733,8 +128989,8 @@ 3590317504,3590317527,A2 3590317528,3590317543,IQ 3590317544,3590317567,A2 -3590317568,3590317823,IQ -3590317824,3590317951,A2 +3590317568,3590317695,IQ +3590317696,3590317951,A2 3590317952,3590318047,UA 3590318048,3590319167,A2 3590319168,3590319231,AE @@ -125783,7 +129039,8 @@ 3590322352,3590322391,A2 3590322392,3590322399,IQ 3590322400,3590322415,AO -3590322416,3590322431,A2 +3590322416,3590322423,A2 +3590322424,3590322431,NG 3590322432,3590322559,LB 3590322560,3590322607,A2 3590322608,3590322687,LB @@ -125794,13 +129051,23 @@ 3590323912,3590323967,A2 3590323968,3590323975,SD 3590323976,3590323983,A2 -3590323984,3590323991,NG -3590323992,3590324023,A2 +3590323984,3590323999,NG +3590324000,3590324007,LR +3590324008,3590324015,A2 +3590324016,3590324023,NG 3590324024,3590324031,ZW -3590324032,3590324095,NG -3590324096,3590324103,A2 -3590324104,3590324111,ZW -3590324112,3590324215,A2 +3590324032,3590324103,A2 +3590324104,3590324111,KE +3590324112,3590324119,A2 +3590324120,3590324127,NG +3590324128,3590324159,A2 +3590324160,3590324167,NG +3590324168,3590324175,BW +3590324176,3590324183,LR +3590324184,3590324191,SD +3590324192,3590324199,VG +3590324200,3590324207,UG +3590324208,3590324215,CD 3590324216,3590324223,NG 3590324224,3623890943,US 3623890944,3623891199,ZA @@ -125821,8 +129088,8 @@ 3624272384,3624272415,US 3624272416,3624272639,CA 3624272640,3624272895,DZ -3624272896,3624279039,CA -3624279040,3624279087,BD +3624272896,3624279071,CA +3624279072,3624279087,BD 3624279088,3624281087,CA 3624281088,3624281343,HT 3624281344,3624283135,CA @@ -125847,11 +129114,7 @@ 3624303760,3624304639,CA 3624304640,3624321023,US 3624321024,3624325119,CA -3624325120,3624330511,US -3624330512,3624330519,IN -3624330520,3624333183,US -3624333184,3624333215,IN -3624333216,3624357887,US +3624325120,3624357887,US 3624357888,3624358143,KN 3624358144,3624359679,US 3624359680,3624360703,AN @@ -125920,15 +129183,11 @@ 3624380968,3624380983,TW 3624380984,3624381471,US 3624381472,3624381487,AU -3624381488,3624381535,US -3624381536,3624381551,CA -3624381552,3624381567,US +3624381488,3624381567,US 3624381568,3624381583,MY 3624381584,3624381631,US 3624381632,3624381647,GB -3624381648,3624381711,US -3624381712,3624381727,OM -3624381728,3624381807,US +3624381648,3624381807,US 3624381808,3624381823,IN 3624381824,3624381855,US 3624381856,3624381887,AU @@ -125939,9 +129198,7 @@ 3624382048,3624383071,US 3624383072,3624383087,GB 3624383088,3624383103,PT -3624383104,3624383183,US -3624383184,3624383199,DE -3624383200,3624384767,US +3624383104,3624384767,US 3624384768,3624385023,CA 3624385024,3624386559,US 3624386560,3624394751,CA @@ -125952,14 +129209,14 @@ 3624443872,3624443879,US 3624443880,3624443903,CA 3624443904,3624443919,US -3624443920,3624444343,CA +3624443920,3624444303,CA +3624444304,3624444319,US +3624444320,3624444343,CA 3624444344,3624444351,US 3624444352,3624444359,CA 3624444360,3624444367,US 3624444368,3624452095,CA -3624452096,3624474879,US -3624474880,3624475391,CA -3624475392,3624480767,US +3624452096,3624480767,US 3624480768,3624484863,CA 3624484864,3624534015,US 3624534016,3624534271,PA @@ -125983,7 +129240,9 @@ 3624547216,3624547239,US 3624547240,3624547255,A2 3624547256,3624547263,AS -3624547264,3624547591,US +3624547264,3624547327,US +3624547328,3624547583,A2 +3624547584,3624547591,US 3624547592,3624547647,A2 3624547648,3624547711,US 3624547712,3624547743,A2 @@ -125999,15 +129258,13 @@ 3624548032,3624548039,A2 3624548040,3624548063,US 3624548064,3624548087,A2 -3624548088,3624548607,US -3624548608,3624548671,A2 -3624548672,3624548687,US +3624548088,3624548095,US +3624548096,3624548679,A2 +3624548680,3624548687,US 3624548688,3624548703,A2 3624548704,3624548711,US 3624548712,3624548735,A2 -3624548736,3624548815,US -3624548816,3624548823,A2 -3624548824,3624548935,US +3624548736,3624548935,US 3624548936,3624548959,A2 3624548960,3624548975,US 3624548976,3624549023,A2 @@ -126018,27 +129275,12 @@ 3624549088,3624549095,US 3624549096,3624549111,A2 3624549112,3624549375,US -3624549376,3624549887,AS -3624549888,3624550143,A2 +3624549376,3624550143,A2 3624550144,3624587263,US 3624587264,3624591359,JM 3624595456,3624730623,US 3624730624,3624796159,CA -3624796160,3624798207,US -3624798208,3624799231,CA -3624799232,3624799743,US -3624799744,3624799999,CA -3624800000,3624800255,US -3624800768,3624801023,CA -3624801024,3624803071,US -3624803072,3624803583,CA -3624803840,3624804351,US -3624804608,3624804863,CA -3624804864,3624807679,US -3624807936,3624808447,CA -3624808448,3624811519,US -3624811520,3624812287,CA -3624812288,3624817679,US +3624812544,3624817679,US 3624817680,3624817687,CA 3624817688,3624820735,US 3624820736,3624820799,CY @@ -126077,8 +129319,8 @@ 3624900608,3624900639,AU 3624900640,3624900671,BE 3624900672,3624900735,US -3624900736,3624900799,CA -3624900800,3624900831,US +3624900736,3624900767,CA +3624900768,3624900831,US 3624900832,3624900863,DE 3624900864,3624900951,US 3624900952,3624900959,FR @@ -126114,7 +129356,9 @@ 3624905088,3624905151,CA 3624905152,3624905471,US 3624905472,3624905727,CA -3624905728,3624906879,US +3624905728,3624906465,US +3624906466,3624906495,CA +3624906496,3624906879,US 3624906880,3624907007,TW 3624907008,3624907039,FR 3624907040,3624907071,US @@ -126131,7 +129375,7 @@ 3624907746,3624907775,IN 3624907776,3624907903,US 3624907904,3624908031,SG -3624908032,3624908159,TW +3624908032,3624908159,CA 3624908160,3624908287,US 3624908288,3624908319,CA 3624908320,3624908351,US @@ -126155,7 +129399,8 @@ 3624909824,3624909951,CA 3624909952,3624910079,US 3624910080,3624910111,CA -3624910112,3624910175,US +3624910112,3624910143,US +3624910144,3624910175,CA 3624910176,3624910207,BE 3624910208,3624910271,US 3624910272,3624910303,FR @@ -126172,9 +129417,11 @@ 3624911008,3624911039,GB 3624911040,3624911103,US 3624911104,3624911135,CA -3624911136,3624911199,US +3624911136,3624911167,US +3624911168,3624911199,MY 3624911200,3624911231,BE -3624911232,3624911359,US +3624911232,3624911263,CA +3624911264,3624911359,US 3624911360,3624911615,CA 3624911616,3624911647,US 3624911648,3624911651,RU @@ -126182,10 +129429,13 @@ 3624912000,3624912127,CA 3624912128,3624913023,US 3624913024,3624913087,IN -3624913088,3624913311,US +3624913088,3624913247,US +3624913248,3624913279,CA +3624913280,3624913311,US 3624913312,3624913343,CA 3624913344,3624913375,PK -3624913376,3624913535,US +3624913376,3624913407,US +3624913408,3624913535,CA 3624913536,3624913663,IN 3624913664,3624914047,US 3624914048,3624914079,IN @@ -126202,9 +129452,9 @@ 3624915456,3624915903,US 3624915904,3624915935,HK 3624915936,3624916159,US -3624916160,3624916223,MY -3624916224,3624916479,US -3624916480,3624916735,CA +3624916160,3624916191,MY +3624916192,3624916223,US +3624916224,3624916735,CA 3624916736,3624917247,US 3624917248,3624917503,AU 3624917504,3624917919,US @@ -126212,22 +129462,22 @@ 3624917952,3624917983,US 3624917984,3624918015,CA 3624918016,3624918527,US -3624918528,3624918783,CA -3624918784,3624918815,HK +3624918528,3624918815,CA 3624918816,3624918847,US 3624918848,3624918875,IN -3624918876,3624919007,US +3624918876,3624918943,US +3624918944,3624918975,CA +3624918976,3624919007,US 3624919008,3624919039,MY 3624919040,3624919071,US 3624919072,3624919103,BE 3624919104,3624919295,US 3624919296,3624919423,CA 3624919424,3624919551,IN -3624919552,3624919679,CA -3624919680,3624919967,US +3624919552,3624919967,US 3624919968,3624919999,BE 3624920000,3624920031,CA -3624920032,3624920063,US +3624920032,3624920063,TZ 3624920064,3624920191,CA 3624920192,3624920319,IN 3624920320,3624920703,CA @@ -126239,15 +129489,17 @@ 3624921344,3624921855,US 3624921856,3624922111,CA 3624922112,3624922143,US -3624922144,3624922207,MY +3624922144,3624922175,FR +3624922176,3624922207,MY 3624922208,3624922239,FR -3624922240,3624922271,US -3624922272,3624922287,CR -3624922288,3624922335,US +3624922240,3624922335,US 3624922336,3624922367,FR 3624922368,3624922495,IN 3624922496,3624922623,BE -3624922624,3624922815,US +3624922624,3624922655,US +3624922656,3624922687,CA +3624922688,3624922783,US +3624922784,3624922815,CN 3624922816,3624922847,FR 3624922848,3624922879,US 3624922880,3624923135,IN @@ -126278,18 +129530,13 @@ 3624990464,3624991223,CA 3624991224,3624991231,US 3624991232,3624992767,CA -3624992768,3625002351,US -3625002352,3625002367,CA -3625002368,3625019135,US -3625019136,3625019391,ES -3625019392,3625042327,US +3624992768,3625042327,US 3625042328,3625042335,IT 3625042336,3625058303,US 3625058304,3625091071,CA 3625091072,3625116671,US 3625116672,3625116767,CA -3625116768,3625116775,US -3625116776,3625116927,CA +3625116768,3625116927,US 3625116928,3625117183,SE 3625117184,3625117775,US 3625117776,3625117783,CA @@ -126341,9 +129588,7 @@ 3625293616,3625295871,CA 3625295872,3625320447,US 3625320448,3625320467,CA -3625320468,3625321727,US -3625321728,3625321983,PA -3625321984,3625325055,US +3625320468,3625325055,US 3625325056,3625325087,RU 3625325088,3625326632,US 3625326633,3625326642,GB @@ -126353,8 +129598,7 @@ 3625327815,3625327824,GB 3625327825,3625327907,US 3625327908,3625327917,ID -3625327918,3625333375,US -3625333376,3625333383,PA +3625327918,3625333383,US 3625333384,3625333391,GB 3625333392,3625333455,US 3625333456,3625333463,GB @@ -126400,9 +129644,7 @@ 3625375136,3625375167,RU 3625375168,3625375247,US 3625375248,3625375255,CA -3625375256,3625375271,US -3625375272,3625375279,GB -3625375280,3625375359,US +3625375256,3625375359,US 3625375360,3625375367,SE 3625375368,3625375399,US 3625375400,3625375407,MT @@ -126484,7 +129726,7 @@ 3626228464,3626228479,AE 3626228480,3626270719,US 3626270720,3626287103,CA -3626287104,3626332159,US +3626287104,3626328063,US 3626332160,3626336255,CA 3626336256,3626381317,US 3626381318,3626381321,AU @@ -127080,15 +130322,9 @@ 3627507712,3627511807,CA 3627511808,3627519616,US 3627519617,3627519626,CA -3627519627,3627522690,US -3627522691,3627522700,GB -3627522701,3627524751,US -3627524752,3627524759,AE -3627524760,3627524979,US +3627519627,3627524979,US 3627524980,3627524987,IR -3627524988,3627525200,US -3627525201,3627525208,AU -3627525209,3627532287,US +3627524988,3627532287,US 3627532288,3627544575,CA 3627544576,3627659263,US 3627659264,3627663359,CA @@ -127102,9 +130338,7 @@ 3627667520,3627667583,CA 3627667584,3627669831,US 3627669832,3627669839,CA -3627669840,3627670799,US -3627670800,3627670811,CA -3627670812,3627679743,US +3627669840,3627679743,US 3627679744,3627712511,CA 3627712512,3627745343,US 3627745344,3627745375,BE @@ -127117,10 +130351,15 @@ 3627746400,3627746431,CA 3627746432,3627746559,US 3627746560,3627746815,IN -3627746816,3627753471,US +3627746816,3627747159,US +3627747160,3627747167,IN +3627747168,3627753471,US 3627753472,3627753727,AR -3627753728,3627769855,US -3627778048,3627802623,US +3627753728,3627755007,US +3627755008,3627755135,IE +3627755136,3627755263,US +3627755264,3627755391,IE +3627755392,3627802623,US 3627802624,3627810815,CA 3627810816,3627842047,US 3627842048,3627842303,IS @@ -127192,9 +130431,7 @@ 3628155104,3628155119,NZ 3628155120,3628155647,US 3628155648,3628155903,CA -3628155904,3628156159,US -3628156160,3628156415,GB -3628156416,3628161023,US +3628155904,3628161023,US 3628161024,3628161279,CA 3628161280,3628164927,US 3628164928,3628164943,IE @@ -127348,8 +130585,8 @@ 3629202012,3629202015,US 3629202016,3629202047,CA 3629202048,3629202175,US -3629202176,3629202207,CA -3629202208,3629202219,US +3629202176,3629202203,CA +3629202204,3629202219,US 3629202220,3629202239,CA 3629202240,3629202263,US 3629202264,3629202271,CA @@ -127363,9 +130600,7 @@ 3629202428,3629203199,CA 3629203200,3629318143,US 3629318144,3629326335,CA -3629326336,3629331967,US -3629331968,3629332479,CA -3629332480,3629539327,US +3629326336,3629539327,US 3629539328,3629547519,CA 3629547520,3629662207,US 3629662208,3629662463,GB @@ -127873,9 +131108,7 @@ 3630746880,3630747391,TZ 3630747392,3630780415,US 3630780416,3630784511,CA -3630784512,3630784895,US -3630784896,3630784911,IL -3630784912,3630787568,US +3630784512,3630787568,US 3630787569,3630787576,IE 3630787577,3630850047,US 3630850048,3630854143,CA @@ -127899,9 +131132,7 @@ 3631015296,3631015311,CN 3631015312,3631015887,US 3631015888,3631015903,CN -3631015904,3631016243,US -3631016244,3631016257,BD -3631016258,3631016555,US +3631015904,3631016555,US 3631016556,3631016571,CN 3631016572,3631016581,US 3631016582,3631016613,BD @@ -127926,17 +131157,7 @@ 3631045632,3631045759,CA 3631045760,3631045983,US 3631045984,3631045991,CA -3631045992,3631057577,US -3631057578,3631057597,GB -3631057598,3631058405,US -3631058406,3631058415,CA -3631058416,3631058511,US -3631058512,3631058521,CA -3631058522,3631058581,US -3631058582,3631058591,CA -3631058592,3631059229,US -3631059230,3631059239,NO -3631059240,3631112191,US +3631045992,3631112191,US 3631112192,3631116543,BB 3631116544,3631117567,GD 3631117568,3631117823,BB @@ -128006,7 +131227,6 @@ 3631881792,3631939583,US 3631939584,3632005119,CA 3632005120,3632136191,US -3632136192,3632144383,CA 3632144384,3632152575,US 3632152576,3632168959,CA 3632168960,3632197631,US @@ -128021,21 +131241,15 @@ 3632284880,3632284895,CA 3632284896,3632286479,US 3632286480,3632286495,CA -3632286496,3632287239,US -3632287240,3632287263,CA -3632287264,3632289583,US +3632286496,3632289583,US 3632289584,3632289599,PH 3632289600,3632291775,US 3632291776,3632291839,GB 3632291840,3632332799,US 3632332800,3632357375,CA -3632357376,3632370559,US -3632370560,3632370575,NG -3632370576,3632373503,US -3632373504,3632373759,NG -3632373760,3632381951,US +3632357376,3632381951,US 3632381952,3632390143,CA -3632390144,3632414719,US +3632390144,3632406527,US 3632414720,3632422911,CA 3632422912,3632451583,US 3632451584,3632455679,CA @@ -128494,9 +131708,7 @@ 3632902144,3632971775,US 3632971776,3632972031,CA 3632972032,3632972063,US -3632972064,3632976287,CA -3632976288,3632976303,US -3632976304,3632988159,CA +3632972064,3632988159,CA 3632988160,3633029119,US 3633029120,3633029631,PY 3633029632,3633030143,NI @@ -128566,8 +131778,8 @@ 3633034048,3633034079,A2 3633034080,3633034519,US 3633034520,3633034527,NG -3633034528,3633034559,US -3633034560,3633034751,NG +3633034528,3633034623,US +3633034624,3633034751,NG 3633034752,3633035015,US 3633035016,3633035023,NL 3633035024,3633035071,US @@ -128605,16 +131817,7 @@ 3633336480,3633340415,KY 3633340416,3633344511,US 3633344512,3633348607,CA -3633348608,3633373535,US -3633373536,3633373567,BA -3633373568,3633374799,US -3633374800,3633374815,CA -3633374816,3633376959,US -3633376960,3633376991,CA -3633376992,3633377087,US -3633377088,3633377119,IN -3633377120,3633379327,US -3633381376,3633405951,US +3633348608,3633405951,US 3633405952,3633410047,CA 3633410048,3633479679,US 3633479680,3633483775,CA @@ -128622,44 +131825,38 @@ 3633513985,3633514238,ES 3633514239,3633545215,US 3633545216,3633545727,GA -3633545728,3633546239,A2 +3633545728,3633545983,A2 +3633545984,3633546239,US 3633546240,3633546751,GA -3633546752,3633547263,A2 +3633546752,3633547007,A2 +3633547008,3633547263,US 3633547264,3633548287,GA 3633548288,3633548543,A2 3633548544,3633548799,GA -3633548800,3633548927,A2 +3633548800,3633548863,A2 +3633548864,3633548927,US 3633548928,3633549055,GA 3633549056,3633549375,A2 3633549376,3633549391,US 3633549392,3633549567,A2 3633549568,3633549823,GA -3633549824,3633550079,A2 -3633550080,3633550335,US -3633550336,3633550463,A2 -3633550464,3633550527,US -3633550528,3633550847,A2 +3633549824,3633550335,US +3633550336,3633550431,A2 +3633550432,3633550591,US +3633550592,3633550695,A2 +3633550696,3633550847,US 3633550848,3633551359,GA -3633551360,3633552383,A2 -3633552384,3633552639,US +3633551360,3633552639,US 3633552640,3633552911,A2 3633552912,3633552927,GA -3633552928,3633552951,US -3633552952,3633552959,A2 -3633552960,3633552967,US -3633552968,3633553031,A2 -3633553032,3633553039,US -3633553040,3633553127,A2 -3633553128,3633553135,US -3633553136,3633553151,A2 +3633552928,3633553119,US +3633553120,3633553127,A2 +3633553128,3633553143,US +3633553144,3633553151,A2 3633553152,3633553279,GW -3633553280,3633553295,US -3633553296,3633553351,A2 -3633553352,3633553367,US -3633553368,3633553399,A2 -3633553400,3633812775,US -3633812776,3633812783,CA -3633812784,3633815551,US +3633553280,3633553311,US +3633553312,3633553343,A2 +3633553344,3633815551,US 3633815552,3633816079,CA 3633816080,3633816095,US 3633816096,3633816119,CA @@ -128676,8 +131873,8 @@ 3633816248,3633816255,IN 3633816256,3633816263,NG 3633816264,3633816279,CA -3633816280,3633816303,US -3633816304,3633816351,CA +3633816280,3633816311,US +3633816312,3633816351,CA 3633816352,3633816383,IN 3633816384,3633816391,NG 3633816392,3633816399,US @@ -128690,16 +131887,18 @@ 3633816504,3633816511,IN 3633816512,3633816519,US 3633816520,3633816527,ZA -3633816528,3633819135,CA +3633816528,3633816535,CA +3633816536,3633816543,US +3633816544,3633819135,CA 3633819136,3633819199,IN 3633819200,3633819391,CA 3633819392,3633819423,IN 3633819424,3633819647,CA 3633819648,3633821279,US 3633821280,3633821311,BB -3633821312,3633822207,US -3633822208,3633822335,CY -3633822336,3633881087,US +3633821312,3633822303,US +3633822304,3633822327,CA +3633822328,3633881087,US 3633881088,3633885183,AN 3633885184,3633889279,US 3633889280,3633893375,CA @@ -128718,15 +131917,11 @@ 3634098176,3634125831,US 3634125832,3634125839,CA 3634125840,3634125855,JP -3634125856,3634125887,US -3634125888,3634125903,GB -3634125904,3634125951,US +3634125856,3634125951,US 3634125952,3634125967,CA 3634125968,3634135423,US 3634135424,3634135487,CA -3634135488,3634135935,US -3634135936,3634136062,CA -3634136063,3634136103,US +3634135488,3634136103,US 3634136104,3634136111,CA 3634136112,3634138127,US 3634138128,3634138143,CA @@ -128772,15 +131967,7 @@ 3635314688,3635322879,CA 3635322880,3635425279,US 3635425280,3635429375,CA -3635429376,3635458527,US -3635458528,3635458543,CH -3635458544,3635460031,US -3635460032,3635460095,CH -3635460096,3635460543,US -3635460544,3635460575,CH -3635460576,3635460799,US -3635460800,3635460831,CH -3635460832,3635464031,US +3635429376,3635464031,US 3635464032,3635464063,GB 3635464064,3635464127,US 3635464128,3635464135,GB @@ -128869,7 +132056,9 @@ 3636151489,3636151535,US 3636151536,3636151759,CA 3636151760,3636151775,US -3636151776,3636152575,CA +3636151776,3636152303,CA +3636152304,3636152319,US +3636152320,3636152575,CA 3636152576,3636152591,US 3636152592,3636152639,CA 3636152640,3636152647,US @@ -128895,9 +132084,7 @@ 3636154912,3636154975,CA 3636154976,3636154979,US 3636154980,3636154990,CA -3636154991,3636154991,US -3636154992,3636155007,CA -3636155008,3636155071,US +3636154991,3636155071,US 3636155072,3636155391,CA 3636155392,3636155407,US 3636155408,3636155455,CA @@ -128939,7 +132126,9 @@ 3636159840,3636159871,CA 3636159872,3636159999,IN 3636160000,3636160255,US -3636160256,3636160415,CA +3636160256,3636160335,CA +3636160336,3636160343,US +3636160344,3636160415,CA 3636160416,3636160431,US 3636160432,3636160831,CA 3636160832,3636160895,US @@ -128952,8 +132141,8 @@ 3636161792,3636161871,CA 3636161872,3636161885,US 3636161886,3636161943,CA -3636161944,3636161951,US -3636161952,3636162559,CA +3636161944,3636162015,US +3636162016,3636162559,CA 3636162560,3636163583,US 3636163584,3636164095,CA 3636164096,3636164111,BV @@ -129009,41 +132198,26 @@ 3636635392,3636635775,CR 3636635776,3636636415,US 3636636416,3636636543,CR -3636636544,3636667647,US -3636667904,3636668159,SC -3636668416,3636668671,GI -3636668672,3636668927,US -3636668928,3636669183,BZ -3636669184,3636669439,CY -3636669696,3636669951,SC -3636669952,3636670207,DE -3636670304,3636670335,RU -3636670464,3636670527,US -3636670656,3636670719,RU -3636670784,3636670799,RU -3636670976,3636671007,VG -3636671200,3636671231,IT -3636671232,3636671487,SC -3636671488,3636671743,GB -3636674560,3636822015,US +3636636544,3636822015,US 3636822016,3636854783,CA 3636854784,3636887551,US 3636887552,3636895743,CA -3636895744,3636904351,US -3636904352,3636904383,MY -3636904384,3636904511,US +3636895744,3636904063,US +3636904064,3636904095,GB +3636904096,3636904159,US +3636904160,3636904191,CA +3636904192,3636904447,US +3636904448,3636904479,CA +3636904480,3636904511,HK 3636904512,3636904543,CA 3636904544,3636904575,IN 3636904576,3636904607,US -3636904608,3636904639,IN -3636904640,3636904703,US +3636904608,3636904671,IN +3636904672,3636904703,US 3636904704,3636904959,MY -3636904960,3636905087,US -3636905088,3636905215,MY -3636905216,3636905471,US +3636904960,3636905471,US 3636905472,3636905727,CA -3636905728,3636905759,HK -3636905760,3636905791,US +3636905728,3636905791,US 3636905792,3636905823,IN 3636905824,3636905887,US 3636905888,3636905951,CA @@ -129056,30 +132230,40 @@ 3636906176,3636906207,IN 3636906208,3636906367,US 3636906368,3636906465,IN -3636906466,3636906623,US +3636906466,3636906495,US +3636906496,3636906623,CA 3636906624,3636906751,IN 3636906752,3636906879,US 3636906880,3636907007,IN -3636907008,3636907103,US +3636907008,3636907039,CA +3636907040,3636907103,US 3636907104,3636907135,IN -3636907136,3636907199,CA -3636907200,3636907231,HK +3636907136,3636907167,CA +3636907168,3636907199,US +3636907200,3636907231,CA 3636907232,3636907775,US 3636907776,3636908031,CA 3636908032,3636908543,US 3636908544,3636908799,IN -3636908800,3636909055,US -3636909056,3636909567,CA -3636909568,3636909663,US +3636908800,3636908863,US +3636908864,3636908991,CA +3636908992,3636909055,US +3636909056,3636909311,CA +3636909312,3636909663,US 3636909664,3636909695,IT -3636909696,3636909791,CA +3636909696,3636909727,CA +3636909728,3636909759,US +3636909760,3636909791,CA 3636909792,3636909855,US 3636909856,3636909887,CN 3636909888,3636909951,IT -3636909952,3636910079,US -3636910080,3636910335,CA -3636910336,3636910399,IN -3636910400,3636910495,US +3636909952,3636909983,US +3636909984,3636910015,TZ +3636910016,3636910335,US +3636910336,3636910367,IN +3636910368,3636910399,US +3636910400,3636910431,IN +3636910432,3636910495,US 3636910496,3636910527,BE 3636910528,3636910591,US 3636910592,3636910719,CA @@ -129090,40 +132274,52 @@ 3636911360,3636911423,US 3636911424,3636911455,BE 3636911456,3636911615,US -3636911616,3636911743,TW +3636911616,3636911743,CA 3636911744,3636911871,IN -3636911872,3636912383,US +3636911872,3636911903,US +3636911904,3636911935,CA +3636911936,3636912383,US 3636912384,3636912447,JP 3636912448,3636912959,US 3636912960,3636912991,BE -3636912992,3636913919,US -3636913920,3636914175,CA -3636914176,3636914431,US -3636914432,3636914687,CA +3636912992,3636913279,US +3636913280,3636913407,CA +3636913408,3636913535,US +3636913536,3636913663,CA +3636913664,3636913919,US +3636913920,3636914687,CA 3636914688,3636914815,US 3636914816,3636914943,CA 3636914944,3636915103,US 3636915104,3636915135,IN 3636915136,3636915199,US 3636915200,3636915327,IN -3636915328,3636915455,US +3636915328,3636915455,CA 3636915456,3636915583,IN -3636915584,3636916223,US +3636915584,3636915711,CA +3636915712,3636915839,US +3636915840,3636915967,CA +3636915968,3636916031,US +3636916032,3636916063,CA +3636916064,3636916223,US 3636916224,3636916351,CA 3636916352,3636916479,US 3636916480,3636916607,CA 3636916608,3636916735,IN -3636916736,3636916991,US -3636916992,3636917120,CA -3636917121,3636917255,US +3636916736,3636916927,US +3636916928,3636916959,CA +3636916960,3636916991,US +3636916992,3636917119,CA +3636917120,3636917255,US 3636917256,3636917263,IN -3636917264,3636917271,CA -3636917272,3636917295,US +3636917264,3636917295,US 3636917296,3636917303,IN -3636917304,3636917447,US +3636917304,3636917359,US +3636917360,3636917367,AU +3636917368,3636917447,US 3636917448,3636917455,HK -3636917456,3636917631,US -3636917632,3636919039,CA +3636917456,3636917503,US +3636917504,3636919039,CA 3636919040,3636919071,IN 3636919072,3636919103,US 3636919104,3636919135,CA @@ -129134,14 +132330,15 @@ 3636919712,3636919743,BE 3636919744,3636919807,US 3636919808,3636919871,GB -3636919872,3637071887,US +3636919872,3636920127,US +3636920128,3636920191,CA +3636920192,3637071887,US 3637071888,3637071903,AD 3637071904,3637071935,US 3637071936,3637071943,SK 3637071944,3637071951,IL 3637071952,3637071967,CY -3637071968,3637071999,US -3637072000,3637072015,CA +3637071968,3637072015,US 3637072016,3637072031,CY 3637072032,3637072071,US 3637072072,3637072079,FI @@ -129308,9 +132505,7 @@ 3638370304,3638374751,CA 3638374752,3638374767,US 3638374768,3638386687,CA -3638386688,3638494175,US -3638494176,3638494183,CA -3638494184,3638509295,US +3638386688,3638509295,US 3638509296,3638509311,GB 3638509312,3638509567,US 3638509568,3638526911,CA @@ -129345,11 +132540,7 @@ 3639258679,3639263231,CA 3639263232,3639279615,US 3639279616,3639283711,CA -3639283712,3639322511,US -3639322512,3639322519,JP -3639322520,3639322535,US -3639322536,3639322543,JP -3639322544,3639342703,US +3639283712,3639342703,US 3639342704,3639342711,GB 3639342712,3639343135,US 3639343136,3639343167,GB @@ -129441,7 +132632,6 @@ 3639439640,3639440767,US 3639440768,3639440895,IN 3639440896,3639476223,US -3639507456,3639507967,US 3639541760,3639558143,US 3639558144,3639566335,CA 3639566336,3639607295,US @@ -129537,19 +132727,23 @@ 3639680992,3639681023,CL 3639681024,3639730175,US 3639730176,3639734271,CA -3639734272,3639886095,US -3639886096,3639886103,CN -3639886104,3639886591,US +3639734272,3639886591,US 3639886592,3639886599,SG -3639886600,3639888927,US -3639888928,3639888959,NO -3639888960,3639892359,US +3639886600,3639892359,US 3639892360,3639892367,ID 3639892368,3639892375,US 3639892376,3639892383,ID 3639892384,3639892415,US 3639892416,3639892431,MX -3639892432,3639902207,US +3639892432,3639892815,US +3639892816,3639892831,MX +3639892832,3639893119,US +3639893120,3639893151,DE +3639893152,3639893167,US +3639893168,3639893199,DE +3639893200,3639893207,US +3639893208,3639893215,DE +3639893216,3639902207,US 3639902208,3639918591,PE 3639918592,3639934975,AR 3639934976,3640001751,US @@ -129862,7 +133056,11 @@ 3641559136,3641560959,DE 3641560960,3641561087,NL 3641561088,3641565183,RU -3641565184,3641573375,SE +3641565184,3641567343,SE +3641567344,3641567351,FI +3641567352,3641568967,SE +3641568968,3641568975,NO +3641568976,3641573375,SE 3641573376,3641577471,NO 3641577472,3641581567,RU 3641581568,3641585663,ES @@ -129935,9 +133133,7 @@ 3641762012,3641762047,GR 3641762048,3641762571,CY 3641762572,3641762575,GR -3641762576,3641762591,CY -3641762592,3641762595,GR -3641762596,3641762607,CY +3641762576,3641762607,CY 3641762608,3641762611,GR 3641762612,3641762647,CY 3641762648,3641762655,GR @@ -130146,6 +133342,7 @@ 3642056704,3642060799,RU 3642060800,3642064895,KE 3642064896,3642068991,SE +3642068992,3642073087,AL 3642073088,3642077183,LV 3642077184,3642081271,BE 3642081272,3642081278,US @@ -130250,7 +133447,6 @@ 3642249216,3642253311,FR 3642253312,3642257407,FI 3642257408,3642261503,RU -3642261504,3642265599,GB 3642265600,3642266111,AE 3642266112,3642266367,IR 3642266368,3642266623,AE @@ -130328,6 +133524,7 @@ 3642503168,3642507263,LV 3642507264,3642509311,FR 3642509312,3642511359,RU +3642511360,3642515455,CZ 3642515456,3642519551,DE 3642519552,3642523647,IT 3642523648,3642527743,GB @@ -130352,14 +133549,11 @@ 3642552688,3642552831,UA 3642552832,3642552847,EE 3642552848,3642553095,UA -3642553096,3642553097,LV -3642553098,3642553099,UA -3642553100,3642553139,LV +3642553096,3642553139,LV 3642553140,3642553143,UA 3642553144,3642553175,LV 3642553176,3642553183,UA -3642553184,3642553335,LV -3642553336,3642553343,UA +3642553184,3642553343,LV 3642553344,3642553371,RU 3642553372,3642553375,UA 3642553376,3642553377,RU @@ -130390,9 +133584,9 @@ 3642554120,3642554123,UA 3642554124,3642554151,RU 3642554152,3642554177,UA -3642554178,3642554203,RU -3642554204,3642554205,UA -3642554206,3642554223,RU +3642554178,3642554207,RU +3642554208,3642554211,UA +3642554212,3642554223,RU 3642554224,3642554239,UA 3642554240,3642554271,RU 3642554272,3642554367,UA @@ -130441,17 +133635,21 @@ 3642555184,3642555199,UA 3642555200,3642555223,LT 3642555224,3642555227,LV -3642555228,3642555391,LT -3642555392,3642555499,PL -3642555500,3642555647,UA +3642555228,3642555289,LT +3642555290,3642555295,UA +3642555296,3642555391,LT +3642555392,3642555493,PL +3642555494,3642555495,UA +3642555496,3642555503,PL +3642555504,3642555647,UA 3642555648,3642555683,SE 3642555684,3642555687,UA 3642555688,3642555695,SE -3642555696,3642555703,LV +3642555696,3642555703,UA 3642555704,3642555707,FI 3642555708,3642555711,SE 3642555712,3642555727,RU -3642555728,3642555735,SE +3642555728,3642555735,UA 3642555736,3642555743,GB 3642555744,3642555759,SE 3642555760,3642555771,GB @@ -130460,9 +133658,7 @@ 3642555784,3642555787,GB 3642555788,3642555789,UA 3642555790,3642555791,SE -3642555792,3642555839,UA -3642555840,3642555903,SE -3642555904,3642556159,UA +3642555792,3642556159,UA 3642556160,3642556415,LV 3642556416,3642560511,CZ 3642560512,3642564607,KG @@ -130478,18 +133674,9 @@ 3642601472,3642605567,RU 3642605568,3642609663,GB 3642609664,3642613759,DZ -3642613760,3642614527,AX -3642614528,3642614783,FI -3642614784,3642615103,AX -3642615104,3642615167,FI -3642615168,3642615295,AX -3642615296,3642615551,FI -3642615552,3642615567,AX -3642615568,3642615583,FI +3642613760,3642615583,FI 3642615584,3642615615,AX -3642615616,3642615679,FI -3642615680,3642616383,AX -3642616384,3642617855,FI +3642615616,3642617855,FI 3642617856,3642621951,JO 3642621952,3642626047,IT 3642626048,3642630143,BE @@ -130737,8 +133924,8 @@ 3645149952,3645150559,DE 3645150560,3645150591,HK 3645150592,3645150615,DE -3645150616,3645150623,US -3645150624,3645150975,DE +3645150616,3645150639,US +3645150640,3645150975,DE 3645150976,3645151231,US 3645151232,3645151487,DE 3645151488,3645151615,MT @@ -130859,9 +134046,9 @@ 3645460480,3645464575,UA 3645464576,3645468671,SE 3645468672,3645472767,RU -3645472768,3645476863,UA 3645476864,3645480959,DE 3645480960,3645485055,RO +3645485056,3645489151,PL 3645489152,3645493247,RU 3645493248,3645501439,IT 3645501440,3645505535,PL @@ -131056,8 +134243,7 @@ 3645763715,3645763715,NL 3645763716,3645763716,DE 3645763717,3645763717,NL -3645763718,3645763718,DE -3645763719,3645763719,NL +3645763718,3645763719,DE 3645763720,3645763720,IT 3645763721,3645763721,DE 3645763722,3645763722,GR @@ -131349,7 +134535,8 @@ 3645764110,3645764110,DK 3645764111,3645764111,DE 3645764112,3645764112,IT -3645764113,3645764114,ES +3645764113,3645764113,ES +3645764114,3645764114,DE 3645764115,3645764115,GB 3645764116,3645764116,GR 3645764117,3645764117,DE @@ -131841,12 +135028,14 @@ 3645779968,3645784063,PS 3645784064,3645788159,NG 3645788160,3645792255,GB +3645792256,3645796351,TR 3645796352,3645800447,CH 3645800448,3645804543,DE 3645804544,3645808639,GB 3645808640,3645812735,DE 3645812736,3645816831,RU 3645816832,3645825023,FI +3645825024,3645829119,RU 3645829120,3645833215,NL 3645833216,3645841407,RU 3645841408,3645845503,BG @@ -131899,7 +135088,9 @@ 3647886188,3647886207,GB 3647886208,3647886271,DE 3647886272,3647886303,GB -3647886304,3647890463,DE +3647886304,3647889663,DE +3647889664,3647889671,BE +3647889672,3647890463,DE 3647890464,3647890471,FR 3647890472,3647912447,DE 3647912448,3647912511,BE @@ -131907,9 +135098,7 @@ 3647916800,3647917055,SE 3647917056,3647917599,DE 3647917600,3647917615,US -3647917616,3647936823,DE -3647936824,3647936827,GB -3647936828,3647936871,DE +3647917616,3647936871,DE 3647936872,3647936879,FR 3647936880,3647954231,DE 3647954232,3647954239,GB @@ -131919,7 +135108,9 @@ 3647957512,3647957519,GB 3647957520,3647959567,DE 3647959568,3647959575,ES -3647959576,3647961215,DE +3647959576,3647959599,DE +3647959600,3647959607,AT +3647959608,3647961215,DE 3647961216,3647961247,IT 3647961248,3647963167,DE 3647963168,3647963183,BE @@ -131960,9 +135151,7 @@ 3647966576,3647966583,DE 3647966584,3647967231,GB 3647967232,3647968255,BE -3647968256,3647968703,FR -3647968704,3647968767,GB -3647968768,3647969279,FR +3647968256,3647969279,FR 3647969280,3647969791,IT 3647969792,3647970303,BE 3647970304,3647971327,FR @@ -131970,12 +135159,9 @@ 3647971672,3647971679,DE 3647971680,3647972191,GB 3647972192,3647972199,DE -3647972200,3647972215,GB -3647972216,3647972223,DE -3647972224,3647972259,GB +3647972200,3647972259,GB 3647972260,3647972263,DE -3647972264,3647972343,GB -3647972344,3647972351,DE +3647972264,3647972351,GB 3647972352,3647973679,IT 3647973680,3647973695,DE 3647973696,3647973783,IT @@ -131986,13 +135172,9 @@ 3647974048,3647974055,DE 3647974056,3647974399,IT 3647974400,3647976447,ES -3647976448,3647976503,BE -3647976504,3647976511,DE -3647976512,3647976559,BE +3647976448,3647976559,BE 3647976560,3647976575,FR -3647976576,3647976607,BE -3647976608,3647976639,BR -3647976640,3647976647,BE +3647976576,3647976647,BE 3647976648,3647976663,DE 3647976664,3647976719,BE 3647976720,3647976727,DE @@ -132004,10 +135186,10 @@ 3647976792,3647976799,DE 3647976800,3647976927,BE 3647976928,3647976935,DE -3647976936,3647977071,BE -3647977072,3647977087,DE -3647977088,3647977119,BE -3647977120,3647977215,DE +3647976936,3647977079,BE +3647977080,3647977087,DE +3647977088,3647977151,BE +3647977152,3647977215,DE 3647977216,3647977471,BE 3647977472,3647977791,GB 3647977792,3647977855,IE @@ -132016,14 +135198,20 @@ 3647978776,3647978783,DE 3647978784,3647978871,NL 3647978872,3647978879,DE -3647978880,3647978887,NL -3647978888,3647979519,DE +3647978880,3647978895,NL +3647978896,3647978911,DE +3647978912,3647978927,NL +3647978928,3647979007,DE +3647979008,3647979136,IT +3647979137,3647979519,DE 3647979520,3647980543,FR 3647980544,3647981055,GB 3647981056,3647981567,IE 3647981568,3647982591,BE 3647982592,3647983615,IT -3647983616,3647995903,DE +3647983616,3647984639,NL +3647984640,3647985151,DK +3647985152,3647995903,DE 3647995904,3648004095,RU 3648004096,3648004607,GB 3648004608,3648006271,RU @@ -132135,7 +135323,9 @@ 3648181024,3648181055,AT 3648181056,3648181215,DE 3648181216,3648181231,RU -3648181232,3648181311,DE +3648181232,3648181247,DE +3648181248,3648181279,IT +3648181280,3648181311,DE 3648181312,3648181343,AT 3648181344,3648181375,DE 3648181376,3648181407,RU @@ -132145,9 +135335,7 @@ 3648181552,3648181567,RU 3648181568,3648181631,DE 3648181632,3648181647,AT -3648181648,3648181655,DE -3648181656,3648181663,IT -3648181664,3648181887,DE +3648181648,3648181887,DE 3648181888,3648181903,AT 3648181904,3648182143,DE 3648182144,3648182159,NL @@ -132165,8 +135353,10 @@ 3648182816,3648182823,US 3648182824,3648182831,RU 3648182832,3648182847,DE -3648182848,3648182911,IT -3648182912,3648183871,DE +3648182848,3648182879,AT +3648182880,3648183551,DE +3648183552,3648183679,BR +3648183680,3648183871,DE 3648183872,3648183935,GB 3648183936,3648184319,DE 3648184320,3648192511,RU @@ -132240,11 +135430,7 @@ 3648417880,3648417919,GB 3648417920,3648418047,AT 3648418048,3648418079,GB -3648418080,3648418095,ES -3648418096,3648418111,GB -3648418112,3648418135,ES -3648418136,3648418143,GB -3648418144,3648418247,ES +3648418080,3648418247,ES 3648418248,3648418255,CH 3648418256,3648418263,ES 3648418264,3648418271,GB @@ -132382,24 +135568,17 @@ 3650244608,3650256895,GB 3650256896,3650265087,DE 3650265088,3650269183,CH -3650269184,3650273279,GB +3650269184,3650273071,GB +3650273072,3650273279,IR 3650273280,3650277375,IT 3650277376,3650281471,IR 3650281472,3650285567,FR 3650285568,3650289663,UA 3650289664,3650297855,RU 3650297856,3650301951,LT -3650301952,3650306623,DE -3650306624,3650306639,GE -3650306640,3650306775,DE +3650301952,3650306775,DE 3650306776,3650306779,GE -3650306780,3650306783,DE -3650306784,3650306791,AT -3650306792,3650306799,DE -3650306800,3650306807,AT -3650306808,3650306943,DE -3650306944,3650306959,GB -3650306960,3650307007,DE +3650306780,3650307007,DE 3650307008,3650307010,GB 3650307011,3650310143,DE 3650310144,3650314239,GB @@ -132416,7 +135595,9 @@ 3650338816,3650342911,FR 3650342912,3650344463,CH 3650344464,3650344479,AT -3650344480,3650344879,CH +3650344480,3650344559,CH +3650344560,3650344575,AT +3650344576,3650344879,CH 3650344880,3650344911,PT 3650344912,3650345879,CH 3650345880,3650345887,IM @@ -132548,7 +135729,9 @@ 3650912640,3650912671,FR 3650912672,3650923103,GB 3650923104,3650923135,FR -3650923136,3650945023,GB +3650923136,3650926591,GB +3650926592,3650929663,ES +3650929664,3650945023,GB 3650945024,3651010559,DK 3651010560,3651076095,GB 3651076096,3651077375,DE @@ -132587,8 +135770,9 @@ 3651087872,3651088127,DE 3651088128,3651088383,IE 3651088384,3651088639,GR -3651088640,3651088895,SG -3651088896,3651098111,DE +3651088640,3651090919,DE +3651090920,3651090959,IE +3651090960,3651098111,DE 3651098112,3651098367,IE 3651098368,3651098623,FR 3651098624,3651101439,DE @@ -132619,7 +135803,8 @@ 3651108864,3651141631,EE 3651141632,3651173375,DE 3651173376,3651173631,ES -3651173632,3651199231,DE +3651173632,3651198975,DE +3651198976,3651199231,GB 3651199232,3651199487,ES 3651199488,3651199743,GB 3651199744,3651200255,ES @@ -132632,8 +135817,13 @@ 3651202048,3651202175,FR 3651202176,3651202303,GB 3651202304,3651202815,ES -3651202816,3651203071,GB -3651203072,3651207167,US +3651202816,3651203583,GB +3651203584,3651203839,FR +3651203840,3651204095,DE +3651204096,3651204223,ES +3651204224,3651204351,DE +3651204352,3651204607,PL +3651204608,3651207167,DE 3651207168,3651207199,GB 3651207200,3651207223,EU 3651207224,3651207295,GB @@ -132766,7 +135956,11 @@ 3651886380,3651886383,CD 3651886384,3651886391,BE 3651886392,3651886395,CD -3651886396,3651886435,BE +3651886396,3651886407,BE +3651886408,3651886415,CD +3651886416,3651886423,BE +3651886424,3651886427,CD +3651886428,3651886435,BE 3651886436,3651886451,CD 3651886452,3651886455,BE 3651886456,3651886459,CD @@ -132776,7 +135970,9 @@ 3651886480,3651886495,CD 3651886496,3651886511,BE 3651886512,3651886527,CD -3651886528,3651887103,BE +3651886528,3651886591,BE +3651886592,3651886847,CD +3651886848,3651887103,BE 3651887104,3651891199,GB 3651891200,3651895295,DE 3651895296,3651899391,GB @@ -132879,56 +136075,29 @@ 3652011520,3652011775,IT 3652011776,3652014079,RU 3652014080,3652018175,SA -3652018176,3652018239,IE -3652018240,3652018303,GB -3652018304,3652018687,IE -3652018688,3652018943,GB -3652018944,3652019169,IE -3652019170,3652019199,GB +3652018176,3652019183,IE +3652019184,3652019199,GB 3652019200,3652019327,IE 3652019328,3652019335,GB -3652019336,3652019351,IE -3652019352,3652019359,GB -3652019360,3652019407,IE -3652019408,3652019423,GB -3652019424,3652019455,IE +3652019336,3652019455,IE 3652019456,3652019471,GB 3652019472,3652019479,IE 3652019480,3652019487,GB -3652019488,3652019527,IE -3652019528,3652019551,GB -3652019552,3652019615,IE -3652019616,3652019631,GB -3652019632,3652019663,IE -3652019664,3652019679,GB -3652019680,3652019687,IE -3652019688,3652019695,GB -3652019696,3652019735,IE -3652019736,3652019751,GB -3652019752,3652019791,IE -3652019792,3652019807,GB -3652019808,3652019815,IE -3652019816,3652019887,GB -3652019888,3652019935,IE -3652019936,3652019951,GB -3652019952,3652020255,IE -3652020256,3652020279,GB -3652020280,3652020351,IE -3652020352,3652020479,GB -3652020480,3652020767,IE -3652020768,3652020799,GB +3652019488,3652019567,IE +3652019568,3652019583,GB +3652019584,3652019599,IE +3652019600,3652019615,GB +3652019616,3652019679,IE +3652019680,3652019687,GB +3652019688,3652019735,IE +3652019736,3652019739,GB +3652019740,3652019751,IE +3652019752,3652019759,GB +3652019760,3652020799,IE 3652020800,3652020863,DE -3652020864,3652020991,GB -3652020992,3652021063,IE -3652021064,3652021087,GB -3652021088,3652021151,IE -3652021152,3652021247,GB -3652021248,3652021423,IE -3652021424,3652021759,GB -3652021760,3652021775,IE -3652021776,3652021791,GB -3652021792,3652021887,IE -3652021888,3652022271,GB +3652020864,3652021415,IE +3652021416,3652021423,BE +3652021424,3652022271,IE 3652022272,3652026367,ES 3652026368,3652028031,DE 3652028032,3652028063,US @@ -133017,10 +136186,12 @@ 3652714496,3652985039,DE 3652985040,3652985047,FR 3652985048,3653029775,DE -3653029776,3653029791,RO +3653029776,3653029791,LU 3653029792,3653039103,DE 3653039104,3653039359,IT -3653039360,3653238783,DE +3653039360,3653039999,DE +3653040000,3653040015,LU +3653040016,3653238783,DE 3653238784,3653334141,CH 3653334142,3653334142,AT 3653334143,3653341871,CH @@ -133048,7 +136219,8 @@ 3653403976,3653403983,A2 3653403984,3653403999,UA 3653404000,3653404008,LB -3653404009,3653404039,A2 +3653404009,3653404015,ZM +3653404016,3653404039,A2 3653404040,3653404047,IQ 3653404048,3653404063,A2 3653404064,3653404071,LB @@ -133085,7 +136257,9 @@ 3653405064,3653405071,IQ 3653405072,3653405095,A2 3653405096,3653405103,NG -3653405104,3653405167,A2 +3653405104,3653405135,A2 +3653405136,3653405143,CD +3653405144,3653405167,A2 3653405168,3653405183,UA 3653405184,3653405439,AT 3653405440,3653407015,A2 @@ -133099,9 +136273,7 @@ 3653407120,3653407127,ZW 3653407128,3653407167,A2 3653407168,3653407231,NG -3653407232,3653407367,A2 -3653407368,3653407375,NG -3653407376,3653407391,A2 +3653407232,3653407391,A2 3653407392,3653407399,NG 3653407400,3653407423,A2 3653407424,3653407487,ZW @@ -133121,23 +136293,35 @@ 3653408048,3653408063,A2 3653408064,3653408071,ZM 3653408072,3653408079,NG -3653408080,3653408143,A2 +3653408080,3653408119,A2 +3653408120,3653408127,NG +3653408128,3653408143,A2 3653408144,3653408151,NG 3653408152,3653408167,A2 3653408168,3653408175,ZW -3653408176,3653408183,A2 +3653408176,3653408183,US 3653408184,3653408191,MW -3653408192,3653408231,A2 +3653408192,3653408199,A2 +3653408200,3653408207,NG +3653408208,3653408231,A2 3653408232,3653408239,KE -3653408240,3653408247,ZM -3653408248,3653408767,A2 +3653408240,3653408247,BF +3653408248,3653408271,A2 +3653408272,3653408287,IQ +3653408288,3653408319,A2 +3653408320,3653408327,IQ +3653408328,3653408767,A2 3653408768,3653409023,CD 3653409024,3653409039,A2 3653409040,3653409047,NG -3653409048,3653409087,A2 +3653409048,3653409063,A2 +3653409064,3653409071,CD +3653409072,3653409087,A2 3653409088,3653409095,CD -3653409096,3653409111,A2 -3653409112,3653409127,NG +3653409096,3653409103,A2 +3653409104,3653409111,MW +3653409112,3653409119,NG +3653409120,3653409127,A2 3653409128,3653409143,CD 3653409144,3653409151,NG 3653409152,3653409191,A2 @@ -133145,7 +136329,9 @@ 3653409200,3653409223,A2 3653409224,3653409231,NG 3653409232,3653409279,A2 -3653409280,3653409535,TZ +3653409280,3653409311,TZ +3653409312,3653409319,IQ +3653409320,3653409535,TZ 3653409536,3653409559,UA 3653409560,3653409567,CM 3653409568,3653409575,UA @@ -133164,11 +136350,10 @@ 3653410096,3653410111,ZW 3653410112,3653410119,A2 3653410120,3653410127,NG -3653410128,3653410143,A2 -3653410144,3653410151,ET +3653410128,3653410151,A2 3653410152,3653410159,KE 3653410160,3653410175,NG -3653410176,3653410183,KE +3653410176,3653410183,US 3653410184,3653410191,MZ 3653410192,3653410199,ZW 3653410200,3653410215,A2 @@ -133289,7 +136474,6 @@ 3653652480,3653656575,RU 3653656576,3653660671,GB 3653660672,3653664767,CZ -3653664768,3653668863,UA 3653668864,3653672959,SE 3653672960,3653681151,RU 3653681152,3653685247,ES @@ -133440,7 +136624,9 @@ 3664004352,3664004607,MY 3664004608,3664004863,SG 3664004864,3664005119,KH -3664005120,3664006143,ID +3664005120,3664005887,ID +3664005888,3664006143,MY +3664006144,3664006399,AU 3664052224,3664084991,NZ 3664084992,3664117759,KR 3664117760,3664248831,HK diff --git a/src/config/torrc.bridge.in b/src/config/torrc.bridge.in new file mode 100644 index 0000000000..557b7adf46 --- /dev/null +++ b/src/config/torrc.bridge.in @@ -0,0 +1,171 @@ +## Configuration file for a typical Tor user +## Last updated 16 July 2009 for Tor 0.2.2.1-alpha. +## (May or may not work for much older or much newer versions of Tor.) +## +## Lines that begin with "## " try to explain what's going on. Lines +## that begin with just "#" are disabled commands: you can enable them +## by removing the "#" symbol. +## +## See 'man tor', or https://www.torproject.org/tor-manual.html, +## for more options you can use in this file. +## +## Tor will look for this file in various places based on your platform: +## https://wiki.torproject.org/noreply/TheOnionRouter/TorFAQ#torrc + + +## Replace this with "SocksPort 0" if you plan to run Tor only as a +## relay, and not make any local application connections yourself. +SocksPort 9050 # what port to open for local application connections +SocksListenAddress 127.0.0.1 # accept connections only from localhost +#SocksListenAddress 192.168.0.1:9100 # listen on this IP:port also + +## Entry policies to allow/deny SOCKS requests based on IP address. +## First entry that matches wins. If no SocksPolicy is set, we accept +## all (and only) requests from SocksListenAddress. +#SocksPolicy accept 192.168.0.0/16 +#SocksPolicy reject * + +## Logs go to stdout at level "notice" unless redirected by something +## else, like one of the below lines. You can have as many Log lines as +## you want. +## +## We advise using "notice" in most cases, since anything more verbose +## may provide sensitive information to an attacker who obtains the logs. +## +## Send all messages of level 'notice' or higher to @LOCALSTATEDIR@/log/tor/notices.log +#Log notice file @LOCALSTATEDIR@/log/tor/notices.log +## Send every possible message to @LOCALSTATEDIR@/log/tor/debug.log +#Log debug file @LOCALSTATEDIR@/log/tor/debug.log +## Use the system log instead of Tor's logfiles +#Log notice syslog +## To send all messages to stderr: +#Log debug stderr + +## Uncomment this to start the process in the background... or use +## --runasdaemon 1 on the command line. This is ignored on Windows; +## see the FAQ entry if you want Tor to run as an NT service. +#RunAsDaemon 1 + +## The directory for keeping all the keys/etc. By default, we store +## things in $HOME/.tor on Unix, and in Application Data\tor on Windows. +#DataDirectory @LOCALSTATEDIR@/lib/tor + +## The port on which Tor will listen for local connections from Tor +## controller applications, as documented in control-spec.txt. +#ControlPort 9051 +## If you enable the controlport, be sure to enable one of these +## authentication methods, to prevent attackers from accessing it. +#HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C +#CookieAuthentication 1 + +############### This section is just for location-hidden services ### + +## Once you have configured a hidden service, you can look at the +## contents of the file ".../hidden_service/hostname" for the address +## to tell people. +## +## HiddenServicePort x y:z says to redirect requests on port x to the +## address y:z. + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 +#HiddenServicePort 22 127.0.0.1:22 + +################ This section is just for relays ##################### +# +## See https://www.torproject.org/docs/tor-doc-relay for details. + +## Required: what port to advertise for incoming Tor connections. +ORPort 9001 +## If you want to listen on a port other than the one advertised +## in ORPort (e.g. to advertise 443 but bind to 9090), uncomment the +## line below too. You'll need to do ipchains or other port forwarding +## yourself to make this work. +#ORListenAddress 0.0.0.0:9090 + +## A handle for your relay, so people don't have to refer to it by key. +Nickname Unnamed + +## The IP address or full DNS name for your relay. Leave commented out +## and Tor will guess. +#Address noname.example.com + +## Define these to limit how much relayed traffic you will allow. Your +## own traffic is still unthrottled. Note that RelayBandwidthRate must +## be at least 20 KB. +#RelayBandwidthRate 100 KB # Throttle traffic to 100KB/s (800Kbps) +#RelayBandwidthBurst 200 KB # But allow bursts up to 200KB/s (1600Kbps) +RelayBandwidthBurst 10485760 +RelayBandwidthRate 5242880 + +## Use these to restrict the maximum traffic per day, week, or month. +## Note that this threshold applies to sent _and_ to received bytes, +## not to their sum: Setting "4 GB" may allow up to 8 GB +## total before hibernating. +## +## Set a maximum of 4 gigabytes each way per period. +#AccountingMax 4 GB +## Each period starts daily at midnight (AccountingMax is per day) +#AccountingStart day 00:00 +## Each period starts on the 3rd of the month at 15:00 (AccountingMax +## is per month) +#AccountingStart month 3 15:00 + +## Contact info to be published in the directory, so we can contact you +## if your relay is misconfigured or something else goes wrong. Google +## indexes this, so spammers might also collect it. +#ContactInfo Random Person <nobody AT example dot com> +## You might also include your PGP or GPG fingerprint if you have one: +#ContactInfo 1234D/FFFFFFFF Random Person <nobody AT example dot com> + +## Uncomment this to mirror directory information for others. Please do +## if you have enough bandwidth. +DirPort 9030 # what port to advertise for directory connections +## If you want to listen on a port other than the one advertised +## in DirPort (e.g. to advertise 80 but bind to 9091), uncomment the line +## below too. You'll need to do ipchains or other port forwarding yourself +## to make this work. +#DirListenAddress 0.0.0.0:9091 +## Uncomment to return an arbitrary blob of html on your DirPort. Now you +## can explain what Tor is if anybody wonders why your IP address is +## contacting them. See contrib/tor-exit-notice.html in Tor's source +## distribution for a sample. +#DirPortFrontPage @CONFDIR@/tor-exit-notice.html + +## Uncomment this if you run more than one Tor relay, and add the identity +## key fingerprint of each Tor relay you control, even if they're on +## different networks. You declare it here so Tor clients can avoid +## using more than one of your relays in a single circuit. See +## https://wiki.torproject.org/noreply/TheOnionRouter/TorFAQ#MultipleServers +#MyFamily $keyid,$keyid,... + +## A comma-separated list of exit policies. They're considered first +## to last, and the first match wins. If you want to _replace_ +## the default exit policy, end this with either a reject *:* or an +## accept *:*. Otherwise, you're _augmenting_ (prepending to) the +## default exit policy. Leave commented to just use the default, which is +## described in the man page or at +## https://www.torproject.org/documentation.html +## +## Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses +## for issues you might encounter if you use the default exit policy. +## +## If certain IPs and ports are blocked externally, e.g. by your firewall, +## you should update your exit policy to reflect this -- otherwise Tor +## users will be told that those destinations are down. +## +#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more +#ExitPolicy accept *:119 # accept nntp as well as default exit policy +#ExitPolicy reject *:* # no exits allowed +# +## Bridge relays (or "bridges") are Tor relays that aren't listed in the +## main directory. Since there is no complete public list of them, even if an +## ISP is filtering connections to all the known Tor relays, they probably +## won't be able to block all the bridges. Also, websites won't treat you +## differently because they won't know you're running Tor. If you can +## be a real relay, please do; but if not, be a bridge! +BridgeRelay 1 +ExitPolicy reject *:* diff --git a/src/config/torrc.complete.in b/src/config/torrc.complete.in deleted file mode 100644 index 310458a5c0..0000000000 --- a/src/config/torrc.complete.in +++ /dev/null @@ -1,533 +0,0 @@ -# $Id$ -# Last updated on $Date$ -#################################################################### -## This config file is divided into four sections. They are: -## 1. Global Options (clients and servers) -## 2. Client Options Only -## 3. Server Options Only -## 4. Directory Server Options (for running your own Tor network) -## 5. Hidden Service Options (clients and servers) -## -## The conventions used are: -## double hash (##) is for summary text about the config option; -## single hash (#) is for the config option; and, -## the config option is always after the text. -#################################################################### - - -## Section 1: Global Options (clients and servers) - -## A token bucket limits the average incoming bandwidth on this node -## to the specified number of bytes per second. (Default: 2MB) -#BandwidthRate N bytes|KB|MB|GB|TB - -## Limit the maximum token bucket size (also known as the burst) to -## the given number of bytes. (Default: 5 MB) -#BandwidthBurst N bytes|KB|MB|GB|TB - -## If set, we will not advertise more than this amount of bandwidth -## for our BandwidthRate. Server operators who want to reduce the -## number of clients who ask to build circuits through them (since -## this is proportional to advertised bandwidth rate) can thus -## reduce the CPU demands on their server without impacting -## network performance. -#MaxAdvertisedBandwidth N bytes|KB|MB|GB|TB - -## If set, Tor will accept connections from the same machine -## (localhost only) on this port, and allow those connections to -## control the Tor process using the Tor Control Protocol -## (described in control-spec.txt). Note: unless you also specify -## one of HashedControlPassword or CookieAuthentication, setting -## this option will cause Tor to allow any process on the local -## host to control it. -#ControlPort Port - -## Don’t allow any connections on the control port except when the -## other process knows the password whose one-way hash is -## hashed_password. You can compute the hash of a password by -## running "tor --hash-password password". -#HashedControlPassword hashed_password - -## If this option is set to 1, don’t allow any connections on the -## control port except when the connecting process knows the -## contents of a file named "control_auth_cookie", which Tor will -## create in its data directory. This authentication method -## should only be used on systems with good filesystem security. -## (Default: 0) -#CookieAuthentication 0|1 - -## Store working data in DIR (Default: /usr/local/var/lib/tor) -#DataDirectory DIR - -## Every time the specified period elapses, Tor downloads a direc- -## tory. A directory contains a signed list of all known servers -## as well as their current liveness status. A value of "0 sec- -## onds" tells Tor to choose an appropriate default. -## (Default: 1 hour for clients, 20 minutes for servers) -#DirFetchPeriod N seconds|minutes|hours|days|weeks - -## Tor only trusts directories signed with one of these keys, and -## uses the given addresses to connect to the trusted directory -## servers. If no DirServer lines are specified, Tor uses the built-in -## defaults (moria1, moria2, tor26), so you can leave this alone unless -## you need to change it. -## -## WARNING! Changing these options will make your Tor behave -## differently from everyone else's, and hurt your anonymity. Even -## uncommenting these lines is a bad idea. They are the defaults now, -## but the defaults may change in the future, leaving you behind. -## -#DirServer moria1 v1 18.244.0.188:9031 FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441 -#DirServer moria2 v1 18.244.0.114:80 719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF -#DirServer tor26 v1 86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D - -## On startup, setgid to this user. -#Group GID - -## Tor will make all its directory requests through this host:port -## (or host:80 if port is not specified), rather than connecting -## directly to any directory servers. -#HttpProxy host[:port] - -## If defined, Tor will use this username:password for Basic Http -## proxy authentication, as in RFC 2617. This is currently the -## only form of Http proxy authentication that Tor supports; feel -## free to submit a patch if you want it to support others. -#HttpProxyAuthenticator username:password - -## Tor will make all its OR (SSL) connections through this -## host:port (or host:443 if port is not specified), via HTTP CON- -## NECT rather than connecting directly to servers. You may want -## to set FascistFirewall to restrict the set of ports you might -## try to connect to, if your Https proxy only allows connecting -## to certain ports. -#HttpsProxy host[:port] - -## If defined, Tor will use this username:password for Basic Https -## proxy authentication, as in RFC 2617. This is currently the -## only form of Https proxy authentication that Tor supports; feel -## free to submit a patch if you want it to support others. -#HttpsProxyAuthenticator username:password - -## To keep firewalls from expiring connections, send a padding -## keepalive cell every NUM seconds on open connections that are -## in use. If the connection has no open circuits, it will instead -## be closed after NUM seconds of idleness. (Default: 5 minutes) -#KeepalivePeriod NUM - -## Send all messages between minSeverity and maxSeverity to the -## standard output stream, the standard error stream, or to the -## system log. (The "syslog" value is only supported on Unix.) -## Recognized severity levels are debug, info, notice, warn, and -## err. If only one severity level is given, all messages of that -## level or higher will be sent to the listed destination. -#Log minSeverity[-maxSeverity] stderr|stdout|syslog - -## As above, but send log messages to the listed filename. The -## "Log" option may appear more than once in a configuration file. -## Messages are sent to all the logs that match their severity -## level. -#Log minSeverity[-maxSeverity] file FILENAME - -## Maximum number of simultaneous sockets allowed. You probably -## don’t need to adjust this. (Default: 1024) -#MaxConn NUM - -## Make all outbound connections originate from the IP address -## specified. This is only useful when you have multiple network -## interfaces, and you want all of Tor’s outgoing connections to -## use a single one. -#OutboundBindAddress IP - -## On startup, write our PID to FILE. On clean shutdown, remove -## FILE. -#PIDFile FILE - -## If 1, Tor forks and daemonizes to the background. (Default: 0) -#RunAsDaemon 0|1 - -## If 1, Tor replaces potentially sensitive strings in the logs -## (e.g. addresses) with the string [scrubbed]. This way logs can -## still be useful, but they don’t leave behind personally identi- -## fying information about what sites a user might have visited. -## (Default: 1) -#SafeLogging 0|1 - -## Every time the specified period elapses, Tor downloads signed -## status information about the current state of known servers. A -## value of "0 seconds" tells Tor to choose an appropriate -## default. (Default: 30 minutes for clients, 15 minutes for -## servers) -#StatusFetchPeriod N seconds|minutes|hours|days|weeks - -## On startup, setuid to this user. -#User UID - -## If non-zero, try to use crypto hardware acceleration when -## available. (Default: 1) -#HardwareAccel 0|1 - - -## Section 2: Client Options Only - -## Where on our circuits should we allow Tor servers that the -## directory servers haven’t authenticated as "verified"? -## (Default: middle,rendezvous) -#AllowUnverifiedNodes entry|exit|middle|introduction|rendezvous|... - -## If set to 1, Tor will under no circumstances run as a server. -## The default is to run as a client unless ORPort is configured. -## (Usually, you don’t need to set this; Tor is pretty smart at -## figuring out whether you are reliable and high-bandwidth enough -## to be a useful server.) -## This option will likely be deprecated in the future; see the -## NoPublish option below. (Default: 0) -#ClientOnly 0|1 - -## A list of preferred nodes to use for the first hop in the -## circuit, if possible. -#EntryNodes nickname,nickname,... - -## A list of preferred nodes to use for the last hop in the -## circuit, if possible. -#ExitNodes nickname,nickname,... - -## A list of nodes to never use when building a circuit. -#ExcludeNodes nickname,nickname,... - -## If 1, Tor will never use any nodes besides those listed in -## "exitnodes" for the last hop of a circuit. -#StrictExitNodes 0|1 - -## If 1, Tor will never use any nodes besides those listed in -## "entrynodes" for the first hop of a circuit. -#StrictEntryNodes 0|1 - -## If 1, Tor will only create outgoing connections to ORs running -## on ports that your firewall allows (defaults to 80 and 443; see -## FirewallPorts). This will allow you to run Tor as a client -## behind a firewall with restrictive policies, but will not allow -## you to run as a server behind such a firewall. -#FascistFirewall 0|1 - -## A list of ports that your firewall allows you to connect to. -## Only used when FascistFirewall is set. (Default: 80, 443) -#FirewallPorts PORTS - -## A comma-separated list of IPs that your firewall allows you to -## connect to. Only used when FascistFirewall is set. The format -## is as for the addresses in ExitPolicy. -## For example, ’FirewallIPs 99.0.0.0/8, *:80’ means that your -## firewall allows connections to everything inside net 99, and -## to port 80 outside. -#FirewallIPs ADDR[/MASK][:PORT]... - -## A list of ports for services that tend to have long-running -## connections (e.g. chat and interactive shells). Circuits for -## streams that use these ports will contain only high-uptime -## nodes, to reduce the chance that a node will go down before the -## stream is finished. (Default: 21, 22, 706, 1863, 5050, 5190, -## 5222, 5223, 6667, 8300, 8888) -#LongLivedPorts PORTS - -## When a request for address arrives to Tor, it will rewrite it -## to newaddress before processing it. For example, if you always -## want connections to www.indymedia.org to exit via torserver -## (where torserver is the nickname of the server), -## use "MapAddress www.indymedia.org www.indymedia.org.torserver.exit". -#MapAddress address newaddress - -## Every NUM seconds consider whether to build a new circuit. -## (Default: 30 seconds) -#NewCircuitPeriod NUM - -## Feel free to reuse a circuit that was first used at most NUM -## seconds ago, but never attach a new stream to a circuit that is -## too old. (Default: 10 minutes) -#MaxCircuitDirtiness NUM - -## The named Tor servers constitute a "family" of similar or co- -## administered servers, so never use any two of them in the same -## circuit. Defining a NodeFamily is only needed when a server -## doesn’t list the family itself (with MyFamily). This option can -## be used multiple times. -#NodeFamily nickname,nickname,... - -## A list of preferred nodes to use for the rendezvous point, if -## possible. -#RendNodes nickname,nickname,... - -## A list of nodes to never use when choosing a rendezvous point. -#RendExcludeNodes nickname,nickname,... - -## Advertise this port to listen for connections from SOCKS-speak- -## ing applications. Set this to 0 if you don’t want to allow -## application connections. (Default: 9050) -#SOCKSPort PORT - -## Bind to this address to listen for connections from SOCKS- -## speaking applications. (Default: 127.0.0.1) You can also spec- -## ify a port (e.g. 192.168.0.1:9100). This directive can be spec- -## ified multiple times to bind to multiple addresses/ports. -#SOCKSBindAddress IP[:PORT] - -## Set an entrance policy for this server, to limit who can con- -## nect to the SOCKS ports. The policies have the same form as -## exit policies below. -#SOCKSPolicy policy,policy,... - -## For each value in the comma separated list, Tor will track -## recent connections to hosts that match this value and attempt -## to reuse the same exit node for each. If the value is prepended -## with a ’.’, it is treated as matching an entire domain. If one -## of the values is just a ’.’, it means match everything. This -## option is useful if you frequently connect to sites that will -## expire all your authentication cookies (ie log you out) if your -## IP address changes. Note that this option does have the disad- -## vantage of making it more clear that a given history is associ- -## ated with a single user. However, most people who would wish to -## observe this will observe it through cookies or other protocol- -## specific means anyhow. -#TrackHostExits host,.domain,... - -## Since exit servers go up and down, it is desirable to expire -## the association between host and exit server after NUM seconds. -## The default is 1800 seconds (30 minutes). -#TrackHostExitsExpire NUM - -## If this option is set to 1, we pick a few entry servers as our -## "helpers", and try to use only those fixed entry servers. This -## is desirable, because constantly changing servers increases the -## odds that an adversary who owns some servers will observe a -## fraction of your paths. (Defaults to 0; will eventually -## default to 1.) -#UseHelperNodes 0|1 - -## If UseHelperNodes is set to 1, we will try to pick a total of -## NUM helper nodes as entries for our circuits. (Defaults to 3.) -#NumHelperNodes NUM - - -## Section 3: Server Options Only - -## The IP or fqdn of this server (e.g. moria.mit.edu). You can -## leave this unset, and Tor will guess your IP. -#Address address - -## Administrative contact information for server. -#ContactInfo email_address - -## Set an exit policy for this server. Each policy is of the form -## "accept|reject ADDR[/MASK][:PORT]". If /MASK is omitted then -## this policy just applies to the host given. Instead of giving -## a host or network you can also use "*" to denote the universe -## (0.0.0.0/0). PORT can be a single port number, an interval of -## ports "FROM_PORT-TO_PORT", or "*". If PORT is omitted, that -## means "*". -## -## For example, "reject 127.0.0.1:*,reject 192.168.1.0/24:*,accept -## *:*" would reject any traffic destined for localhost and any -## 192.168.1.* address, but accept anything else. -## -## This directive can be specified multiple times so you don’t -## have to put it all on one line. -## -## See RFC 3330 for more details about internal and reserved IP -## address space. Policies are considered first to last, and the -## first match wins. If you want to _replace_ the default exit -## policy, end your exit policy with either a reject *:* or an -## accept *:*. Otherwise, you’re _augmenting_ (prepending to) the -## default exit policy. The default exit policy is: -## reject 0.0.0.0/8 -## reject 169.254.0.0/16 -## reject 127.0.0.0/8 -## reject 192.168.0.0/16 -## reject 10.0.0.0/8 -## reject 172.16.0.0/12 -## reject *:25 -## reject *:119 -## reject *:135-139 -## reject *:445 -## reject *:1214 -## reject *:4661-4666 -## reject *:6346-6429 -## reject *:6699 -## reject *:6881-6999 -## accept *:* -#ExitPolicy policy,policy,... - -## If you have more than this number of onionskins queued for -## decrypt, reject new ones. (Default: 100) -#MaxOnionsPending NUM - -## Declare that this Tor server is controlled or administered by a -## group or organization identical or similar to that of the other -## named servers. When two servers both declare that they are in -## the same ’family’, Tor clients will not use them in the same -## circuit. (Each server only needs to list the other servers in -## its family; it doesn’t need to list itself, but it won’t hurt.) -#MyFamily nickname,nickname,... - -## Set the server’s nickname to ’name’. -#Nickname name - -## If you set NoPublish 1, Tor will act as a server if you have an -## ORPort defined, but it will not publish its descriptor to the -## dirservers. This option is useful if you're testing out your -## server, or if you're using alternate dirservers (e.g. for other -## Tor networks such as Blossom). (Default: 0) -#NoPublish 0|1 - -## How many processes to use at once for decrypting onionskins. -## (Default: 1) -#NumCPUs num - -## Advertise this port to listen for connections from Tor clients -## and servers. -#ORPort PORT - -## Bind to this IP address to listen for connections from Tor -## clients and servers. If you specify a port, bind to this port -## rather than the one specified in ORPort. (Default: 0.0.0.0) -#ORBindAddress IP[:PORT] - -## Whenever an outgoing connection tries to connect to one of a -## given set of addresses, connect to target (an address:port -## pair) instead. The address pattern is given in the same format -## as for an exit policy. The address translation applies after -## exit policies are applied. Multiple RedirectExit options can -## be used: once any one has matched successfully, no subsequent -## rules are considered. You can specify that no redirection is -## to be performed on a given set of addresses by using the spe- -## cial target string "pass", which prevents subsequent rules from -## being considered. -#RedirectExit pattern target - -## When we get a SIGINT and we're a server, we begin shutting -## down: we close listeners and start refusing new circuits. After -## NUM seconds, we exit. If we get a second SIGINT, we exit imme- -## diately. (Default: 30 seconds) -#ShutdownWaitLengthNUM - -## Every time the specified period elapses, Tor uploads its server -## descriptors to the directory servers. This information is also -## uploaded whenever it changes. (Default: 20 minutes) -#DirPostPeriod N seconds|minutes|hours|days|weeks - -## A token bucket limits the average relayed bandwidth (server -## traffic only, not client traffic) on this node to the specified -## number of bytes per second. -#RelayBandwidthRate N bytes|KB|MB|GB|TB - -## Limit the maximum token bucket size (also known as the burst) for -## relayed traffic (server traffic only, not client traffic) to the -## given number of bytes. -#RelayBandwidthBurst N bytes|KB|MB|GB|TB - -## Never send more than the specified number of bytes in a given -## accounting period, or receive more than that number in the -## period. For example, with AccountingMax set to 1 GB, a server -## could send 900 MB and receive 800 MB and continue running. It -## will only hibernate once one of the two reaches 1 GB. When the -## number of bytes is exhausted, Tor will hibernate until some -## time in the next accounting period. To prevent all servers -## from waking at the same time, Tor will also wait until a random -## point in each period before waking up. If you have bandwidth -## cost issues, enabling hibernation is preferable to setting a -## low bandwidth, since it provides users with a collection of -## fast servers that are up some of the time, which is more useful -## than a set of slow servers that are always "available". -#AccountingMax N bytes|KB|MB|GB|TB - -## Specify how long accounting periods last. If month is given, -## each accounting period runs from the time HH:MM on the dayth -## day of one month to the same day and time of the next. (The -## day must be between 1 and 28.) If week is given, each account- -## ing period runs from the time HH:MM of the dayth day of one -## week to the same day and time of the next week, with Monday as -## day 1 and Sunday as day 7. If day is given, each accounting -## period runs from the time HH:MM each day to the same time on -## the next day. All times are local, and given in 24-hour time. -## (Defaults to "month 1 0:00".) -#AccountingStart day|week|month [day] HH:MM - - -## Section 4: Directory Server Options (for running your own Tor -## network) - -## When this option is set to 1, Tor operates as an authoritative -## directory server. Instead of caching the directory, it gener- -## ates its own list of good servers, signs it, and sends that to -## the clients. Unless the clients already have you listed as a -## trusted directory, you probably do not want to set this option. -## Please coordinate with the other admins at -## tor-ops@freehaven.net if you think you should be a directory. -#AuthoritativeDirectory 0|1 - -## Advertise the directory service on this port. -#DirPort PORT - -## Bind the directory service to this address. If you specify a -## port, bind to this port rather than the one specified in DirPort. -## (Default: 0.0.0.0) -#DirBindAddress IP[:PORT] - -## Set an entrance policy for this server, to limit who can con- -## nect to the directory ports. The policies have the same form -## as exit policies above. -#DirPolicy policy,policy,... - -## STRING is a command-separated list of Tor versions currently -## believed to be safe. The list is included in each directory, -## and nodes which pull down the directory learn whether they need -## to upgrade. This option can appear multiple times: the values -## from multiple lines are spliced together. -#RecommendedVersions STRING - - -## If set to 1, Tor will accept router descriptors with arbitrary -## "Address" elements. Otherwise, if the address is not an IP or -## is a private IP, it will reject the router descriptor. Defaults -## to 0. -#DirAllowPrivateAddresses 0|1 - -## If set to 1, Tor tries to build circuits through all of the -## servers it knows about, so it can tell which are up and which -## are down. This option is only useful for authoritative direc- -## tories, so you probably don't want to use it. -#RunTesting 0|1 - -## Section 5: Hidden Service Options (clients and servers) - -## Store data files for a hidden service in DIRECTORY. Every hid- -## den service must have a separate directory. You may use this -## option multiple times to specify multiple services. -#HiddenServiceDir DIRECTORY - -## Configure a virtual port VIRTPORT for a hidden service. You -## may use this option multiple times; each time applies to the -## service using the most recent hiddenservicedir. By default, -## this option maps the virtual port to the same port on -## 127.0.0.1. You may override the target port, address, or both -## by specifying a target of addr, port, or addr:port. -#HiddenServicePort VIRTPORT [TARGET] - -## If possible, use the specified nodes as introduction points for -## the hidden service. If this is left unset, Tor will be smart -## and pick some reasonable ones; most people can leave this unset. -#HiddenServiceNodes nickname,nickname,... - -## Do not use the specified nodes as introduction points for the -## hidden service. In normal use there is no reason to set this. -#HiddenServiceExcludeNodes nickname,nickname,... - -## Publish the given rendezvous service descriptor versions for the -## hidden service. -#HiddenServiceVersion 0,2 - -## Every time the specified period elapses, Tor uploads any ren- -## dezvous service descriptors to the directory servers. This -## information is also uploaded whenever it changes. -## (Default: 20 minutes) -#RendPostPeriod N seconds|minutes|hours|days|weeks -# diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in index d0b1ee1591..f0c78ce5a9 100644 --- a/src/config/torrc.sample.in +++ b/src/config/torrc.sample.in @@ -1,5 +1,5 @@ ## Configuration file for a typical Tor user -## Last updated 12 April 2009 for Tor 0.2.1.14-rc. +## Last updated 16 July 2009 for Tor 0.2.2.1-alpha. ## (May or may not work for much older or much newer versions of Tor.) ## ## Lines that begin with "## " try to explain what's going on. Lines @@ -95,9 +95,22 @@ SocksListenAddress 127.0.0.1 # accept connections only from localhost ## Define these to limit how much relayed traffic you will allow. Your ## own traffic is still unthrottled. Note that RelayBandwidthRate must -## be at least 20 KBytes. -#RelayBandwidthRate 100 KBytes # Throttle traffic to 100KB/s (800Kbps) -#RelayBandwidthBurst 200 KBytes # But allow bursts up to 200KB/s (1600Kbps) +## be at least 20 KB. +#RelayBandwidthRate 100 KB # Throttle traffic to 100KB/s (800Kbps) +#RelayBandwidthBurst 200 KB # But allow bursts up to 200KB/s (1600Kbps) + +## Use these to restrict the maximum traffic per day, week, or month. +## Note that this threshold applies to sent _and_ to received bytes, +## not to their sum: Setting "4 GB" may allow up to 8 GB +## total before hibernating. +## +## Set a maximum of 4 gigabytes each way per period. +#AccountingMax 4 GB +## Each period starts daily at midnight (AccountingMax is per day) +#AccountingStart day 00:00 +## Each period starts on the 3rd of the month at 15:00 (AccountingMax +## is per month) +#AccountingStart month 3 15:00 ## Contact info to be published in the directory, so we can contact you ## if your relay is misconfigured or something else goes wrong. Google @@ -116,8 +129,9 @@ SocksListenAddress 127.0.0.1 # accept connections only from localhost #DirListenAddress 0.0.0.0:9091 ## Uncomment to return an arbitrary blob of html on your DirPort. Now you ## can explain what Tor is if anybody wonders why your IP address is -## contacting them. See contrib/tor-exit-notice.html for a sample. -#DirPortFrontPage /etc/tor/exit-notice.html +## contacting them. See contrib/tor-exit-notice.html in Tor's source +## distribution for a sample. +#DirPortFrontPage @CONFDIR@/tor-exit-notice.html ## Uncomment this if you run more than one Tor relay, and add the identity ## key fingerprint of each Tor relay you control, even if they're on diff --git a/src/or/Makefile.am b/src/or/Makefile.am index ad2476ff15..a9ac3cdee1 100644 --- a/src/or/Makefile.am +++ b/src/or/Makefile.am @@ -1,8 +1,5 @@ -TESTS = test - -noinst_PROGRAMS = test - bin_PROGRAMS = tor +noinst_LIBRARIES = libtor.a if BUILD_NT_SERVICES tor_platform_source=ntmain.c @@ -10,18 +7,30 @@ else tor_platform_source= endif -EXTRA_DIST=ntmain.c +EXTRA_DIST=ntmain.c or_sha1.i + +if USE_EXTERNAL_EVDNS +evdns_source= +else +evdns_source=eventdns.c +endif -tor_SOURCES = buffers.c circuitbuild.c circuitlist.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 $(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 \ - eventdns.c \ - tor_main.c + $(evdns_source) config_codedigest.c + +#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \ +# ../common/libor-event.a + + +tor_SOURCES = tor_main.c AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ @@ -32,76 +41,48 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ # 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 = ../common/libor.a ../common/libor-crypto.a \ - -lz @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ -test_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) \ - 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 \ - eventdns.c \ - test_data.c test.c +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@ -test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ - @TOR_LDFLAGS_libevent@ -test_LDADD = ../common/libor.a ../common/libor-crypto.a \ - -lz @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 -noinst_HEADERS = or.h eventdns.h eventdns_tor.h micro-revision.i +config_codedigest.o: or_sha1.i tor_main.o: micro-revision.i micro-revision.i: FORCE - @svkdir=$$SVKROOT; \ - if test "x$$svkdir" = x ; then \ - svkdir=$$HOME/.svk; \ - fi; \ - if test -d ../../.git && test -x "`which git 2>&1;true`" ; then \ - if test -d ../../.git/svn && test -x "`which git-svn 2>&1;true`" ; then \ - git-svn info ../../README | \ - sed -n 's/^Revision: \([0-9][0-9]*\).*/"\1"/p' \ - > micro-revision.tmp \ - || true; \ - fi; \ - elif test -d ../../.svn && test -x "`which svn 2>&1;true`" ; then \ - svn info ../.. | \ - sed -n 's/^Revision: \([0-9][0-9]*\).*/"\1"/p' > micro-revision.tmp \ - || true; \ - elif test -x "`which svk 2>&1;true`" && test -d $$svkdir/local; then \ - location=../..; \ - rev=x; \ - while test x$$rev = xx; do \ - x=`svk info $$location | \ - sed -n 's/^Mirrored From:.*, Rev\. \([0-9][0-9]*\)/\1/p'`; \ - if test x$$x != x; then \ - rev=$$x; \ - break; \ - else \ - loc=`svk info $$location | \ - sed -n 's/^Copied From: \(.*\), Rev\. [0-9][0-9]*/\1/p' | \ - head -1`; \ - if test x$$loc = x; then \ - break; \ - else \ - location=/$$loc; \ - fi; \ - fi; \ - done; \ - if test x$$rev != xx; then \ - echo \"$$rev\" > micro-revision.tmp; \ - fi; \ - fi; \ - if test ! -f micro-revision.tmp ; then \ - if test ! -f micro-revision.i ; then \ - echo '""' > micro-revision.i; \ - fi; \ - elif test ! -f micro-revision.i || \ + @rm -f micro-revision.tmp; \ + if test -d ../../.git && test -x "`which git 2>&1;true`"; then \ + HASH="`git rev-parse --short=16 HEAD`"; \ + echo \"$$HASH\" > micro-revision.tmp; \ + fi; \ + if test ! -f micro-revision.tmp ; then \ + if test ! -f micro-revision.i ; then \ + echo '""' > micro-revision.i; \ + fi; \ + elif test ! -f micro-revision.i || \ test x"`cat micro-revision.tmp`" != x"`cat micro-revision.i`"; then \ - mv micro-revision.tmp micro-revision.i; \ + mv micro-revision.tmp micro-revision.i; \ fi; true +or_sha1.i: $(tor_SOURCES) + if test "@SHA1SUM@" != none; then \ + @SHA1SUM@ $(tor_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; \ + else \ + rm or_sha1.i; \ + touch or_sha1.i; \ + fi + +CLEANFILES = micro-revision.i + #Dummy target to ensure that micro-revision.i _always_ gets built. FORCE: diff --git a/src/or/buffers.c b/src/or/buffers.c index f26c202198..f84fb45c64 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -12,6 +12,14 @@ **/ #define BUFFERS_PRIVATE #include "or.h" +#include "buffers.h" +#include "config.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "reasons.h" +#include "../common/util.h" +#include "../common/torlog.h" #ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -145,10 +153,13 @@ get_freelist(size_t alloc) /** Deallocate a chunk or put it on a freelist */ static void -chunk_free(chunk_t *chunk) +chunk_free_unchecked(chunk_t *chunk) { - size_t alloc = CHUNK_ALLOC_SIZE(chunk->memlen); - chunk_freelist_t *freelist = get_freelist(alloc); + size_t alloc; + chunk_freelist_t *freelist; + + alloc = CHUNK_ALLOC_SIZE(chunk->memlen); + freelist = get_freelist(alloc); if (freelist && freelist->cur_length < freelist->max_length) { chunk->next = freelist->head; freelist->head = chunk; @@ -193,7 +204,7 @@ chunk_new_with_alloc_size(size_t alloc) } #else static void -chunk_free(chunk_t *chunk) +chunk_free_unchecked(chunk_t *chunk) { tor_free(chunk); } @@ -259,13 +270,22 @@ buf_shrink_freelists(int free_all) int n_to_free = free_all ? freelists[i].cur_length : (freelists[i].lowest_length - slack); int n_to_skip = freelists[i].cur_length - n_to_free; + int orig_length = freelists[i].cur_length; int orig_n_to_free = n_to_free, n_freed=0; int orig_n_to_skip = n_to_skip; int new_length = n_to_skip; chunk_t **chp = &freelists[i].head; chunk_t *chunk; while (n_to_skip) { - tor_assert((*chp)->next); + if (! (*chp)->next) { + log_warn(LD_BUG, "I wanted to skip %d chunks in the freelist for " + "%d-byte chunks, but only found %d. (Length %d)", + orig_n_to_skip, (int)freelists[i].alloc_size, + orig_n_to_skip-n_to_skip, freelists[i].cur_length); + assert_freelist_ok(&freelists[i]); + goto done; + } + // tor_assert((*chp)->next); chp = &(*chp)->next; --n_to_skip; } @@ -290,13 +310,15 @@ buf_shrink_freelists(int free_all) } // tor_assert(!n_to_free); freelists[i].cur_length = new_length; - log_info(LD_MM, "Cleaned freelist for %d-byte chunks: kept %d, " - "dropped %d.", - (int)freelists[i].alloc_size, orig_n_to_skip, orig_n_to_free); + log_info(LD_MM, "Cleaned freelist for %d-byte chunks: original " + "length %d, kept %d, dropped %d.", + (int)freelists[i].alloc_size, orig_length, + orig_n_to_skip, orig_n_to_free); } freelists[i].lowest_length = freelists[i].cur_length; assert_freelist_ok(&freelists[i]); } + done: enable_control_logging(); #else (void) free_all; @@ -404,7 +426,7 @@ buf_pullup(buf_t *buf, size_t bytes, int nulterminate) dest->next = src->next; if (buf->tail == src) buf->tail = dest; - chunk_free(src); + chunk_free_unchecked(src); } else { memcpy(CHUNK_WRITE_PTR(dest), src->data, n); dest->datalen += n; @@ -450,7 +472,7 @@ buf_remove_from_front(buf_t *buf, size_t n) buf->head = victim->next; if (buf->tail == victim) buf->tail = NULL; - chunk_free(victim); + chunk_free_unchecked(victim); } } check(); @@ -484,7 +506,7 @@ buf_clear(buf_t *buf) buf->datalen = 0; for (chunk = buf->head; chunk; chunk = next) { next = chunk->next; - chunk_free(chunk); + chunk_free_unchecked(chunk); } buf->head = buf->tail = NULL; } @@ -523,6 +545,8 @@ buf_slack(const buf_t *buf) void buf_free(buf_t *buf) { + if (!buf) + return; buf_clear(buf); buf->magic = 0xdeadbeef; tor_free(buf); @@ -1275,6 +1299,43 @@ fetch_from_buf_http(buf_t *buf, return 1; } +/** + * Wait this many seconds before warning the user about using SOCKS unsafely + * again (requires that WarnUnsafeSocks is turned on). */ +#define SOCKS_WARN_INTERVAL 5 + +/** Warn that the user application has made an unsafe socks request using + * protocol <b>socks_protocol</b> on port <b>port</b>. Don't warn more than + * once per SOCKS_WARN_INTERVAL, unless <b>safe_socks</b> is set. */ +static void +log_unsafe_socks_warning(int socks_protocol, const char *address, + uint16_t port, int safe_socks) +{ + static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL); + + or_options_t *options = get_options(); + char *m = NULL; + if (! options->WarnUnsafeSocks) + return; + if (safe_socks || (m = rate_limit_log(&socks_ratelim, approx_time()))) { + log_warn(LD_APP, + "Your application (using socks%d to port %d) is giving " + "Tor only an IP address. Applications that do DNS resolves " + "themselves may leak information. Consider using Socks4A " + "(e.g. via privoxy or socat) instead. For more information, " + "please see https://wiki.torproject.org/TheOnionRouter/" + "TorFAQ#SOCKSAndDNS.%s%s", + socks_protocol, + (int)port, + safe_socks ? " Rejecting." : "", + m ? m : ""); + tor_free(m); + } + control_event_client_status(LOG_WARN, + "DANGEROUS_SOCKS PROTOCOL=SOCKS%d ADDRESS=%s:%d", + socks_protocol, address, (int)port); +} + /** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one * of the forms * - socks4: "socksheader username\\0" @@ -1313,10 +1374,6 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, char *next, *startaddr; struct in_addr in; - /* If the user connects with socks4 or the wrong variant of socks5, - * then log a warning to let him know that it might be unwise. */ - static int have_warned_about_unsafe_socks = 0; - if (buf->datalen < 2) /* version and another byte */ return 0; @@ -1396,21 +1453,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, req->port = ntohs(get_uint16(buf->head->data+4+addrlen)); buf_remove_from_front(buf, 6+addrlen); if (req->command != SOCKS_COMMAND_RESOLVE_PTR && - !addressmap_have_mapping(req->address,0) && - !have_warned_about_unsafe_socks) { - log_warn(LD_APP, - "Your application (using socks5 to port %d) is giving " - "Tor only an IP address. Applications that do DNS resolves " - "themselves may leak information. Consider using Socks4A " - "(e.g. via privoxy or socat) instead. For more information, " - "please see http://wiki.noreply.org/noreply/TheOnionRouter/" - "TorFAQ#SOCKSAndDNS.%s", req->port, - safe_socks ? " Rejecting." : ""); - /*have_warned_about_unsafe_socks = 1;*/ - /*(for now, warn every time)*/ - control_event_client_status(LOG_WARN, - "DANGEROUS_SOCKS PROTOCOL=SOCKS5 ADDRESS=%s:%d", - req->address, req->port); + !addressmap_have_mapping(req->address,0)) { + log_unsafe_socks_warning(5, req->address, req->port, safe_socks); if (safe_socks) return -1; } @@ -1475,8 +1519,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, return -1; } - req->port = ntohs(*(uint16_t*)(buf->head->data+2)); - destip = ntohl(*(uint32_t*)(buf->head->data+4)); + req->port = ntohs(get_uint16(buf->head->data+2)); + destip = ntohl(get_uint32(buf->head->data+4)); if ((!req->port && req->command!=SOCKS_COMMAND_RESOLVE) || !destip) { log_warn(LD_APP,"socks4: Port or DestIP is zero. Rejecting."); return -1; @@ -1491,7 +1535,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, return -1; } log_debug(LD_APP, - "socks4: successfully read destip (%s)", safe_str(tmpbuf)); + "socks4: successfully read destip (%s)", + safe_str_client(tmpbuf)); socks4_prot = socks4; } @@ -1509,20 +1554,9 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, startaddr = NULL; if (socks4_prot != socks4a && - !addressmap_have_mapping(tmpbuf,0) && - !have_warned_about_unsafe_socks) { - log_warn(LD_APP, - "Your application (using socks4 to port %d) is giving Tor " - "only an IP address. Applications that do DNS resolves " - "themselves may leak information. Consider using Socks4A " - "(e.g. via privoxy or socat) instead. For more information, " - "please see http://wiki.noreply.org/noreply/TheOnionRouter/" - "TorFAQ#SOCKSAndDNS.%s", req->port, - safe_socks ? " Rejecting." : ""); - /*have_warned_about_unsafe_socks = 1;*/ /*(for now, warn every time)*/ - control_event_client_status(LOG_WARN, - "DANGEROUS_SOCKS PROTOCOL=SOCKS4 ADDRESS=%s:%d", - tmpbuf, req->port); + !addressmap_have_mapping(tmpbuf,0)) { + log_unsafe_socks_warning(4, tmpbuf, req->port, safe_socks); + if (safe_socks) return -1; } @@ -1614,6 +1648,132 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, } } +/** Inspect a reply from SOCKS server stored in <b>buf</b> according + * to <b>state</b>, removing the protocol data upon success. Return 0 on + * incomplete response, 1 on success and -1 on error, in which case + * <b>reason</b> is set to a descriptive message (free() when finished + * with it). + * + * As a special case, 2 is returned when user/pass is required + * during SOCKS5 handshake and user/pass is configured. + */ +int +fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) +{ + unsigned char *data; + size_t addrlen; + + if (buf->datalen < 2) + return 0; + + buf_pullup(buf, 128, 0); + tor_assert(buf->head && buf->head->datalen >= 2); + + data = (unsigned char *) buf->head->data; + + switch (state) { + case PROXY_SOCKS4_WANT_CONNECT_OK: + /* Wait for the complete response */ + if (buf->head->datalen < 8) + return 0; + + if (data[1] != 0x5a) { + *reason = tor_strdup(socks4_response_code_to_string(data[1])); + return -1; + } + + /* Success */ + buf_remove_from_front(buf, 8); + return 1; + + case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE: + /* we don't have any credentials */ + if (data[1] != 0x00) { + *reason = tor_strdup("server doesn't support any of our " + "available authentication methods"); + return -1; + } + + log_info(LD_NET, "SOCKS 5 client: continuing without authentication"); + buf_clear(buf); + return 1; + + case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929: + /* we have a username and password. return 1 if we can proceed without + * providing authentication, or 2 otherwise. */ + switch (data[1]) { + case 0x00: + log_info(LD_NET, "SOCKS 5 client: we have auth details but server " + "doesn't require authentication."); + buf_clear(buf); + return 1; + case 0x02: + log_info(LD_NET, "SOCKS 5 client: need authentication."); + buf_clear(buf); + return 2; + /* fall through */ + } + + *reason = tor_strdup("server doesn't support any of our available " + "authentication methods"); + return -1; + + case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK: + /* handle server reply to rfc1929 authentication */ + if (data[1] != 0x00) { + *reason = tor_strdup("authentication failed"); + return -1; + } + + log_info(LD_NET, "SOCKS 5 client: authentication successful."); + buf_clear(buf); + return 1; + + case PROXY_SOCKS5_WANT_CONNECT_OK: + /* response is variable length. BND.ADDR, etc, isn't needed + * (don't bother with buf_pullup()), but make sure to eat all + * the data used */ + + /* wait for address type field to arrive */ + if (buf->datalen < 4) + return 0; + + switch (data[3]) { + case 0x01: /* ip4 */ + addrlen = 4; + break; + case 0x04: /* ip6 */ + addrlen = 16; + break; + case 0x03: /* fqdn (can this happen here?) */ + if (buf->datalen < 5) + return 0; + addrlen = 1 + data[4]; + break; + default: + *reason = tor_strdup("invalid response to connect request"); + return -1; + } + + /* wait for address and port */ + if (buf->datalen < 6 + addrlen) + return 0; + + if (data[1] != 0x00) { + *reason = tor_strdup(socks5_response_code_to_string(data[1])); + return -1; + } + + buf_remove_from_front(buf, 6 + addrlen); + return 1; + } + + /* shouldn't get here... */ + tor_assert(0); + + return -1; +} + /** Return 1 iff buf looks more like it has an (obsolete) v0 controller * command on it than any valid v1 controller command. */ int diff --git a/src/or/buffers.h b/src/or/buffers.h new file mode 100644 index 0000000000..8fd403d954 --- /dev/null +++ b/src/or/buffers.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file buffers.h + * \brief Header file for buffers.c. + **/ + +#ifndef _TOR_BUFFERS_H +#define _TOR_BUFFERS_H + +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); +void buf_shrink(buf_t *buf); +void buf_shrink_freelists(int free_all); +void buf_dump_freelist_sizes(int severity); + +size_t buf_datalen(const buf_t *buf); +size_t buf_allocation(const buf_t *buf); +size_t buf_slack(const buf_t *buf); + +int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof, + int *socket_error); +int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf); + +int flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen); +int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen); + +int write_to_buf(const char *string, size_t string_len, buf_t *buf); +int write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state, + const char *data, size_t data_len, int done); +int move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen); +int fetch_from_buf(char *string, size_t string_len, buf_t *buf); +int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto); +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); +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); +int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len); + +int peek_buf_has_control0_command(buf_t *buf); + +void assert_buf_ok(buf_t *buf); + +#ifdef BUFFERS_PRIVATE +int buf_find_string_offset(const buf_t *buf, const char *s, size_t n); +#endif + +#endif + diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 0ec5aaef58..2fe750ea5b 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -9,9 +9,45 @@ * \brief The actual details of building circuits. **/ +#define CIRCUIT_PRIVATE + #include "or.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "directory.h" +#include "main.h" +#include "networkstatus.h" +#include "onion.h" +#include "policies.h" +#include "relay.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" +#include "crypto.h" +#undef log +#include <math.h> + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#define CBT_BIN_TO_MS(bin) ((bin)*CBT_BIN_WIDTH + (CBT_BIN_WIDTH/2)) /********* START VARIABLES **********/ +/** Global list of circuit build times */ +// FIXME: Add this as a member for entry_guard_t instead of global? +// Then we could do per-guard statistics, as guards are likely to +// vary in their own latency. The downside of this is that guards +// can change frequently, so we'd be building a lot more circuits +// most likely. +circuit_build_times_t circ_times; /** A global list of all circuits at this hop. */ extern circuit_t *global_circuitlist; @@ -47,6 +83,10 @@ static smartlist_t *entry_guards = NULL; * and those changes need to be flushed to disk. */ static int entry_guards_dirty = 0; +/** If set, we're running the unit tests: we should avoid clobbering + * our state file or accessing get_options() or get_or_state() */ +static int unit_tests = 0; + /********* END VARIABLES ************/ static int circuit_deliver_create_cell(circuit_t *circ, @@ -59,6 +99,1236 @@ static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice); static void entry_guards_changed(void); +static int +circuit_build_times_disabled(void) +{ + if (unit_tests) { + return 0; + } else { + int consensus_disabled = networkstatus_get_param(NULL, "cbtdisabled", + 0); + int config_disabled = !get_options()->LearnCircuitBuildTimeout; + int dirauth_disabled = get_options()->AuthoritativeDir; + int state_disabled = (get_or_state()->LastWritten == -1); + + if (consensus_disabled || config_disabled || dirauth_disabled || + state_disabled) { + log_info(LD_CIRC, + "CircuitBuildTime learning is disabled. " + "Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d", + consensus_disabled, config_disabled, dirauth_disabled, + state_disabled); + return 1; + } else { + return 0; + } + } +} + +static int32_t +circuit_build_times_max_timeouts(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtmaxtimeouts", + CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT); + return num; +} + +static int32_t +circuit_build_times_default_num_xm_modes(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtnummodes", + CBT_DEFAULT_NUM_XM_MODES); + return num; +} + +static int32_t +circuit_build_times_min_circs_to_observe(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtmincircs", + CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE); + return num; +} + +/** Return true iff <b>cbt</b> has recorded enough build times that we + * want to start acting on the timeout it implies. */ +int +circuit_build_times_enough_to_compute(circuit_build_times_t *cbt) +{ + return cbt->total_build_times >= circuit_build_times_min_circs_to_observe(); +} + +double +circuit_build_times_quantile_cutoff(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtquantile", + CBT_DEFAULT_QUANTILE_CUTOFF); + return num/100.0; +} + +static double +circuit_build_times_close_quantile(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtclosequantile", + CBT_DEFAULT_CLOSE_QUANTILE); + + return num/100.0; +} + +static int32_t +circuit_build_times_test_frequency(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbttestfreq", + CBT_DEFAULT_TEST_FREQUENCY); + return num; +} + +static int32_t +circuit_build_times_min_timeout(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtmintimeout", + CBT_DEFAULT_TIMEOUT_MIN_VALUE); + return num; +} + +int32_t +circuit_build_times_initial_timeout(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtinitialtimeout", + CBT_DEFAULT_TIMEOUT_INITIAL_VALUE); + return num; +} + +static int32_t +circuit_build_times_recent_circuit_count(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtrecentcount", + CBT_DEFAULT_RECENT_CIRCUITS); + return num; +} + +/** + * This function is called when we get a consensus update. + * + * It checks to see if we have changed any consensus parameters + * that require reallocation or discard of previous stats. + */ +void +circuit_build_times_new_consensus_params(circuit_build_times_t *cbt, + networkstatus_t *ns) +{ + int32_t num = networkstatus_get_param(ns, "cbtrecentcount", + CBT_DEFAULT_RECENT_CIRCUITS); + + if (num > 0 && num != cbt->liveness.num_recent_circs) { + int8_t *recent_circs; + log_notice(LD_CIRC, "Changing recent timeout size from %d to %d", + cbt->liveness.num_recent_circs, num); + + tor_assert(cbt->liveness.timeouts_after_firsthop); + + /* + * Technically this is a circular array that we are reallocating + * and memcopying. However, since it only consists of either 1s + * or 0s, and is only used in a statistical test to determine when + * we should discard our history after a sufficient number of 1's + * have been reached, it is fine if order is not preserved or + * elements are lost. + * + * cbtrecentcount should only be changing in cases of severe network + * distress anyway, so memory correctness here is paramount over + * doing acrobatics to preserve the array. + */ + recent_circs = tor_malloc_zero(sizeof(int8_t)*num); + memcpy(recent_circs, cbt->liveness.timeouts_after_firsthop, + sizeof(int8_t)*MIN(num, cbt->liveness.num_recent_circs)); + + // Adjust the index if it needs it. + if (num < cbt->liveness.num_recent_circs) { + cbt->liveness.after_firsthop_idx = MIN(num-1, + cbt->liveness.after_firsthop_idx); + } + + tor_free(cbt->liveness.timeouts_after_firsthop); + cbt->liveness.timeouts_after_firsthop = recent_circs; + cbt->liveness.num_recent_circs = num; + } +} + +/** Make a note that we're running unit tests (rather than running Tor + * itself), so we avoid clobbering our state file. */ +void +circuitbuild_running_unit_tests(void) +{ + unit_tests = 1; +} + +/** + * Return the initial default or configured timeout in milliseconds + */ +static double +circuit_build_times_get_initial_timeout(void) +{ + double timeout; + if (!unit_tests && get_options()->CircuitBuildTimeout) { + timeout = get_options()->CircuitBuildTimeout*1000; + if (timeout < circuit_build_times_min_timeout()) { + log_warn(LD_CIRC, "Config CircuitBuildTimeout too low. Setting to %ds", + circuit_build_times_min_timeout()/1000); + timeout = circuit_build_times_min_timeout(); + } + } else { + timeout = circuit_build_times_initial_timeout(); + } + return timeout; +} + +/** + * Reset the build time state. + * + * Leave estimated parameters, timeout and network liveness intact + * for future use. + */ +void +circuit_build_times_reset(circuit_build_times_t *cbt) +{ + memset(cbt->circuit_build_times, 0, sizeof(cbt->circuit_build_times)); + cbt->total_build_times = 0; + cbt->build_times_idx = 0; + cbt->have_computed_timeout = 0; +} + +/** + * Initialize the buildtimes structure for first use. + * + * Sets the initial timeout values based on either the config setting, + * the consensus param, or the default (CBT_DEFAULT_TIMEOUT_INITIAL_VALUE). + */ +void +circuit_build_times_init(circuit_build_times_t *cbt) +{ + memset(cbt, 0, sizeof(*cbt)); + cbt->liveness.num_recent_circs = circuit_build_times_recent_circuit_count(); + cbt->liveness.timeouts_after_firsthop = tor_malloc_zero(sizeof(int8_t)* + cbt->liveness.num_recent_circs); + cbt->close_ms = cbt->timeout_ms = circuit_build_times_get_initial_timeout(); + control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET); +} + +#if 0 +/** + * Rewind our build time history by n positions. + */ +static void +circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n) +{ + int i = 0; + + cbt->build_times_idx -= n; + cbt->build_times_idx %= CBT_NCIRCUITS_TO_OBSERVE; + + for (i = 0; i < n; i++) { + cbt->circuit_build_times[(i+cbt->build_times_idx) + %CBT_NCIRCUITS_TO_OBSERVE]=0; + } + + if (cbt->total_build_times > n) { + cbt->total_build_times -= n; + } else { + cbt->total_build_times = 0; + } + + log_info(LD_CIRC, + "Rewound history by %d places. Current index: %d. " + "Total: %d", n, cbt->build_times_idx, cbt->total_build_times); +} +#endif + +/** + * Add a new build time value <b>time</b> to the set of build times. Time + * units are milliseconds. + * + * circuit_build_times <b>cbt</a> is a circular array, so loop around when + * array is full. + */ +int +circuit_build_times_add_time(circuit_build_times_t *cbt, build_time_t time) +{ + if (time <= 0 || time > CBT_BUILD_TIME_MAX) { + log_warn(LD_BUG, "Circuit build time is too large (%u)." + "This is probably a bug.", time); + tor_fragile_assert(); + return -1; + } + + log_debug(LD_CIRC, "Adding circuit build time %u", time); + + cbt->circuit_build_times[cbt->build_times_idx] = time; + cbt->build_times_idx = (cbt->build_times_idx + 1) % CBT_NCIRCUITS_TO_OBSERVE; + if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE) + cbt->total_build_times++; + + if ((cbt->total_build_times % CBT_SAVE_STATE_EVERY) == 0) { + /* Save state every n circuit builds */ + if (!unit_tests && !get_options()->AvoidDiskWrites) + or_state_mark_dirty(get_or_state(), 0); + } + + return 0; +} + +/** + * Return maximum circuit build time + */ +static build_time_t +circuit_build_times_max(circuit_build_times_t *cbt) +{ + int i = 0; + build_time_t max_build_time = 0; + for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (cbt->circuit_build_times[i] > max_build_time + && cbt->circuit_build_times[i] != CBT_BUILD_ABANDONED) + max_build_time = cbt->circuit_build_times[i]; + } + return max_build_time; +} + +#if 0 +/** Return minimum circuit build time */ +build_time_t +circuit_build_times_min(circuit_build_times_t *cbt) +{ + int i = 0; + build_time_t min_build_time = CBT_BUILD_TIME_MAX; + for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (cbt->circuit_build_times[i] && /* 0 <-> uninitialized */ + cbt->circuit_build_times[i] < min_build_time) + min_build_time = cbt->circuit_build_times[i]; + } + if (min_build_time == CBT_BUILD_TIME_MAX) { + log_warn(LD_CIRC, "No build times less than CBT_BUILD_TIME_MAX!"); + } + return min_build_time; +} +#endif + +/** + * Calculate and return a histogram for the set of build times. + * + * Returns an allocated array of histrogram bins representing + * the frequency of index*CBT_BIN_WIDTH millisecond + * build times. Also outputs the number of bins in nbins. + * + * The return value must be freed by the caller. + */ +static uint32_t * +circuit_build_times_create_histogram(circuit_build_times_t *cbt, + build_time_t *nbins) +{ + uint32_t *histogram; + build_time_t max_build_time = circuit_build_times_max(cbt); + int i, c; + + *nbins = 1 + (max_build_time / CBT_BIN_WIDTH); + histogram = tor_malloc_zero(*nbins * sizeof(build_time_t)); + + // calculate histogram + for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (cbt->circuit_build_times[i] == 0 + || cbt->circuit_build_times[i] == CBT_BUILD_ABANDONED) + continue; /* 0 <-> uninitialized */ + + c = (cbt->circuit_build_times[i] / CBT_BIN_WIDTH); + histogram[c]++; + } + + return histogram; +} + +/** + * Return the Pareto start-of-curve parameter Xm. + * + * Because we are not a true Pareto curve, we compute this as the + * weighted average of the N=3 most frequent build time bins. + */ +static build_time_t +circuit_build_times_get_xm(circuit_build_times_t *cbt) +{ + build_time_t i, nbins; + build_time_t *nth_max_bin; + int32_t bin_counts=0; + build_time_t ret = 0; + uint32_t *histogram = circuit_build_times_create_histogram(cbt, &nbins); + int n=0; + int num_modes = circuit_build_times_default_num_xm_modes(); + + // Only use one mode if < 1000 buildtimes. Not enough data + // for multiple. + if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE) + num_modes = 1; + + nth_max_bin = (build_time_t*)tor_malloc_zero(num_modes*sizeof(build_time_t)); + + for (i = 0; i < nbins; i++) { + if (histogram[i] >= histogram[nth_max_bin[0]]) { + nth_max_bin[0] = i; + } + + for (n = 1; n < num_modes; n++) { + if (histogram[i] >= histogram[nth_max_bin[n]] && + (!histogram[nth_max_bin[n-1]] + || histogram[i] < histogram[nth_max_bin[n-1]])) { + nth_max_bin[n] = i; + } + } + } + + for (n = 0; n < num_modes; n++) { + bin_counts += histogram[nth_max_bin[n]]; + ret += CBT_BIN_TO_MS(nth_max_bin[n])*histogram[nth_max_bin[n]]; + log_info(LD_CIRC, "Xm mode #%d: %u %u", n, CBT_BIN_TO_MS(nth_max_bin[n]), + histogram[nth_max_bin[n]]); + } + + ret /= bin_counts; + tor_free(histogram); + tor_free(nth_max_bin); + + return ret; +} + +/** + * Output a histogram of current circuit build times to + * the or_state_t state structure. + */ +void +circuit_build_times_update_state(circuit_build_times_t *cbt, + or_state_t *state) +{ + uint32_t *histogram; + build_time_t i = 0; + build_time_t nbins = 0; + config_line_t **next, *line; + + histogram = circuit_build_times_create_histogram(cbt, &nbins); + // write to state + config_free_lines(state->BuildtimeHistogram); + next = &state->BuildtimeHistogram; + *next = NULL; + + state->TotalBuildTimes = cbt->total_build_times; + state->CircuitBuildAbandonedCount = 0; + + for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (cbt->circuit_build_times[i] == CBT_BUILD_ABANDONED) + state->CircuitBuildAbandonedCount++; + } + + for (i = 0; i < nbins; i++) { + // compress the histogram by skipping the blanks + if (histogram[i] == 0) continue; + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("CircuitBuildTimeBin"); + line->value = tor_malloc(25); + tor_snprintf(line->value, 25, "%d %d", + CBT_BIN_TO_MS(i), histogram[i]); + next = &(line->next); + } + + if (!unit_tests) { + if (!get_options()->AvoidDiskWrites) + or_state_mark_dirty(get_or_state(), 0); + } + + tor_free(histogram); +} + +/** + * Shuffle the build times array. + * + * Stolen from http://en.wikipedia.org/wiki/Fisher\u2013Yates_shuffle + */ +static void +circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, + build_time_t *raw_times, + int num_times) +{ + int n = num_times; + if (num_times > CBT_NCIRCUITS_TO_OBSERVE) { + log_notice(LD_CIRC, "Decreasing circuit_build_times size from %d to %d", + num_times, CBT_NCIRCUITS_TO_OBSERVE); + } + + /* This code can only be run on a compact array */ + while (n-- > 1) { + int k = crypto_rand_int(n + 1); /* 0 <= k <= n. */ + build_time_t tmp = raw_times[k]; + raw_times[k] = raw_times[n]; + raw_times[n] = tmp; + } + + /* Since the times are now shuffled, take a random CBT_NCIRCUITS_TO_OBSERVE + * subset (ie the first CBT_NCIRCUITS_TO_OBSERVE values) */ + for (n = 0; n < MIN(num_times, CBT_NCIRCUITS_TO_OBSERVE); n++) { + circuit_build_times_add_time(cbt, raw_times[n]); + } +} + +/** + * Filter old synthetic timeouts that were created before the + * new right-censored Pareto calculation was deployed. + * + * Once all clients before 0.2.1.13-alpha are gone, this code + * will be unused. + */ +static int +circuit_build_times_filter_timeouts(circuit_build_times_t *cbt) +{ + int num_filtered=0, i=0; + double timeout_rate = 0; + build_time_t max_timeout = 0; + + timeout_rate = circuit_build_times_timeout_rate(cbt); + max_timeout = (build_time_t)cbt->close_ms; + + for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (cbt->circuit_build_times[i] > max_timeout) { + build_time_t replaced = cbt->circuit_build_times[i]; + num_filtered++; + cbt->circuit_build_times[i] = CBT_BUILD_ABANDONED; + + log_debug(LD_CIRC, "Replaced timeout %d with %d", replaced, + cbt->circuit_build_times[i]); + } + } + + log_info(LD_CIRC, + "We had %d timeouts out of %d build times, " + "and filtered %d above the max of %u", + (int)(cbt->total_build_times*timeout_rate), + cbt->total_build_times, num_filtered, max_timeout); + + return num_filtered; +} + +/** + * Load histogram from <b>state</b>, shuffling the resulting array + * after we do so. Use this result to estimate parameters and + * calculate the timeout. + * + * Return -1 on error. + */ +int +circuit_build_times_parse_state(circuit_build_times_t *cbt, + or_state_t *state) +{ + int tot_values = 0; + uint32_t loaded_cnt = 0, N = 0; + config_line_t *line; + unsigned int i; + build_time_t *loaded_times; + int err = 0; + circuit_build_times_init(cbt); + + if (circuit_build_times_disabled()) { + return 0; + } + + /* build_time_t 0 means uninitialized */ + loaded_times = tor_malloc_zero(sizeof(build_time_t)*state->TotalBuildTimes); + + for (line = state->BuildtimeHistogram; line; line = line->next) { + smartlist_t *args = smartlist_create(); + smartlist_split_string(args, line->value, " ", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + if (smartlist_len(args) < 2) { + log_warn(LD_GENERAL, "Unable to parse circuit build times: " + "Too few arguments to CircuitBuildTime"); + err = 1; + SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); + smartlist_free(args); + break; + } else { + const char *ms_str = smartlist_get(args,0); + const char *count_str = smartlist_get(args,1); + uint32_t count, k; + build_time_t ms; + int ok; + ms = (build_time_t)tor_parse_ulong(ms_str, 0, 0, + CBT_BUILD_TIME_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_GENERAL, "Unable to parse circuit build times: " + "Unparsable bin number"); + err = 1; + SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); + smartlist_free(args); + break; + } + count = (uint32_t)tor_parse_ulong(count_str, 0, 0, + UINT32_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_GENERAL, "Unable to parse circuit build times: " + "Unparsable bin count"); + err = 1; + SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); + smartlist_free(args); + break; + } + + if (loaded_cnt+count+state->CircuitBuildAbandonedCount + > state->TotalBuildTimes) { + log_warn(LD_CIRC, + "Too many build times in state file. " + "Stopping short before %d", + loaded_cnt+count); + SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); + smartlist_free(args); + break; + } + + for (k = 0; k < count; k++) { + loaded_times[loaded_cnt++] = ms; + } + N++; + SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); + smartlist_free(args); + } + } + + log_info(LD_CIRC, + "Adding %d timeouts.", state->CircuitBuildAbandonedCount); + for (i=0; i < state->CircuitBuildAbandonedCount; i++) { + loaded_times[loaded_cnt++] = CBT_BUILD_ABANDONED; + } + + if (loaded_cnt != state->TotalBuildTimes) { + log_warn(LD_CIRC, + "Corrupt state file? Build times count mismatch. " + "Read %d times, but file says %d", loaded_cnt, + state->TotalBuildTimes); + err = 1; + circuit_build_times_reset(cbt); + goto done; + } + + circuit_build_times_shuffle_and_store_array(cbt, loaded_times, loaded_cnt); + + /* Verify that we didn't overwrite any indexes */ + for (i=0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (!cbt->circuit_build_times[i]) + break; + tot_values++; + } + log_info(LD_CIRC, + "Loaded %d/%d values from %d lines in circuit time histogram", + tot_values, cbt->total_build_times, N); + + if (cbt->total_build_times != tot_values + || cbt->total_build_times > CBT_NCIRCUITS_TO_OBSERVE) { + log_warn(LD_CIRC, + "Corrupt state file? Shuffled build times mismatch. " + "Read %d times, but file says %d", tot_values, + state->TotalBuildTimes); + err = 1; + circuit_build_times_reset(cbt); + goto done; + } + + circuit_build_times_set_timeout(cbt); + + if (!state->CircuitBuildAbandonedCount && cbt->total_build_times) { + circuit_build_times_filter_timeouts(cbt); + } + + done: + tor_free(loaded_times); + return err ? -1 : 0; +} + +/** + * Estimates the Xm and Alpha parameters using + * http://en.wikipedia.org/wiki/Pareto_distribution#Parameter_estimation + * + * The notable difference is that we use mode instead of min to estimate Xm. + * This is because our distribution is frechet-like. We claim this is + * an acceptable approximation because we are only concerned with the + * accuracy of the CDF of the tail. + */ +int +circuit_build_times_update_alpha(circuit_build_times_t *cbt) +{ + build_time_t *x=cbt->circuit_build_times; + double a = 0; + int n=0,i=0,abandoned_count=0; + build_time_t max_time=0; + + /* http://en.wikipedia.org/wiki/Pareto_distribution#Parameter_estimation */ + /* We sort of cheat here and make our samples slightly more pareto-like + * and less frechet-like. */ + cbt->Xm = circuit_build_times_get_xm(cbt); + + tor_assert(cbt->Xm > 0); + + for (i=0; i< CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (!x[i]) { + continue; + } + + if (x[i] < cbt->Xm) { + a += tor_mathlog(cbt->Xm); + } else if (x[i] == CBT_BUILD_ABANDONED) { + abandoned_count++; + } else { + a += tor_mathlog(x[i]); + if (x[i] > max_time) + max_time = x[i]; + } + n++; + } + + /* + * We are erring and asserting here because this can only happen + * in codepaths other than startup. The startup state parsing code + * performs this same check, and resets state if it hits it. If we + * hit it at runtime, something serious has gone wrong. + */ + if (n!=cbt->total_build_times) { + log_err(LD_CIRC, "Discrepancy in build times count: %d vs %d", n, + cbt->total_build_times); + } + tor_assert(n==cbt->total_build_times); + + if (max_time <= 0) { + /* This can happen if Xm is actually the *maximum* value in the set. + * It can also happen if we've abandoned every single circuit somehow. + * In either case, tell the caller not to compute a new build timeout. */ + log_warn(LD_BUG, + "Could not determine largest build time (%d). " + "Xm is %dms and we've abandoned %d out of %d circuits.", max_time, + cbt->Xm, abandoned_count, n); + return 0; + } + + a += abandoned_count*tor_mathlog(max_time); + + a -= n*tor_mathlog(cbt->Xm); + // Estimator comes from Eq #4 in: + // "Bayesian estimation based on trimmed samples from Pareto populations" + // by Arturo J. Fernández. We are right-censored only. + a = (n-abandoned_count)/a; + + cbt->alpha = a; + + return 1; +} + +/** + * This is the Pareto Quantile Function. It calculates the point x + * in the distribution such that F(x) = quantile (ie quantile*100% + * of the mass of the density function is below x on the curve). + * + * We use it to calculate the timeout and also to generate synthetic + * values of time for circuits that timeout before completion. + * + * See http://en.wikipedia.org/wiki/Quantile_function, + * http://en.wikipedia.org/wiki/Inverse_transform_sampling and + * http://en.wikipedia.org/wiki/Pareto_distribution#Generating_a_ + * random_sample_from_Pareto_distribution + * That's right. I'll cite wikipedia all day long. + * + * Return value is in milliseconds. + */ +double +circuit_build_times_calculate_timeout(circuit_build_times_t *cbt, + double quantile) +{ + double ret; + tor_assert(quantile >= 0); + tor_assert(1.0-quantile > 0); + tor_assert(cbt->Xm > 0); + + ret = cbt->Xm/pow(1.0-quantile,1.0/cbt->alpha); + if (ret > INT32_MAX) { + ret = INT32_MAX; + } + tor_assert(ret > 0); + return ret; +} + +/** Pareto CDF */ +double +circuit_build_times_cdf(circuit_build_times_t *cbt, double x) +{ + double ret; + tor_assert(cbt->Xm > 0); + ret = 1.0-pow(cbt->Xm/x,cbt->alpha); + tor_assert(0 <= ret && ret <= 1.0); + return ret; +} + +/** + * Generate a synthetic time using our distribution parameters. + * + * The return value will be within the [q_lo, q_hi) quantile points + * on the CDF. + */ +build_time_t +circuit_build_times_generate_sample(circuit_build_times_t *cbt, + double q_lo, double q_hi) +{ + double randval = crypto_rand_double(); + build_time_t ret; + double u; + + /* Generate between [q_lo, q_hi) */ + /*XXXX This is what nextafter is supposed to be for; we should use it on the + * platforms that support it. */ + q_hi -= 1.0/(INT32_MAX); + + tor_assert(q_lo >= 0); + tor_assert(q_hi < 1); + tor_assert(q_lo < q_hi); + + u = q_lo + (q_hi-q_lo)*randval; + + tor_assert(0 <= u && u < 1.0); + /* circuit_build_times_calculate_timeout returns <= INT32_MAX */ + ret = (build_time_t) + tor_lround(circuit_build_times_calculate_timeout(cbt, u)); + tor_assert(ret > 0); + return ret; +} + +/** + * Estimate an initial alpha parameter by solving the quantile + * function with a quantile point and a specific timeout value. + */ +void +circuit_build_times_initial_alpha(circuit_build_times_t *cbt, + double quantile, double timeout_ms) +{ + // Q(u) = Xm/((1-u)^(1/a)) + // Q(0.8) = Xm/((1-0.8))^(1/a)) = CircBuildTimeout + // CircBuildTimeout = Xm/((1-0.8))^(1/a)) + // CircBuildTimeout = Xm*((1-0.8))^(-1/a)) + // ln(CircBuildTimeout) = ln(Xm)+ln(((1-0.8)))*(-1/a) + // -ln(1-0.8)/(ln(CircBuildTimeout)-ln(Xm))=a + tor_assert(quantile >= 0); + tor_assert(cbt->Xm > 0); + cbt->alpha = tor_mathlog(1.0-quantile)/ + (tor_mathlog(cbt->Xm)-tor_mathlog(timeout_ms)); + tor_assert(cbt->alpha > 0); +} + +/** + * Returns true if we need circuits to be built + */ +int +circuit_build_times_needs_circuits(circuit_build_times_t *cbt) +{ + /* Return true if < MIN_CIRCUITS_TO_OBSERVE */ + return !circuit_build_times_enough_to_compute(cbt); +} + +/** + * Returns true if we should build a timeout test circuit + * right now. + */ +int +circuit_build_times_needs_circuits_now(circuit_build_times_t *cbt) +{ + return circuit_build_times_needs_circuits(cbt) && + approx_time()-cbt->last_circ_at > circuit_build_times_test_frequency(); +} + +/** + * Called to indicate that the network showed some signs of liveness, + * i.e. we received a cell. + * + * This is used by circuit_build_times_network_check_live() to decide + * if we should record the circuit build timeout or not. + * + * This function is called every time we receive a cell. Avoid + * syscalls, events, and other high-intensity work. + */ +void +circuit_build_times_network_is_live(circuit_build_times_t *cbt) +{ + time_t now = approx_time(); + if (cbt->liveness.nonlive_timeouts > 0) { + log_notice(LD_CIRC, + "Tor now sees network activity. Restoring circuit build " + "timeout recording. Network was down for %d seconds " + "during %d circuit attempts.", + (int)(now - cbt->liveness.network_last_live), + cbt->liveness.nonlive_timeouts); + } + cbt->liveness.network_last_live = now; + cbt->liveness.nonlive_timeouts = 0; +} + +/** + * Called to indicate that we completed a circuit. Because this circuit + * succeeded, it doesn't count as a timeout-after-the-first-hop. + * + * This is used by circuit_build_times_network_check_changed() to determine + * if we had too many recent timeouts and need to reset our learned timeout + * to something higher. + */ +void +circuit_build_times_network_circ_success(circuit_build_times_t *cbt) +{ + cbt->liveness.timeouts_after_firsthop[cbt->liveness.after_firsthop_idx] = 0; + cbt->liveness.after_firsthop_idx++; + cbt->liveness.after_firsthop_idx %= cbt->liveness.num_recent_circs; +} + +/** + * A circuit just timed out. If it failed after the first hop, record it + * in our history for later deciding if the network speed has changed. + * + * This is used by circuit_build_times_network_check_changed() to determine + * if we had too many recent timeouts and need to reset our learned timeout + * to something higher. + */ +static void +circuit_build_times_network_timeout(circuit_build_times_t *cbt, + int did_onehop) +{ + if (did_onehop) { + cbt->liveness.timeouts_after_firsthop[cbt->liveness.after_firsthop_idx]=1; + cbt->liveness.after_firsthop_idx++; + cbt->liveness.after_firsthop_idx %= cbt->liveness.num_recent_circs; + } +} + +/** + * A circuit was just forcibly closed. If there has been no recent network + * activity at all, but this circuit was launched back when we thought the + * network was live, increment the number of "nonlive" circuit timeouts. + * + * This is used by circuit_build_times_network_check_live() to decide + * if we should record the circuit build timeout or not. + */ +static void +circuit_build_times_network_close(circuit_build_times_t *cbt, + int did_onehop, time_t start_time) +{ + time_t now = time(NULL); + /* + * Check if this is a timeout that was for a circuit that spent its + * entire existence during a time where we have had no network activity. + */ + if (cbt->liveness.network_last_live < start_time) { + if (did_onehop) { + char last_live_buf[ISO_TIME_LEN+1]; + char start_time_buf[ISO_TIME_LEN+1]; + char now_buf[ISO_TIME_LEN+1]; + format_local_iso_time(last_live_buf, cbt->liveness.network_last_live); + format_local_iso_time(start_time_buf, start_time); + format_local_iso_time(now_buf, now); + log_warn(LD_BUG, + "Circuit somehow completed a hop while the network was " + "not live. Network was last live at %s, but circuit launched " + "at %s. It's now %s.", last_live_buf, start_time_buf, + now_buf); + } + cbt->liveness.nonlive_timeouts++; + if (cbt->liveness.nonlive_timeouts == 1) { + log_notice(LD_CIRC, + "Tor has not observed any network activity for the past %d " + "seconds. Disabling circuit build timeout code.", + (int)(now - cbt->liveness.network_last_live)); + } else { + log_info(LD_CIRC, + "Got non-live timeout. Current count is: %d", + cbt->liveness.nonlive_timeouts); + } + } +} + +/** + * When the network is not live, we do not record circuit build times. + * + * The network is considered not live if there has been at least one + * circuit build that began and ended (had its close_ms measurement + * period expire) since we last received a cell. + * + * Also has the side effect of rewinding the circuit time history + * in the case of recent liveness changes. + */ +int +circuit_build_times_network_check_live(circuit_build_times_t *cbt) +{ + if (cbt->liveness.nonlive_timeouts > 0) { + return 0; + } + + return 1; +} + +/** + * Returns true if we have seen more than MAX_RECENT_TIMEOUT_COUNT of + * the past RECENT_CIRCUITS time out after the first hop. Used to detect + * if the network connection has changed significantly, and if so, + * resets our circuit build timeout to the default. + * + * Also resets the entire timeout history in this case and causes us + * to restart the process of building test circuits and estimating a + * new timeout. + */ +int +circuit_build_times_network_check_changed(circuit_build_times_t *cbt) +{ + int total_build_times = cbt->total_build_times; + int timeout_count=0; + int i; + + /* how many of our recent circuits made it to the first hop but then + * timed out? */ + for (i = 0; i < cbt->liveness.num_recent_circs; i++) { + timeout_count += cbt->liveness.timeouts_after_firsthop[i]; + } + + /* If 80% of our recent circuits are timing out after the first hop, + * we need to re-estimate a new initial alpha and timeout. */ + if (timeout_count < circuit_build_times_max_timeouts()) { + return 0; + } + + circuit_build_times_reset(cbt); + memset(cbt->liveness.timeouts_after_firsthop, 0, + sizeof(*cbt->liveness.timeouts_after_firsthop)* + cbt->liveness.num_recent_circs); + cbt->liveness.after_firsthop_idx = 0; + + /* Check to see if this has happened before. If so, double the timeout + * to give people on abysmally bad network connections a shot at access */ + if (cbt->timeout_ms >= circuit_build_times_get_initial_timeout()) { + if (cbt->timeout_ms > INT32_MAX/2 || cbt->close_ms > INT32_MAX/2) { + log_warn(LD_CIRC, "Insanely large circuit build timeout value. " + "(timeout = %lfmsec, close = %lfmsec)", + cbt->timeout_ms, cbt->close_ms); + } else { + cbt->timeout_ms *= 2; + cbt->close_ms *= 2; + } + } else { + cbt->close_ms = cbt->timeout_ms + = circuit_build_times_get_initial_timeout(); + } + + control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET); + + log_notice(LD_CIRC, + "Network connection speed appears to have changed. Resetting " + "timeout to %lds after %d timeouts and %d buildtimes.", + tor_lround(cbt->timeout_ms/1000), timeout_count, + total_build_times); + + return 1; +} + +/** + * Count the number of timeouts in a set of cbt data. + */ +double +circuit_build_times_timeout_rate(const circuit_build_times_t *cbt) +{ + int i=0,timeouts=0; + for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (cbt->circuit_build_times[i] >= cbt->timeout_ms) { + timeouts++; + } + } + + if (!cbt->total_build_times) + return 0; + + return ((double)timeouts)/cbt->total_build_times; +} + +/** + * Count the number of closed circuits in a set of cbt data. + */ +double +circuit_build_times_close_rate(const circuit_build_times_t *cbt) +{ + int i=0,closed=0; + for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { + if (cbt->circuit_build_times[i] == CBT_BUILD_ABANDONED) { + closed++; + } + } + + if (!cbt->total_build_times) + return 0; + + return ((double)closed)/cbt->total_build_times; +} + +/** + * Store a timeout as a synthetic value. + * + * Returns true if the store was successful and we should possibly + * update our timeout estimate. + */ +int +circuit_build_times_count_close(circuit_build_times_t *cbt, + int did_onehop, + time_t start_time) +{ + if (circuit_build_times_disabled()) { + cbt->close_ms = cbt->timeout_ms + = circuit_build_times_get_initial_timeout(); + return 0; + } + + /* Record this force-close to help determine if the network is dead */ + circuit_build_times_network_close(cbt, did_onehop, start_time); + + /* Only count timeouts if network is live.. */ + if (!circuit_build_times_network_check_live(cbt)) { + return 0; + } + + circuit_build_times_add_time(cbt, CBT_BUILD_ABANDONED); + return 1; +} + +/** + * Update timeout counts to determine if we need to expire + * our build time history due to excessive timeouts. + * + * We do not record any actual time values at this stage; + * we are only interested in recording the fact that a timeout + * happened. We record the time values via + * circuit_build_times_count_close() and circuit_build_times_add_time(). + */ +void +circuit_build_times_count_timeout(circuit_build_times_t *cbt, + int did_onehop) +{ + if (circuit_build_times_disabled()) { + cbt->close_ms = cbt->timeout_ms + = circuit_build_times_get_initial_timeout(); + return; + } + + /* Register the fact that a timeout just occurred. */ + circuit_build_times_network_timeout(cbt, did_onehop); + + /* If there are a ton of timeouts, we should reset + * the circuit build timeout. */ + circuit_build_times_network_check_changed(cbt); +} + +/** + * Estimate a new timeout based on history and set our timeout + * variable accordingly. + */ +static int +circuit_build_times_set_timeout_worker(circuit_build_times_t *cbt) +{ + build_time_t max_time; + if (!circuit_build_times_enough_to_compute(cbt)) + return 0; + + if (!circuit_build_times_update_alpha(cbt)) + return 0; + + cbt->timeout_ms = circuit_build_times_calculate_timeout(cbt, + circuit_build_times_quantile_cutoff()); + + cbt->close_ms = circuit_build_times_calculate_timeout(cbt, + circuit_build_times_close_quantile()); + + max_time = circuit_build_times_max(cbt); + + /* Sometimes really fast guard nodes give us such a steep curve + * that this ends up being not that much greater than timeout_ms. + * Make it be at least 1 min to handle this case. */ + cbt->close_ms = MAX(cbt->close_ms, circuit_build_times_initial_timeout()); + + if (cbt->timeout_ms > max_time) { + log_notice(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); + cbt->timeout_ms = max_time; + } + + if (max_time < INT32_MAX/2 && cbt->close_ms > 2*max_time) { + log_notice(LD_CIRC, + "Circuit build measurement period of %dms is more than twice " + "the maximum build time we have ever observed. Capping it to " + "%dms.", (int)cbt->close_ms, 2*max_time); + cbt->close_ms = 2*max_time; + } + + cbt->have_computed_timeout = 1; + return 1; +} + +/** + * Exposed function to compute a new timeout. Dispatches events and + * also filters out extremely high timeout values. + */ +void +circuit_build_times_set_timeout(circuit_build_times_t *cbt) +{ + long prev_timeout = tor_lround(cbt->timeout_ms/1000); + double timeout_rate; + + if (!circuit_build_times_set_timeout_worker(cbt)) + return; + + if (cbt->timeout_ms < circuit_build_times_min_timeout()) { + log_warn(LD_CIRC, "Set buildtimeout to low value %lfms. Setting to %dms", + cbt->timeout_ms, circuit_build_times_min_timeout()); + cbt->timeout_ms = circuit_build_times_min_timeout(); + if (cbt->close_ms < cbt->timeout_ms) { + /* This shouldn't happen because of MAX() in timeout_worker above, + * but doing it just in case */ + cbt->close_ms = circuit_build_times_initial_timeout(); + } + } + + control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_COMPUTED); + + timeout_rate = circuit_build_times_timeout_rate(cbt); + + if (prev_timeout > tor_lround(cbt->timeout_ms/1000)) { + log_notice(LD_CIRC, + "Based on %d circuit times, it looks like we don't need to " + "wait so long for circuits to finish. We will now assume a " + "circuit is too slow to use after waiting %ld seconds.", + cbt->total_build_times, + tor_lround(cbt->timeout_ms/1000)); + log_info(LD_CIRC, + "Circuit timeout data: %lfms, %lfms, Xm: %d, a: %lf, r: %lf", + 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, + "Based on %d circuit times, it looks like we need to wait " + "longer for circuits to finish. We will now assume a " + "circuit is too slow to use after waiting %ld seconds.", + cbt->total_build_times, + tor_lround(cbt->timeout_ms/1000)); + log_info(LD_CIRC, + "Circuit timeout data: %lfms, %lfms, Xm: %d, a: %lf, r: %lf", + cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, + timeout_rate); + } else { + log_info(LD_CIRC, + "Set circuit build timeout to %lds (%lfms, %lfms, Xm: %d, a: %lf," + " r: %lf) based on %d circuit times", + tor_lround(cbt->timeout_ms/1000), + cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, timeout_rate, + cbt->total_build_times); + } +} + /** Iterate over values of circ_id, starting from conn-\>next_circ_id, * and with the high bit specified by conn-\>circ_id_type, until we get * a circ_id that is not in use by any other circuit on that conn. @@ -112,21 +1382,21 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) crypt_path_t *hop; smartlist_t *elements; const char *states[] = {"closed", "waiting for keys", "open"}; - char buf[128]; char *s; elements = smartlist_create(); if (verbose) { const char *nickname = build_state_get_exit_nickname(circ->build_state); - tor_snprintf(buf, sizeof(buf), "%s%s circ (length %d%s%s):", + char *cp; + tor_asprintf(&cp, "%s%s circ (length %d%s%s):", circ->build_state->is_internal ? "internal" : "exit", circ->build_state->need_uptime ? " (high-uptime)" : "", circ->build_state->desired_path_len, circ->_base.state == CIRCUIT_STATE_OPEN ? "" : ", exit ", circ->_base.state == CIRCUIT_STATE_OPEN ? "" : (nickname?nickname:"*unnamed*")); - smartlist_add(elements, tor_strdup(buf)); + smartlist_add(elements, cp); } hop = circ->cpath; @@ -148,8 +1418,7 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) router_get_verbose_nickname(elt, ri); } else if ((rs = router_get_consensus_status_by_id(id))) { routerstatus_get_verbose_nickname(elt, rs); - } else if (hop->extend_info->nickname && - is_legal_nickname(hop->extend_info->nickname)) { + } else if (is_legal_nickname(hop->extend_info->nickname)) { elt[0] = '$'; base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN); elt[HEX_DIGEST_LEN+1]= '~'; @@ -217,7 +1486,7 @@ void circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ) { char *s = circuit_list_path(circ,1); - log(severity,domain,"%s",s); + tor_log(severity,domain,"%s",s); tor_free(s); } @@ -269,7 +1538,7 @@ static int onion_populate_cpath(origin_circuit_t *circ) { int r; -again: + again: r = onion_extend_cpath(circ); if (r < 0) { log_info(LD_CIRC,"Generating cpath hop failed."); @@ -361,9 +1630,10 @@ circuit_handle_first_hop(origin_circuit_t *circ) if (!n_conn) { /* not currently connected in a useful way. */ - const char *name = firsthop->extend_info->nickname ? + const char *name = strlen(firsthop->extend_info->nickname) ? firsthop->extend_info->nickname : fmt_addr(&firsthop->extend_info->addr); - log_info(LD_CIRC, "Next router is %s: %s ", safe_str(name), msg?msg:"???"); + log_info(LD_CIRC, "Next router is %s: %s ", + safe_str_client(name), msg?msg:"???"); circ->_base.n_hop = extend_info_dup(firsthop->extend_info); if (should_launch) { @@ -506,7 +1776,8 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, cell.circ_id = circ->n_circ_id; memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN); - append_cell_to_circuit_queue(circ, circ->n_conn, &cell, CELL_DIRECTION_OUT); + append_cell_to_circuit_queue(circ, circ->n_conn, &cell, + CELL_DIRECTION_OUT, 0); if (CIRCUIT_IS_ORIGIN(circ)) { /* mark it so it gets better rate limiting treatment. */ @@ -536,7 +1807,7 @@ inform_testing_reachability(void) "CHECKING_REACHABILITY DIRADDRESS=%s:%d", me->address, me->dir_port); } - log(LOG_NOTICE, LD_OR, "Now checking whether ORPort %s:%d%s %s reachable... " + log_notice(LD_OR, "Now checking whether ORPort %s:%d%s %s reachable... " "(this may take up to %d minutes -- look for log " "messages indicating success)", me->address, me->or_port, @@ -569,6 +1840,18 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ) return 1; } +/** Return true if <b>circ</b> is the type of circuit we want to count + * timeouts from. In particular, we want it to have not completed yet + * (already completing indicates we cannibalized it), and we want it to + * have exactly three hops. + */ +int +circuit_timeout_want_to_count_circ(origin_circuit_t *circ) +{ + return !circ->has_opened + && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN; +} + /** This is the backbone function for building circuits. * * If circ's first hop is closed, then we need to build a create @@ -642,15 +1925,42 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) if (!hop) { /* done building the circuit. whew. */ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); + if (circuit_timeout_want_to_count_circ(circ)) { + struct timeval end; + long timediff; + tor_gettimeofday(&end); + timediff = tv_mdiff(&circ->_base.highres_created, &end); + + /* + * If the circuit build time is much greater than we would have cut + * it off at, we probably had a suspend event along this codepath, + * and we should discard the value. + */ + if (timediff < 0 || timediff > 2*circ_times.close_ms+1000) { + log_notice(LD_CIRC, "Strange value for circuit build time: %ldmsec. " + "Assuming clock jump. Purpose %d", timediff, + circ->_base.purpose); + } else if (!circuit_build_times_disabled()) { + /* Only count circuit times if the network is live */ + if (circuit_build_times_network_check_live(&circ_times)) { + circuit_build_times_add_time(&circ_times, (build_time_t)timediff); + circuit_build_times_set_timeout(&circ_times); + } + + if (circ->_base.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + circuit_build_times_network_circ_success(&circ_times); + } + } + } log_info(LD_CIRC,"circuit built!"); circuit_reset_failure_count(0); if (circ->build_state->onehop_tunnel) control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0); - if (!has_completed_circuit && !circ->build_state->onehop_tunnel) { + if (!can_complete_circuit && !circ->build_state->onehop_tunnel) { or_options_t *options = get_options(); - has_completed_circuit=1; + can_complete_circuit=1; /* FFFF Log a count of known routers here */ - log(LOG_NOTICE, LD_GENERAL, + log_notice(LD_GENERAL, "Tor has successfully opened a circuit. " "Looks like client functionality is working."); control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0); @@ -662,6 +1972,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) } circuit_rep_hist_note_result(circ); circuit_has_opened(circ); /* do other actions as necessary */ + + /* We're done with measurement circuits here. Just close them */ + if (circ->_base.purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); return 0; } @@ -705,13 +2019,13 @@ void circuit_note_clock_jumped(int seconds_elapsed) { int severity = server_mode(get_options()) ? LOG_WARN : LOG_NOTICE; - log(severity, LD_GENERAL, "Your system clock just jumped %d seconds %s; " + tor_log(severity, LD_GENERAL, "Your system clock just jumped %d seconds %s; " "assuming established circuits no longer work.", seconds_elapsed >=0 ? seconds_elapsed : -seconds_elapsed, seconds_elapsed >=0 ? "forward" : "backward"); control_event_general_status(LOG_WARN, "CLOCK_JUMPED TIME=%d", seconds_elapsed); - has_completed_circuit=0; /* so it'll log when it works again */ + can_complete_circuit=0; /* so it'll log when it works again */ control_event_client_status(severity, "CIRCUIT_NOT_ESTABLISHED REASON=%s", "CLOCK_JUMPED"); circuit_mark_all_unused_circs(); @@ -943,10 +2257,9 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, return -END_CIRC_REASON_TORPROTOCOL; } - if (hop->dh_handshake_state) { - crypto_dh_free(hop->dh_handshake_state); /* don't need it anymore */ - hop->dh_handshake_state = NULL; - } + crypto_dh_free(hop->dh_handshake_state); /* don't need it anymore */ + hop->dh_handshake_state = NULL; + memset(hop->fast_handshake_state, 0, sizeof(hop->fast_handshake_state)); if (circuit_init_cpath_crypto(hop, keys, 0)<0) { @@ -1034,8 +2347,8 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2); log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.", - (unsigned int)*(uint32_t*)(keys), - (unsigned int)*(uint32_t*)(keys+20)); + (unsigned int)get_uint32(keys), + (unsigned int)get_uint32(keys+20)); if (circuit_init_cpath_crypto(tmp_cpath, keys, 0)<0) { log_warn(LD_BUG,"Circuit initialization failed"); tor_free(tmp_cpath); @@ -1056,7 +2369,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, circ->is_first_hop = (cell_type == CELL_CREATED_FAST); append_cell_to_circuit_queue(TO_CIRCUIT(circ), - circ->p_conn, &cell, CELL_DIRECTION_IN); + circ->p_conn, &cell, CELL_DIRECTION_IN, 0); log_debug(LD_CIRC,"Finished sending 'created' cell."); if (!is_local_addr(&circ->p_conn->_base.addr) && @@ -1085,7 +2398,7 @@ new_route_len(uint8_t purpose, extend_info_t *exit, tor_assert(routers); - routelen = 3; + routelen = DEFAULT_ROUTE_LEN; if (exit && purpose != CIRCUIT_PURPOSE_TESTING && purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) @@ -1150,6 +2463,8 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime, smartlist_t *LongLivedServices = get_options()->LongLivedPorts; tor_assert(need_uptime); tor_assert(need_capacity); + // Always predict need_capacity + *need_capacity = 1; enough = (smartlist_len(sl) == 0); for (i = 0; i < smartlist_len(sl); ++i) { port = smartlist_get(sl, i); @@ -1172,6 +2487,8 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports) for (i = 0; i < smartlist_len(needed_ports); ++i) { addr_policy_result_t r; + /* alignment issues aren't a worry for this dereference, since + 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); @@ -1254,9 +2571,16 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, n_supported[i] = -1; continue; /* skip routers that are known to be down or bad exits */ } - if (router_is_unreliable(router, need_uptime, need_capacity, 0)) { + if (router_is_unreliable(router, need_uptime, need_capacity, 0) && + (!options->ExitNodes || + !routerset_contains_router(options->ExitNodes, router))) { + /* FFFF Someday, differentiate between a routerset that names + * routers, and a routerset that names countries, and only do this + * check if they've asked for specific exit relays. Or if the country + * they ask for is rare. Or something. */ n_supported[i] = -1; - continue; /* skip routers that are not suitable */ + continue; /* skip routers that are not suitable, unless we have + * ExitNodes set, in which case we asked for it */ } if (!(router->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) { /* if it's invalid and we don't want it */ @@ -1281,7 +2605,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, { if (!ap_stream_wants_exit_attention(conn)) continue; /* Skip everything but APs in CIRCUIT_WAIT */ - if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router)) { + if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router, 1)) { ++n_supported[i]; // log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.", // router->nickname, i, n_supported[i]); @@ -1323,7 +2647,8 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, routersets_get_disjunction(use, supporting, options->ExitNodes, options->_ExcludeExitNodesUnion, 1); - if (smartlist_len(use) == 0 && !options->StrictExitNodes) { + if (smartlist_len(use) == 0 && options->ExitNodes && + !options->StrictNodes) { /* give up on exitnodes and try again */ routersets_get_disjunction(use, supporting, NULL, options->_ExcludeExitNodesUnion, 1); } @@ -1335,7 +2660,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, * possibly support any of them. Choose a router at random that satisfies * at least one predicted exit port. */ - int try; + int attempt; smartlist_t *needed_ports, *supporting, *use; if (best_support == -1) { @@ -1348,19 +2673,20 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, tor_free(n_supported); return choose_good_exit_server_general(dir, 0, 0); } - log_notice(LD_CIRC, "All routers are down or won't exit -- choosing a " - "doomed exit at random."); + log_notice(LD_CIRC, "All routers are down or won't exit%s -- " + "choosing a doomed exit at random.", + options->_ExcludeExitNodesUnion ? " or are Excluded" : ""); } supporting = smartlist_create(); use = smartlist_create(); needed_ports = circuit_get_unhandled_ports(time(NULL)); - for (try = 0; try < 2; try++) { + 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 && - (try || router_handles_some_port(router, needed_ports))) { + (attempt || router_handles_some_port(router, needed_ports))) { // log_fn(LOG_DEBUG,"Try %d: '%s' is a possibility.", // try, router->nickname); smartlist_add(supporting, router); @@ -1369,12 +2695,14 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, routersets_get_disjunction(use, supporting, options->ExitNodes, options->_ExcludeExitNodesUnion, 1); - if (smartlist_len(use) == 0 && !options->StrictExitNodes) { + if (smartlist_len(use) == 0 && options->ExitNodes && + !options->StrictNodes) { /* give up on exitnodes and try again */ routersets_get_disjunction(use, supporting, NULL, options->_ExcludeExitNodesUnion, 1); } - /* XXX sometimes the above results in null, when the requested - * exit node is down. we should pick it anyway. */ + /* FFF sometimes the above results in null, when the requested + * exit node is considered down by the consensus. we should pick + * it anyway, since the user asked for it. */ router = routerlist_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT); if (router) break; @@ -1392,10 +2720,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, log_info(LD_CIRC, "Chose exit server '%s'", router->nickname); return router; } - if (options->StrictExitNodes) { + if (options->ExitNodes && options->StrictNodes) { log_warn(LD_CIRC, "No specified exit routers seem to be running, and " - "StrictExitNodes is set: can't choose an exit."); + "StrictNodes is set: can't choose an exit."); } return NULL; } @@ -1426,15 +2754,13 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir, if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE) flags |= CRN_ALLOW_INVALID; if (is_internal) /* pick it like a middle hop */ - return router_choose_random_node(NULL, NULL, - options->ExcludeNodes, flags); + return router_choose_random_node(NULL, options->ExcludeNodes, flags); else return choose_good_exit_server_general(dir,need_uptime,need_capacity); case CIRCUIT_PURPOSE_C_ESTABLISH_REND: if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS) flags |= CRN_ALLOW_INVALID; - return router_choose_random_node(NULL, NULL, - options->ExcludeNodes, flags); + return router_choose_random_node(NULL, options->ExcludeNodes, flags); } log_warn(LD_BUG,"Unhandled purpose %d", purpose); tor_fragile_assert(); @@ -1554,8 +2880,7 @@ circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *exit) state = circ->build_state; tor_assert(state); - if (state->chosen_exit) - extend_info_free(state->chosen_exit); + extend_info_free(state->chosen_exit); state->chosen_exit = extend_info_dup(exit); ++circ->build_state->desired_path_len; @@ -1677,8 +3002,7 @@ choose_good_middle_server(uint8_t purpose, flags |= CRN_NEED_CAPACITY; if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE) flags |= CRN_ALLOW_INVALID; - choice = router_choose_random_node(NULL, - excluded, options->ExcludeNodes, flags); + choice = router_choose_random_node(excluded, options->ExcludeNodes, flags); smartlist_free(excluded); return choice; } @@ -1742,11 +3066,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) if (options->_AllowInvalid & ALLOW_INVALID_ENTRY) flags |= CRN_ALLOW_INVALID; - choice = router_choose_random_node( - NULL, - excluded, - options->ExcludeNodes, - flags); + choice = router_choose_random_node(excluded, options->ExcludeNodes, flags); smartlist_free(excluded); return choice; } @@ -1867,9 +3187,9 @@ extend_info_from_router(routerinfo_t *r) void extend_info_free(extend_info_t *info) { - tor_assert(info); - if (info->onion_key) - crypto_free_pk_env(info->onion_key); + if (!info) + return; + crypto_free_pk_env(info->onion_key); tor_free(info); } @@ -1928,8 +3248,6 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri, char buf[HEX_DIGEST_LEN+1]; int changed = 0; - tor_assert(options); - *reason = NULL; /* Do we want to mark this guard as bad? */ @@ -1992,35 +3310,58 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now) * - Listed as either up or never yet contacted; * - Present in the routerlist; * - Listed as 'stable' or 'fast' by the current dirserver consensus, - * if demanded by <b>need_uptime</b> or <b>need_capacity</b>; - * (This check is currently redundant with the Guard flag, but in - * the future that might change. Best to leave it in for now.) + * if demanded by <b>need_uptime</b> or <b>need_capacity</b> + * (unless it's a configured EntryNode); * - Allowed by our current ReachableORAddresses config option; and - * - Currently thought to be reachable by us (unless assume_reachable + * - Currently thought to be reachable by us (unless <b>assume_reachable</b> * is true). + * + * If the answer is no, set *<b>msg</b> to an explanation of why. */ static INLINE routerinfo_t * entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, - int assume_reachable) + int assume_reachable, const char **msg) { routerinfo_t *r; - if (e->bad_since) + or_options_t *options = get_options(); + tor_assert(msg); + + if (e->bad_since) { + *msg = "bad"; return NULL; + } /* no good if it's unreachable, unless assume_unreachable or can_retry. */ if (!assume_reachable && !e->can_retry && - e->unreachable_since && !entry_is_time_to_retry(e, time(NULL))) + e->unreachable_since && !entry_is_time_to_retry(e, time(NULL))) { + *msg = "unreachable"; return NULL; + } r = router_get_by_digest(e->identity); - if (!r) + if (!r) { + *msg = "no descriptor"; return NULL; - if (get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_BRIDGE) + } + if (get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_BRIDGE) { + *msg = "not a bridge"; return NULL; - if (!get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_GENERAL) + } + if (!get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_GENERAL) { + *msg = "not general-purpose"; return NULL; - if (router_is_unreliable(r, need_uptime, need_capacity, 0)) + } + if (options->EntryNodes && + routerset_contains_router(options->EntryNodes, r)) { + /* they asked for it, they get it */ + need_uptime = need_capacity = 0; + } + if (router_is_unreliable(r, need_uptime, need_capacity, 0)) { + *msg = "not fast/stable"; return NULL; - if (!fascist_firewall_allows_or(r)) + } + if (!fascist_firewall_allows_or(r)) { + *msg = "unreachable by config"; return NULL; + } return r; } @@ -2029,11 +3370,12 @@ static int num_live_entry_guards(void) { int n = 0; + const char *msg; if (! entry_guards) return 0; SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, { - if (entry_is_live(entry, 0, 1, 0)) + if (entry_is_live(entry, 0, 1, 0, &msg)) ++n; }); return n; @@ -2057,16 +3399,21 @@ static void log_entry_guards(int severity) { smartlist_t *elements = smartlist_create(); - char buf[1024]; char *s; SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, { - tor_snprintf(buf, sizeof(buf), "%s (%s%s)", - e->nickname, - entry_is_live(e, 0, 1, 0) ? "up " : "down ", - e->made_contact ? "made-contact" : "never-contacted"); - smartlist_add(elements, tor_strdup(buf)); + const char *msg = NULL; + char *cp; + if (entry_is_live(e, 0, 1, 0, &msg)) + tor_asprintf(&cp, "%s (up %s)", + e->nickname, + e->made_contact ? "made-contact" : "never-contacted"); + else + tor_asprintf(&cp, "%s (%s, %s)", + e->nickname, msg, + e->made_contact ? "made-contact" : "never-contacted"); + smartlist_add(elements, cp); }); s = smartlist_join_strings(elements, ",", 0, NULL); @@ -2090,12 +3437,13 @@ control_event_guard_deferred(void) **/ #if 0 int n = 0; + const char *msg; or_options_t *options = get_options(); if (!entry_guards) return; SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, { - if (entry_is_live(entry, 0, 1, 0)) { + if (entry_is_live(entry, 0, 1, 0, &msg)) { if (n++ == options->NumEntryGuards) { control_event_guard(entry->nickname, entry->identity, "DEFERRED"); return; @@ -2157,9 +3505,8 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status) /** If the use of entry guards is configured, choose more entry guards * until we have enough in the list. */ static void -pick_entry_guards(void) +pick_entry_guards(or_options_t *options) { - or_options_t *options = get_options(); int changed = 0; tor_assert(entry_guards); @@ -2181,7 +3528,8 @@ pick_entry_guards(void) static void entry_guard_free(entry_guard_t *e) { - tor_assert(e); + if (!e) + return; tor_free(e->chosen_by_version); tor_free(e); } @@ -2190,10 +3538,9 @@ entry_guard_free(entry_guard_t *e) * or which was selected by a version of Tor that's known to select * entry guards badly. */ static int -remove_obsolete_entry_guards(void) +remove_obsolete_entry_guards(time_t now) { int changed = 0, i; - time_t now = time(NULL); for (i = 0; i < smartlist_len(entry_guards); ++i) { entry_guard_t *entry = smartlist_get(entry_guards, i); @@ -2253,11 +3600,10 @@ remove_obsolete_entry_guards(void) * long that we don't think they'll come up again. Return 1 if we * removed any, or 0 if we did nothing. */ static int -remove_dead_entry_guards(void) +remove_dead_entry_guards(time_t now) { char dbuf[HEX_DIGEST_LEN+1]; char tbuf[ISO_TIME_LEN+1]; - time_t now = time(NULL); int i; int changed = 0; @@ -2292,19 +3638,17 @@ remove_dead_entry_guards(void) * think that things are unlisted. */ void -entry_guards_compute_status(void) +entry_guards_compute_status(or_options_t *options, time_t now) { - time_t now; int changed = 0; int severity = LOG_DEBUG; - or_options_t *options; digestmap_t *reasons; + if (! entry_guards) return; - options = get_options(); - - now = time(NULL); + if (options->EntryNodes) /* reshuffle the entry guard list if needed */ + entry_nodes_should_be_added(); reasons = digestmap_new(); SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) @@ -2321,7 +3665,7 @@ entry_guards_compute_status(void) } SMARTLIST_FOREACH_END(entry); - if (remove_dead_entry_guards()) + if (remove_dead_entry_guards(now)) changed = 1; severity = changed ? LOG_DEBUG : LOG_INFO; @@ -2329,13 +3673,16 @@ entry_guards_compute_status(void) if (changed) { SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { const char *reason = digestmap_get(reasons, entry->identity); - log_info(LD_CIRC, "Summary: Entry '%s' is %s, %s%s%s, and %s.", + const char *live_msg = ""; + routerinfo_t *r = entry_is_live(entry, 0, 1, 0, &live_msg); + log_info(LD_CIRC, "Summary: Entry '%s' is %s, %s%s%s, and %s%s.", entry->nickname, entry->unreachable_since ? "unreachable" : "reachable", entry->bad_since ? "unusable" : "usable", reason ? ", ": "", reason ? reason : "", - entry_is_live(entry, 0, 1, 0) ? "live" : "not live"); + r ? "live" : "not live / ", + r ? "" : live_msg); } SMARTLIST_FOREACH_END(entry); log_info(LD_CIRC, " (%d/%d entry guards are usable/new)", num_live_entry_guards(), smartlist_len(entry_guards)); @@ -2406,6 +3753,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded, "Removing from the list. %d/%d entry guards usable/new.", entry->nickname, buf, num_live_entry_guards()-1, smartlist_len(entry_guards)-1); + control_event_guard(entry->nickname, entry->identity, "DROPPED"); entry_guard_free(entry); smartlist_del_keeporder(entry_guards, idx); log_entry_guards(LOG_INFO); @@ -2442,7 +3790,8 @@ entry_guard_register_connect_status(const char *digest, int succeeded, if (e == entry) break; if (e->made_contact) { - routerinfo_t *r = entry_is_live(e, 0, 1, 1); + const char *msg; + routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg); if (r && e->unreachable_since) { refuse_conn = 1; e->can_retry = 1; @@ -2473,16 +3822,16 @@ static int should_add_entry_nodes = 0; void entry_nodes_should_be_added(void) { - log_info(LD_CIRC, "New EntryNodes config option detected. Will use."); + log_info(LD_CIRC, "EntryNodes config option set. Putting configured " + "relays at the front of the entry guard list."); 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. */ static void -entry_guards_prepend_from_config(void) +entry_guards_prepend_from_config(or_options_t *options) { - or_options_t *options = get_options(); smartlist_t *entry_routers, *entry_fps; smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list; tor_assert(entry_guards); @@ -2497,7 +3846,7 @@ entry_guards_prepend_from_config(void) return; } - if (options->EntryNodes) { + { char *string = routerset_to_string(options->EntryNodes); log_info(LD_CIRC,"Adding configured EntryNodes '%s'.", string); tor_free(string); @@ -2541,8 +3890,9 @@ entry_guards_prepend_from_config(void) SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, { add_an_entry_guard(ri, 0); }); - /* Finally, the remaining EntryNodes, unless we're strict */ - if (options->StrictEntryNodes) { + /* Finally, the remaining previously configured guards that are not in + * EntryNodes, unless we're strict in which case we drop them */ + if (options->StrictNodes) { SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e, entry_guard_free(e)); } else { @@ -2556,16 +3906,30 @@ entry_guards_prepend_from_config(void) entry_guards_changed(); } -/** Return 1 if we're fine adding arbitrary routers out of the - * directory to our entry guard list. Else return 0. */ +/** Return 0 if we're fine adding arbitrary routers out of the + * directory to our entry guard list, or return 1 if we have a + * list already and we'd prefer to stick to it. + */ int -entry_list_can_grow(or_options_t *options) +entry_list_is_constrained(or_options_t *options) { - if (options->StrictEntryNodes) - return 0; + if (options->EntryNodes) + return 1; if (options->UseBridges) - return 0; - return 1; + return 1; + return 0; +} + +/* Are we dead set against changing our entry guard list, or would we + * change it if it means keeping Tor usable? */ +static int +entry_list_is_totally_static(or_options_t *options) +{ + if (options->EntryNodes && options->StrictNodes) + return 1; + if (options->UseBridges) + return 1; + return 0; } /** Pick a live (up and listed) entry guard from entry_guards. If @@ -2583,7 +3947,7 @@ choose_random_entry(cpath_build_state_t *state) routerinfo_t *r = NULL; int need_uptime = state ? state->need_uptime : 0; int need_capacity = state ? state->need_capacity : 0; - int consider_exit_family = 0; + int preferred_min, consider_exit_family = 0; if (chosen_exit) { smartlist_add(exit_family, chosen_exit); @@ -2595,38 +3959,62 @@ choose_random_entry(cpath_build_state_t *state) entry_guards = smartlist_create(); if (should_add_entry_nodes) - entry_guards_prepend_from_config(); + entry_guards_prepend_from_config(options); - if (entry_list_can_grow(options) && - (! entry_guards || - smartlist_len(entry_guards) < options->NumEntryGuards)) - pick_entry_guards(); + if (!entry_list_is_constrained(options) && + smartlist_len(entry_guards) < options->NumEntryGuards) + pick_entry_guards(options); retry: smartlist_clear(live_entry_guards); SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, { - r = entry_is_live(entry, need_uptime, need_capacity, 0); - if (r && (!consider_exit_family || !smartlist_isin(exit_family, r))) { - smartlist_add(live_entry_guards, r); - if (!entry->made_contact) { - /* Always start with the first not-yet-contacted entry - * guard. Otherwise we might add several new ones, pick - * the second new one, and now we've expanded our entry - * guard list without needing to. */ - goto choose_and_finish; + const char *msg; + r = entry_is_live(entry, need_uptime, need_capacity, 0, &msg); + if (!r) + continue; /* down, no point */ + if (consider_exit_family && smartlist_isin(exit_family, r)) + continue; /* avoid relays that are family members of our exit */ + if (options->EntryNodes && + !routerset_contains_router(options->EntryNodes, r)) { + /* 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 */ + tor_fragile_assert(); + } else { + log_info(LD_CIRC, + "No relays from EntryNodes available. Using others."); } - if (smartlist_len(live_entry_guards) >= options->NumEntryGuards) - break; /* we have enough */ } + smartlist_add(live_entry_guards, r); + if (!entry->made_contact) { + /* Always start with the first not-yet-contacted entry + * guard. Otherwise we might add several new ones, pick + * the second new one, and now we've expanded our entry + * guard list without needing to. */ + goto choose_and_finish; + } + if (smartlist_len(live_entry_guards) >= options->NumEntryGuards) + break; /* we have enough */ }); - /* Try to have at least 2 choices available. This way we don't - * get stuck with a single live-but-crummy entry and just keep - * using him. - * (We might get 2 live-but-crummy entry guards, but so be it.) */ - if (smartlist_len(live_entry_guards) < 2) { - if (entry_list_can_grow(options)) { + if (entry_list_is_constrained(options)) { + /* If we prefer the entry nodes we've got, and we have at least + * one choice, that's great. Use it. */ + preferred_min = 1; + } else { + /* Try to have at least 2 choices available. This way we don't + * get stuck with a single live-but-crummy entry and just keep + * using him. + * (We might get 2 live-but-crummy entry guards, but so be it.) */ + preferred_min = 2; + } + + if (smartlist_len(live_entry_guards) < preferred_min) { + if (!entry_list_is_totally_static(options)) { /* still no? try adding a new entry then */ /* 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 @@ -2651,7 +4039,7 @@ choose_random_entry(cpath_build_state_t *state) need_capacity = 0; goto retry; } - if (!r && !entry_list_can_grow(options) && consider_exit_family) { + if (!r && 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. */ @@ -2662,15 +4050,15 @@ choose_random_entry(cpath_build_state_t *state) } choose_and_finish: - if (entry_list_can_grow(options)) { + 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); + } 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); - } else { - /* 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); } smartlist_free(live_entry_guards); smartlist_free(exit_family); @@ -2804,7 +4192,7 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg) entry_guards_dirty = 0; /* XXX022 hand new_entry_guards to this func, and move it up a * few lines, so we don't have to re-dirty it */ - if (remove_obsolete_entry_guards()) + if (remove_obsolete_entry_guards(now)) entry_guards_dirty = 1; } digestmap_free(added_by, _tor_free); @@ -2903,9 +4291,11 @@ entry_guards_update_state(or_state_t *state) * */ int getinfo_helper_entry_guards(control_connection_t *conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { - int use_long_names = conn->use_long_names; + (void) conn; + (void) errmsg; if (!strcmp(question,"entry-guards") || !strcmp(question,"helper-nodes")) { @@ -2914,12 +4304,13 @@ getinfo_helper_entry_guards(control_connection_t *conn, char nbuf[MAX_VERBOSE_NICKNAME_LEN+1]; if (!entry_guards) entry_guards = smartlist_create(); - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, - { + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { size_t len = MAX_VERBOSE_NICKNAME_LEN+ISO_TIME_LEN+32; char *c = tor_malloc(len); const char *status = NULL; time_t when = 0; + routerinfo_t *ri; + if (!e->made_contact) { status = "never-connected"; } else if (e->bad_since) { @@ -2928,19 +4319,17 @@ getinfo_helper_entry_guards(control_connection_t *conn, } else { status = "up"; } - if (use_long_names) { - routerinfo_t *ri = router_get_by_digest(e->identity); - if (ri) { - router_get_verbose_nickname(nbuf, ri); - } else { - nbuf[0] = '$'; - base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN); - /* e->nickname field is not very reliable if we don't know about - * this router any longer; don't include it. */ - } + + ri = router_get_by_digest(e->identity); + if (ri) { + router_get_verbose_nickname(nbuf, ri); } else { - base16_encode(nbuf, sizeof(nbuf), e->identity, DIGEST_LEN); + nbuf[0] = '$'; + base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN); + /* e->nickname field is not very reliable if we don't know about + * this router any longer; don't include it. */ } + if (when) { format_iso_time(tbuf, when); tor_snprintf(c, len, "%s %s %s\n", nbuf, status, tbuf); @@ -2948,7 +4337,7 @@ getinfo_helper_entry_guards(control_connection_t *conn, tor_snprintf(c, len, "%s %s\n", nbuf, status); } smartlist_add(sl, c); - }); + } SMARTLIST_FOREACH_END(e); *answer = smartlist_join_strings(sl, "", 0, NULL); SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); @@ -2989,29 +4378,56 @@ clear_bridge_list(void) * (either by comparing keys if possible, else by comparing addr/port). * Else return NULL. */ static bridge_info_t * -routerinfo_get_configured_bridge(routerinfo_t *ri) +get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port, + const char *digest) { if (!bridge_list) return NULL; SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) { if (tor_digest_is_zero(bridge->identity) && - tor_addr_eq_ipv4h(&bridge->addr, ri->addr) && - bridge->port == ri->or_port) + !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) && + bridge->port == port) return bridge; - if (!memcmp(bridge->identity, ri->cache_info.identity_digest, - DIGEST_LEN)) + if (!memcmp(bridge->identity, digest, DIGEST_LEN)) return bridge; } SMARTLIST_FOREACH_END(bridge); return NULL; } +/** 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) +{ + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, ri->addr); + return get_configured_bridge_by_addr_port_digest(&addr, + ri->or_port, ri->cache_info.identity_digest); +} + /** Return 1 if <b>ri</b> is one of our known bridges, else 0. */ int routerinfo_is_a_configured_bridge(routerinfo_t *ri) { - return routerinfo_get_configured_bridge(ri) ? 1 : 0; + return get_configured_bridge_by_routerinfo(ri) ? 1 : 0; +} + +/** 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. + */ +void +learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest) +{ + bridge_info_t *bridge = + get_configured_bridge_by_addr_port_digest(addr, port, digest); + if (bridge && tor_digest_is_zero(bridge->identity)) { + memcpy(bridge->identity, digest, DIGEST_LEN); + log_notice(LD_DIR, "Learned fingerprint %s for bridge %s:%d", + hex_str(digest, DIGEST_LEN), fmt_addr(addr), port); + } } /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b> @@ -3081,9 +4497,8 @@ 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(time_t now) +fetch_bridge_descriptors(or_options_t *options, time_t now) { - or_options_t *options = get_options(); int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY); int ask_bridge_directly; int can_use_bridge_authority; @@ -3151,7 +4566,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE); if (get_options()->UseBridges) { int first = !any_bridge_descriptors_known(); - bridge_info_t *bridge = routerinfo_get_configured_bridge(ri); + bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri); time_t now = time(NULL); ri->is_running = 1; @@ -3207,26 +4622,38 @@ any_pending_bridge_descriptor_fetches(void) return 0; } -/** Return 1 if we have at least one descriptor for a bridge and - * all descriptors we know are down. Else return 0. If <b>act</b> is - * 1, then mark the down bridges up; else just observe and report. */ +/** Return 1 if we have at least one descriptor for an entry guard + * (bridge or member of EntryNodes) and all descriptors we know are + * down. Else return 0. If <b>act</b> is 1, then mark the down guards + * up; else just observe and report. */ static int -bridges_retry_helper(int act) +entries_retry_helper(or_options_t *options, int act) { routerinfo_t *ri; int any_known = 0; int any_running = 0; + int purpose = options->UseBridges ? + ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL; 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 == ROUTER_PURPOSE_BRIDGE) { + if (ri && ri->purpose == purpose) { any_known = 1; if (ri->is_running) - any_running = 1; /* some bridge is both known and running */ - else if (act) { /* mark it for retry */ - ri->is_running = 1; + any_running = 1; /* some entry is both known and running */ + else if (act) { + /* Mark all current connections to this OR as unhealthy, since + * otherwise there could be one that started 30 seconds + * ago, and in 30 seconds it will time out, causing us to mark + * 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); + + /* mark this entry node for retry */ + router_set_status(ri->cache_info.identity_digest, 1); e->can_retry = 1; e->bad_since = 0; } @@ -3237,19 +4664,21 @@ bridges_retry_helper(int act) return any_known && !any_running; } -/** Do we know any descriptors for our bridges, and are they all - * down? */ +/** Do we know any descriptors for our bridges / entrynodes, and are + * all the ones we have descriptors for down? */ int -bridges_known_but_down(void) +entries_known_but_down(or_options_t *options) { - return bridges_retry_helper(0); + tor_assert(entry_list_is_constrained(options)); + return entries_retry_helper(options, 0); } -/** Mark all down known bridges up. */ +/** Mark all down known bridges / entrynodes up. */ void -bridges_retry_all(void) +entries_retry_all(or_options_t *options) { - bridges_retry_helper(1); + tor_assert(entry_list_is_constrained(options)); + entries_retry_helper(options, 1); } /** Release all storage held by the list of entry guards and related diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h new file mode 100644 index 0000000000..a85c410133 --- /dev/null +++ b/src/or/circuitbuild.h @@ -0,0 +1,125 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuitbuild.h + * \brief Header file for circuitbuild.c. + **/ + +#ifndef _TOR_CIRCUITBUILD_H +#define _TOR_CIRCUITBUILD_H + +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, + origin_circuit_t *circ); +void circuit_rep_hist_note_result(origin_circuit_t *circ); +origin_circuit_t *origin_circuit_init(uint8_t purpose, int flags); +origin_circuit_t *circuit_establish_circuit(uint8_t purpose, + extend_info_t *exit, + int flags); +int circuit_handle_first_hop(origin_circuit_t *circ); +void circuit_n_conn_done(or_connection_t *or_conn, int status); +int inform_testing_reachability(void); +int circuit_timeout_want_to_count_circ(origin_circuit_t *circ); +int circuit_send_next_onion_skin(origin_circuit_t *circ); +void circuit_note_clock_jumped(int seconds_elapsed); +int circuit_extend(cell_t *cell, circuit_t *circ); +int circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data, + int reverse); +int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type, + const uint8_t *reply); +int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer); +int onionskin_answer(or_circuit_t *circ, uint8_t cell_type, + const char *payload, const char *keys); +int circuit_all_predicted_ports_handled(time_t now, int *need_uptime, + int *need_capacity); + +int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info); +int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info); +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_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 char *build_state_get_exit_nickname(cpath_build_state_t *state); + +void entry_guards_compute_status(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_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, + const char *question, char **answer, + const char **errmsg); + +void clear_bridge_list(void); +int routerinfo_is_a_configured_bridge(routerinfo_t *ri); +void +learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest); +void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, + char *digest); +void retry_bridge_descriptor_fetch_directly(const char *digest); +void fetch_bridge_descriptors(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); + +void entry_guards_free_all(void); + +extern circuit_build_times_t circ_times; +int circuit_build_times_enough_to_compute(circuit_build_times_t *cbt); +void circuit_build_times_update_state(circuit_build_times_t *cbt, + or_state_t *state); +int circuit_build_times_parse_state(circuit_build_times_t *cbt, + or_state_t *state); +void circuit_build_times_count_timeout(circuit_build_times_t *cbt, + int did_onehop); +int circuit_build_times_count_close(circuit_build_times_t *cbt, + int did_onehop, time_t start_time); +void circuit_build_times_set_timeout(circuit_build_times_t *cbt); +int circuit_build_times_add_time(circuit_build_times_t *cbt, + build_time_t time); +int circuit_build_times_needs_circuits(circuit_build_times_t *cbt); + +int circuit_build_times_needs_circuits_now(circuit_build_times_t *cbt); +void circuit_build_times_init(circuit_build_times_t *cbt); +void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt, + networkstatus_t *ns); +double circuit_build_times_timeout_rate(const circuit_build_times_t *cbt); +double circuit_build_times_close_rate(const circuit_build_times_t *cbt); + +#ifdef CIRCUIT_PRIVATE +double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt, + double quantile); +build_time_t circuit_build_times_generate_sample(circuit_build_times_t *cbt, + double q_lo, double q_hi); +void circuit_build_times_initial_alpha(circuit_build_times_t *cbt, + double quantile, double time_ms); +int circuit_build_times_update_alpha(circuit_build_times_t *cbt); +double circuit_build_times_cdf(circuit_build_times_t *cbt, double x); +void circuitbuild_running_unit_tests(void); +void circuit_build_times_reset(circuit_build_times_t *cbt); + +/* Network liveness functions */ +int circuit_build_times_network_check_changed(circuit_build_times_t *cbt); +#endif + +/* Network liveness functions */ +void circuit_build_times_network_is_live(circuit_build_times_t *cbt); +int circuit_build_times_network_check_live(circuit_build_times_t *cbt); +void circuit_build_times_network_circ_success(circuit_build_times_t *cbt); + +#endif + diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index b84d7f7623..fb4b69be0d 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -10,6 +10,21 @@ **/ #include "or.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "connection.h" +#include "config.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "networkstatus.h" +#include "onion.h" +#include "relay.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rephist.h" +#include "routerlist.h" #include "ht.h" /********* START VARIABLES **********/ @@ -352,6 +367,8 @@ circuit_purpose_to_controller_string(uint8_t purpose) case CIRCUIT_PURPOSE_TESTING: return "TESTING"; + case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT: + return "MEASURE_TIMEOUT"; case CIRCUIT_PURPOSE_CONTROLLER: return "CONTROLLER"; @@ -380,10 +397,17 @@ static void init_circuit_base(circuit_t *circ) { circ->timestamp_created = time(NULL); + tor_gettimeofday(&circ->highres_created); circ->package_window = circuit_initial_package_window(); circ->deliver_window = CIRCWINDOW_START; + /* Initialize the cell_ewma_t structure */ + circ->n_cell_ewma.last_adjusted_tick = cell_ewma_get_tick(); + circ->n_cell_ewma.cell_count = 0.0; + circ->n_cell_ewma.heap_index = -1; + circ->n_cell_ewma.is_for_p_conn = 0; + circuit_add(circ); } @@ -408,6 +432,8 @@ origin_circuit_new(void) init_circuit_base(TO_CIRCUIT(circ)); + circ_times.last_circ_at = approx_time(); + return circ; } @@ -429,6 +455,16 @@ or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn) init_circuit_base(TO_CIRCUIT(circ)); + /* Initialize the cell_ewma_t structure */ + + /* Initialize the cell counts to 0 */ + circ->p_cell_ewma.cell_count = 0.0; + circ->p_cell_ewma.last_adjusted_tick = cell_ewma_get_tick(); + circ->p_cell_ewma.is_for_p_conn = 1; + + /* It's not in any heap yet. */ + circ->p_cell_ewma.heap_index = -1; + return circ; } @@ -439,39 +475,37 @@ circuit_free(circuit_t *circ) { void *mem; size_t memlen; - tor_assert(circ); + if (!circ) + return; + if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); mem = ocirc; memlen = sizeof(origin_circuit_t); tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC); if (ocirc->build_state) { - if (ocirc->build_state->chosen_exit) extend_info_free(ocirc->build_state->chosen_exit); - if (ocirc->build_state->pending_final_cpath) circuit_free_cpath_node(ocirc->build_state->pending_final_cpath); } tor_free(ocirc->build_state); circuit_free_cpath(ocirc->cpath); - if (ocirc->intro_key) - crypto_free_pk_env(ocirc->intro_key); - if (ocirc->rend_data) - rend_data_free(ocirc->rend_data); + + crypto_free_pk_env(ocirc->intro_key); + rend_data_free(ocirc->rend_data); } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); + /* Remember cell statistics for this circuit before deallocating. */ + if (get_options()->CellStatistics) + rep_hist_buffer_stats_add_circ(circ, time(NULL)); mem = ocirc; memlen = sizeof(or_circuit_t); tor_assert(circ->magic == OR_CIRCUIT_MAGIC); - if (ocirc->p_crypto) - crypto_free_cipher_env(ocirc->p_crypto); - if (ocirc->p_digest) - crypto_free_digest_env(ocirc->p_digest); - if (ocirc->n_crypto) - crypto_free_cipher_env(ocirc->n_crypto); - if (ocirc->n_digest) - crypto_free_digest_env(ocirc->n_digest); + crypto_free_cipher_env(ocirc->p_crypto); + crypto_free_digest_env(ocirc->p_digest); + crypto_free_cipher_env(ocirc->n_crypto); + crypto_free_digest_env(ocirc->n_digest); if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; @@ -487,8 +521,7 @@ circuit_free(circuit_t *circ) cell_queue_clear(ô->p_conn_cells); } - if (circ->n_hop) - extend_info_free(circ->n_hop); + extend_info_free(circ->n_hop); tor_free(circ->n_conn_onionskin); /* Remove from map. */ @@ -498,7 +531,7 @@ circuit_free(circuit_t *circ) * "active" checks will be violated. */ cell_queue_clear(&circ->n_conn_cells); - memset(circ, 0xAA, memlen); /* poison memory */ + memset(mem, 0xAA, memlen); /* poison memory */ tor_free(mem); } @@ -541,10 +574,10 @@ circuit_free_all(void) circuit_free(global_circuitlist); global_circuitlist = next; } - if (circuits_pending_or_conns) { - smartlist_free(circuits_pending_or_conns); - circuits_pending_or_conns = NULL; - } + + smartlist_free(circuits_pending_or_conns); + circuits_pending_or_conns = NULL; + HT_CLEAR(orconn_circid_map, &orconn_circid_circuit_map); } @@ -552,18 +585,15 @@ circuit_free_all(void) static void circuit_free_cpath_node(crypt_path_t *victim) { - if (victim->f_crypto) - crypto_free_cipher_env(victim->f_crypto); - if (victim->b_crypto) - crypto_free_cipher_env(victim->b_crypto); - if (victim->f_digest) - crypto_free_digest_env(victim->f_digest); - if (victim->b_digest) - crypto_free_digest_env(victim->b_digest); - if (victim->dh_handshake_state) - crypto_dh_free(victim->dh_handshake_state); - if (victim->extend_info) - extend_info_free(victim->extend_info); + if (!victim) + return; + + crypto_free_cipher_env(victim->f_crypto); + crypto_free_cipher_env(victim->b_crypto); + crypto_free_digest_env(victim->f_digest); + crypto_free_digest_env(victim->b_digest); + crypto_dh_free(victim->dh_handshake_state); + extend_info_free(victim->extend_info); memset(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */ tor_free(victim); @@ -892,6 +922,10 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0; int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0; + /* Make sure we're not trying to create a onehop circ by + * cannibalization. */ + tor_assert(!(flags & CIRCLAUNCH_ONEHOP_TUNNEL)); + log_debug(LD_CIRC, "Hunting for a circ to cannibalize: purpose %d, uptime %d, " "capacity %d, internal %d", @@ -907,7 +941,8 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, if ((!need_uptime || circ->build_state->need_uptime) && (!need_capacity || circ->build_state->need_capacity) && (internal == circ->build_state->is_internal) && - circ->remaining_relay_early_cells) { + circ->remaining_relay_early_cells && + !circ->build_state->onehop_tunnel) { if (info) { /* need to make sure we don't duplicate hops */ crypt_path_t *hop = circ->cpath; @@ -1083,14 +1118,16 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, tor_assert(ocirc->rend_data); /* treat this like getting a nack from it */ log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). " - "Removing from descriptor.", - safe_str(ocirc->rend_data->onion_address), - safe_str(build_state_get_exit_nickname(ocirc->build_state))); + "Removing from descriptor.", + safe_str_client(ocirc->rend_data->onion_address), + safe_str_client(build_state_get_exit_nickname(ocirc->build_state))); rend_client_remove_intro_point(ocirc->build_state->chosen_exit, ocirc->rend_data); } - if (circ->n_conn) + if (circ->n_conn) { + circuit_clear_cell_queue(circ, circ->n_conn); connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason); + } if (! CIRCUIT_IS_ORIGIN(circ)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); @@ -1114,8 +1151,10 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, conn->on_circuit = NULL; } - if (or_circ->p_conn) + if (or_circ->p_conn) { + circuit_clear_cell_queue(circ, or_circ->p_conn); connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason); + } } else { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); edge_connection_t *conn; @@ -1236,11 +1275,6 @@ assert_circuit_ok(const circuit_t *c) tor_assert(c == c2); } } -#if 0 /* false now that rendezvous exits are attached to p_streams */ - if (origin_circ) - for (conn = origin_circ->p_streams; conn; conn = conn->next_stream) - tor_assert(conn->_base.type == CONN_TYPE_AP); -#endif if (or_circ) for (conn = or_circ->n_streams; conn; conn = conn->next_stream) tor_assert(conn->_base.type == CONN_TYPE_EXIT); diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h new file mode 100644 index 0000000000..caca614c8c --- /dev/null +++ b/src/or/circuitlist.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-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuitlist.h + * \brief Header file for circuitlist.c. + **/ + +#ifndef _TOR_CIRCUITLIST_H +#define _TOR_CIRCUITLIST_H + +circuit_t * _circuit_get_global_list(void); +const char *circuit_state_to_string(int state); +const char *circuit_purpose_to_controller_string(uint8_t purpose); +void circuit_dump_by_conn(connection_t *conn, int severity); +void circuit_set_p_circid_orconn(or_circuit_t *circ, circid_t id, + or_connection_t *conn); +void circuit_set_n_circid_orconn(circuit_t *circ, circid_t id, + or_connection_t *conn); +void circuit_set_state(circuit_t *circ, uint8_t state); +void circuit_close_all_marked(void); +int32_t circuit_initial_package_window(void); +origin_circuit_t *origin_circuit_new(void); +or_circuit_t *or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn); +circuit_t *circuit_get_by_circid_orconn(circid_t circ_id, + or_connection_t *conn); +int circuit_id_in_use_on_orconn(circid_t circ_id, or_connection_t *conn); +circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn); +void circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason); +origin_circuit_t *circuit_get_by_global_id(uint32_t id); +origin_circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, + uint8_t purpose); +origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, + const char *digest, uint8_t purpose); +or_circuit_t *circuit_get_rendezvous(const char *cookie); +or_circuit_t *circuit_get_intro_point(const char *digest); +origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose, + extend_info_t *info, int flags); +void circuit_mark_all_unused_circs(void); +void circuit_expire_all_dirty_circs(void); +void _circuit_mark_for_close(circuit_t *circ, int reason, + int line, const char *file); +int circuit_get_cpath_len(origin_circuit_t *circ); +crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum); +void circuit_get_all_pending_on_or_conn(smartlist_t *out, + or_connection_t *or_conn); +int circuit_count_pending_on_or_conn(or_connection_t *or_conn); + +#define circuit_mark_for_close(c, reason) \ + _circuit_mark_for_close((c), (reason), __LINE__, _SHORT_FILE_) + +void assert_cpath_layer_ok(const crypt_path_t *cp); +void assert_circuit_ok(const circuit_t *c); +void circuit_free_all(void); + +#endif + diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 827c4bbf2b..3af0fb642d 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -10,6 +10,20 @@ **/ #include "or.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "control.h" +#include "policies.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rendservice.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" /********* START VARIABLES **********/ @@ -113,7 +127,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, return 0; } } - if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter)) { + if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter, 0)) { /* can't exit from this router */ return 0; } @@ -263,16 +277,22 @@ circuit_conforms_to_options(const origin_circuit_t *circ, void circuit_expire_building(time_t now) { - circuit_t *victim, *circ = global_circuitlist; - time_t general_cutoff = now - get_options()->CircuitBuildTimeout; - time_t begindir_cutoff = now - get_options()->CircuitBuildTimeout/2; + circuit_t *victim, *next_circ = global_circuitlist; + /* circ_times.timeout_ms and circ_times.close_ms are from + * circuit_build_times_get_initial_timeout() if we haven't computed + * custom timeouts yet */ + time_t general_cutoff = now - tor_lround(circ_times.timeout_ms/1000); + time_t begindir_cutoff = now - tor_lround(circ_times.timeout_ms/2000); + time_t fourhop_cutoff = now - tor_lround(4*circ_times.timeout_ms/3000); + time_t cannibalize_cutoff = now - tor_lround(circ_times.timeout_ms/2000); + time_t close_cutoff = now - tor_lround(circ_times.close_ms/1000); time_t introcirc_cutoff = begindir_cutoff; cpath_build_state_t *build_state; - while (circ) { + while (next_circ) { time_t cutoff; - victim = circ; - circ = circ->next; + victim = next_circ; + next_circ = next_circ->next; if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */ victim->marked_for_close) /* don't mess with marked circs */ continue; @@ -280,10 +300,18 @@ circuit_expire_building(time_t now) build_state = TO_ORIGIN_CIRCUIT(victim)->build_state; if (build_state && build_state->onehop_tunnel) cutoff = begindir_cutoff; + else if (build_state && build_state->desired_path_len == 4 + && !TO_ORIGIN_CIRCUIT(victim)->has_opened) + cutoff = fourhop_cutoff; + else if (TO_ORIGIN_CIRCUIT(victim)->has_opened) + cutoff = cannibalize_cutoff; else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING) cutoff = introcirc_cutoff; + else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) + cutoff = close_cutoff; else cutoff = general_cutoff; + if (victim->timestamp_created > cutoff) continue; /* it's still young, leave it alone */ @@ -343,6 +371,54 @@ circuit_expire_building(time_t now) continue; break; } + } else { /* circuit not open, consider recording failure as timeout */ + int first_hop_succeeded = TO_ORIGIN_CIRCUIT(victim)->cpath && + TO_ORIGIN_CIRCUIT(victim)->cpath->state == CPATH_STATE_OPEN; + + if (TO_ORIGIN_CIRCUIT(victim)->p_streams != NULL) { + log_warn(LD_BUG, "Circuit %d (purpose %d) has timed out, " + "yet has attached streams!", + TO_ORIGIN_CIRCUIT(victim)->global_identifier, + victim->purpose); + tor_fragile_assert(); + continue; + } + + if (circuit_timeout_want_to_count_circ(TO_ORIGIN_CIRCUIT(victim)) && + circuit_build_times_enough_to_compute(&circ_times)) { + /* Circuits are allowed to last longer for measurement. + * Switch their purpose and wait. */ + if (victim->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + control_event_circuit_status(TO_ORIGIN_CIRCUIT(victim), + CIRC_EVENT_FAILED, + END_CIRC_REASON_TIMEOUT); + victim->purpose = CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT; + /* Record this failure to check for too many timeouts + * in a row. This function does not record a time value yet + * (we do that later); it only counts the fact that we did + * have a timeout. */ + circuit_build_times_count_timeout(&circ_times, + first_hop_succeeded); + continue; + } + + /* + * If the circuit build time is much greater than we would have cut + * it off at, we probably had a suspend event along this codepath, + * and we should discard the value. + */ + if (now - victim->timestamp_created > 2*circ_times.close_ms/1000+1) { + log_notice(LD_CIRC, + "Extremely large value for circuit build timeout: %lds. " + "Assuming clock jump. Purpose %d", + (long)(now - victim->timestamp_created), + victim->purpose); + } else if (circuit_build_times_count_close(&circ_times, + first_hop_succeeded, + victim->timestamp_created)) { + circuit_build_times_set_timeout(&circ_times); + } + } } if (victim->n_conn) @@ -357,7 +433,10 @@ circuit_expire_building(time_t now) circuit_state_to_string(victim->state), victim->purpose); circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim)); - circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT); + if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) + circuit_mark_for_close(victim, END_CIRC_REASON_MEASUREMENT_EXPIRED); + else + circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT); } } @@ -414,7 +493,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn, if (exitrouter && (!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, exitrouter, 0); } else { addr_policy_result_t r = compare_addr_to_addr_policy( 0, port, exitrouter->exit_policy); @@ -431,11 +510,11 @@ circuit_stream_is_being_handled(edge_connection_t *conn, } /** Don't keep more than this many unused open circuits around. */ -#define MAX_UNUSED_OPEN_CIRCUITS 12 +#define MAX_UNUSED_OPEN_CIRCUITS 14 /** Figure out how many circuits we have open that are clean. Make * sure it's enough for all the upcoming behaviors we predict we'll have. - * But if we have too many, close the not-so-useful ones. + * But put an upper bound on the total number of circuits. */ static void circuit_predict_and_launch_new(void) @@ -517,6 +596,19 @@ circuit_predict_and_launch_new(void) circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags); return; } + + /* Finally, check to see if we still need more circuits to learn + * a good build timeout. But if we're close to our max number we + * want, don't do another -- we want to leave a few slots open so + * we can still build circuits preemptively as needed. */ + if (num < MAX_UNUSED_OPEN_CIRCUITS-2 && + circuit_build_times_needs_circuits_now(&circ_times)) { + 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); + return; + } } /** Build a new test circuit every 5 minutes */ @@ -624,6 +716,11 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) tor_fragile_assert(); } +/** If we haven't yet decided on a good timeout value for circuit + * building, we close idles circuits aggressively so we can get more + * data points. */ +#define IDLE_TIMEOUT_WHILE_LEARNING (10*60) + /** Find each circuit that has been unused for too long, or dirty * for too long and has no streams on it: mark it for close. */ @@ -631,10 +728,18 @@ static void circuit_expire_old_circuits_clientside(time_t now) { circuit_t *circ; - time_t cutoff = now - get_options()->CircuitIdleTimeout; + time_t cutoff; + + if (circuit_build_times_needs_circuits(&circ_times)) { + /* Circuits should be shorter lived if we need more of them + * for learning a good build timeout */ + cutoff = now - IDLE_TIMEOUT_WHILE_LEARNING; + } else { + cutoff = now - get_options()->CircuitIdleTimeout; + } for (circ = global_circuitlist; circ; circ = circ->next) { - if (circ->marked_for_close || ! CIRCUIT_IS_ORIGIN(circ)) + if (circ->marked_for_close || !CIRCUIT_IS_ORIGIN(circ)) continue; /* If the circuit has been dirty for too long, and there are no streams * on it, mark it for close. @@ -647,14 +752,38 @@ circuit_expire_old_circuits_clientside(time_t now) circ->n_circ_id, (int)(now - circ->timestamp_dirty), circ->purpose); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); - } else if (!circ->timestamp_dirty && - circ->state == CIRCUIT_STATE_OPEN && - circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) { + } else if (!circ->timestamp_dirty && circ->state == CIRCUIT_STATE_OPEN) { if (circ->timestamp_created < cutoff) { - log_debug(LD_CIRC, - "Closing circuit that has been unused for %d seconds.", - (int)(now - circ->timestamp_created)); - circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); + if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL || + circ->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT || + circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || + circ->purpose == CIRCUIT_PURPOSE_TESTING || + (circ->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING && + circ->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) || + circ->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) { + log_debug(LD_CIRC, + "Closing circuit that has been unused for %ld seconds.", + (long)(now - circ->timestamp_created)); + circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); + } else if (!TO_ORIGIN_CIRCUIT(circ)->is_ancient) { + /* Server-side rend joined circuits can end up really old, because + * they are reused by clients for longer than normal. The client + * controls their lifespan. (They never become dirty, because + * connection_exit_begin_conn() never marks anything as dirty.) + * Similarly, server-side intro circuits last a long time. */ + if (circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED && + circ->purpose != CIRCUIT_PURPOSE_S_INTRO) { + log_notice(LD_CIRC, + "Ancient non-dirty circuit %d is still around after " + "%ld seconds. Purpose: %d", + TO_ORIGIN_CIRCUIT(circ)->global_identifier, + (long)(now - circ->timestamp_created), + circ->purpose); + /* FFFF implement a new circuit_purpose_to_string() so we don't + * just print out a number for circ->purpose */ + TO_ORIGIN_CIRCUIT(circ)->is_ancient = 1; + } + } } } } @@ -794,6 +923,11 @@ circuit_has_opened(origin_circuit_t *circ) { control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0); + /* Remember that this circuit has finished building. Now if we start + * it building again later (e.g. by extending it), we will know not + * to consider its build time. */ + circ->has_opened = 1; + switch (TO_CIRCUIT(circ)->purpose) { case CIRCUIT_PURPOSE_C_ESTABLISH_REND: rend_client_rendcirc_has_opened(circ); @@ -846,15 +980,29 @@ circuit_build_failed(origin_circuit_t *circ) * to blame, blame it. Also, avoid this relay for a while, and * fail any one-hop directory fetches destined for it. */ const char *n_conn_id = circ->cpath->extend_info->identity_digest; + int already_marked = 0; if (circ->_base.n_conn) { or_connection_t *n_conn = circ->_base.n_conn; + if (n_conn->is_bad_for_new_circs) { + /* We only want to blame this router when a fresh healthy + * connection fails. So don't mark this router as newly failed, + * since maybe this was just an old circuit attempt that's + * finally timing out now. Also, there's no need to blow away + * circuits/streams/etc, since the failure of an unhealthy conn + * doesn't tell us much about whether a healthy conn would + * succeed. */ + already_marked = 1; + } log_info(LD_OR, "Our circuit failed to get a response from the first hop " "(%s:%d). I'm going to try to rotate to a better connection.", n_conn->_base.address, n_conn->_base.port); n_conn->is_bad_for_new_circs = 1; + } else { + log_info(LD_OR, + "Our circuit died before the first hop with no connection"); } - if (n_conn_id) { + if (n_conn_id && !already_marked) { entry_guard_register_connect_status(n_conn_id, 0, 1, time(NULL)); /* if there are any one-hop streams waiting on this circuit, fail * them now so they can retry elsewhere. */ @@ -936,8 +1084,8 @@ circuit_launch_by_router(uint8_t purpose, if (exit) info = extend_info_from_router(exit); circ = circuit_launch_by_extend_info(purpose, info, flags); - if (info) - extend_info_free(info); + + extend_info_free(info); return circ; } @@ -1080,15 +1228,17 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, int severity = LOG_NOTICE; /* FFFF if this is a tunneled directory fetch, don't yell * as loudly. the user doesn't even know it's happening. */ - if (options->UseBridges && bridges_known_but_down()) { + if (entry_list_is_constrained(options) && + entries_known_but_down(options)) { log_fn(severity, LD_APP|LD_DIR, - "Application request when we're believed to be " - "offline. Optimistically trying known bridges again."); - bridges_retry_all(); + "Application request when we haven't used client functionality " + "lately. Optimistically trying known %s again.", + options->UseBridges ? "bridges" : "entrynodes"); + entries_retry_all(options); } else if (!options->UseBridges || any_bridge_descriptors_known()) { log_fn(severity, LD_APP|LD_DIR, - "Application request when we're believed to be " - "offline. Optimistically trying directory fetches again."); + "Application request when we haven't used client functionality " + "lately. Optimistically trying directory fetches again."); routerlist_retry_directory_downloads(time(NULL)); } } @@ -1111,7 +1261,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, need_uptime)) { log_notice(LD_APP, "No Tor server allows exit to %s:%d. Rejecting.", - safe_str(conn->socks_request->address), + safe_str_client(conn->socks_request->address), conn->socks_request->port); return -1; } @@ -1119,7 +1269,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, /* XXXX022 Duplicates checks in connection_ap_handshake_attach_circuit */ routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); int opt = conn->chosen_exit_optional; - if (router && !connection_ap_can_use_exit(conn, router)) { + if (router && !connection_ap_can_use_exit(conn, router, 0)) { log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, "Requested exit point '%s' would refuse request. %s.", conn->chosen_exit_name, opt ? "Trying others" : "Closing"); @@ -1152,19 +1302,14 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, if (!extend_info) { log_info(LD_REND, "No intro points for '%s': re-fetching service descriptor.", - safe_str(conn->rend_data->onion_address)); - /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever - * arrives first. Exception: When using client authorization, only - * fetch v2 descriptors.*/ + safe_str_client(conn->rend_data->onion_address)); rend_client_refetch_v2_renddesc(conn->rend_data); - if (conn->rend_data->auth_type == REND_NO_AUTH) - rend_client_refetch_renddesc(conn->rend_data->onion_address); conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; return 0; } log_info(LD_REND,"Chose '%s' as intro point for '%s'.", extend_info->nickname, - safe_str(conn->rend_data->onion_address)); + safe_str_client(conn->rend_data->onion_address)); } /* If we have specified a particular exit node for our @@ -1193,7 +1338,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, } if (tor_addr_from_str(&addr, conn->socks_request->address) < 0) { log_info(LD_DIR, "Broken address %s on tunnel conn. Closing.", - escaped_safe_str(conn->socks_request->address)); + escaped_safe_str_client(conn->socks_request->address)); return -1; } extend_info = extend_info_alloc(conn->chosen_exit_name+1, @@ -1235,8 +1380,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, flags); } - if (extend_info) - extend_info_free(extend_info); + extend_info_free(extend_info); if (desired_circuit_purpose != CIRCUIT_PURPOSE_C_GENERAL) { /* help predict this next time */ @@ -1418,7 +1562,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) LOG_INFO : LOG_NOTICE; log_fn(severity, LD_APP, "Tried for %d seconds to get a connection to %s:%d. Giving up.", - conn_age, safe_str(conn->socks_request->address), + conn_age, safe_str_client(conn->socks_request->address), conn->socks_request->port); return -1; } @@ -1445,7 +1589,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) } return -1; } - if (router && !connection_ap_can_use_exit(conn, router)) { + if (router && !connection_ap_can_use_exit(conn, router, 0)) { log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, "Requested exit point '%s' would refuse request. %s.", conn->chosen_exit_name, opt ? "Trying others" : "Closing"); diff --git a/src/or/circuituse.h b/src/or/circuituse.h new file mode 100644 index 0000000000..269b6c5f8f --- /dev/null +++ b/src/or/circuituse.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuituse.h + * \brief Header file for circuituse.c. + **/ + +#ifndef _TOR_CIRCUITUSE_H +#define _TOR_CIRCUITUSE_H + +void circuit_expire_building(time_t now); +void circuit_remove_handled_ports(smartlist_t *needed_ports); +int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, + int min); +int circuit_conforms_to_options(const origin_circuit_t *circ, + const or_options_t *options); +void circuit_build_needed_circs(time_t now); +void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn); + +void circuit_expire_old_circuits_serverside(time_t now); + +void reset_bandwidth_test(void); +int circuit_enough_testing_circs(void); + +void circuit_has_opened(origin_circuit_t *circ); +void circuit_build_failed(origin_circuit_t *circ); + +/** Flag to set when a circuit should have only a single hop. */ +#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0) +/** Flag to set when a circuit needs to be built of high-uptime nodes */ +#define CIRCLAUNCH_NEED_UPTIME (1<<1) +/** Flag to set when a circuit needs to be built of high-capacity nodes */ +#define CIRCLAUNCH_NEED_CAPACITY (1<<2) +/** Flag to set when the last hop of a circuit doesn't need to be an + * exit node. */ +#define CIRCLAUNCH_IS_INTERNAL (1<<3) +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); +void circuit_reset_failure_count(int timeout); +int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, + origin_circuit_t *circ, + crypt_path_t *cpath); +int connection_ap_handshake_attach_circuit(edge_connection_t *conn); + +#endif + diff --git a/src/or/command.c b/src/or/command.c index 011cc5aa37..beb5d09a9d 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -16,6 +16,19 @@ */ #include "or.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "command.h" +#include "connection.h" +#include "connection_or.h" +#include "config.h" +#include "control.h" +#include "cpuworker.h" +#include "hibernate.h" +#include "onion.h" +#include "relay.h" +#include "router.h" +#include "routerlist.h" /** How many CELL_PADDING cells have we received, ever? */ uint64_t stats_n_padding_cells_processed = 0; @@ -275,7 +288,14 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) /* hand it off to the cpuworkers, and then return. */ if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) { - log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing."); +#define WARN_HANDOFF_FAILURE_INTERVAL (6*60*60) + static ratelim_t handoff_warning = + RATELIM_INIT(WARN_HANDOFF_FAILURE_INTERVAL); + char *m; + if ((m = rate_limit_log(&handoff_warning, approx_time()))) { + log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.%s",m); + tor_free(m); + } circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return; } @@ -396,15 +416,18 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn) * gotten no more than MAX_RELAY_EARLY_CELLS_PER_CIRCUIT of them. */ if (cell->command == CELL_RELAY_EARLY) { if (direction == CELL_DIRECTION_IN) { - /* XXX Allow an unlimited number of inbound relay_early cells for - * now, for hidden service compatibility. See bug 1038. -RD */ + /* Allow an unlimited number of inbound relay_early cells, + * for hidden service compatibility. There isn't any way to make + * a long circuit through inbound relay_early cells anyway. See + * bug 1038. -RD */ } else { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); if (or_circ->remaining_relay_early_cells == 0) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Received too many RELAY_EARLY cells on circ %d from %s:%d." " Closing circuit.", - cell->circ_id, safe_str(conn->_base.address), conn->_base.port); + cell->circ_id, safe_str(conn->_base.address), + conn->_base.port); circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); return; } @@ -512,7 +535,8 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) conn->handshake_state->received_versions = 1; log_info(LD_OR, "Negotiated version %d with %s:%d; sending NETINFO.", - highest_supported_version, safe_str(conn->_base.address), + highest_supported_version, + safe_str_client(conn->_base.address), conn->_base.port); tor_assert(conn->link_proto >= 2); @@ -626,8 +650,8 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) else log_info(LD_OR, "Got good NETINFO cell from %s:%d; OR connection is now " "open, using protocol version %d", - safe_str(conn->_base.address), conn->_base.port, - (int)conn->link_proto); + safe_str_client(conn->_base.address), + conn->_base.port, (int)conn->link_proto); assert_connection_ok(TO_CONN(conn),time(NULL)); } diff --git a/src/or/command.h b/src/or/command.h new file mode 100644 index 0000000000..1aa56207f6 --- /dev/null +++ b/src/or/command.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file command.h + * \brief Header file for command.c. + **/ + +#ifndef _TOR_COMMAND_H +#define _TOR_COMMAND_H + +void command_process_cell(cell_t *cell, or_connection_t *conn); +void command_process_var_cell(var_cell_t *cell, or_connection_t *conn); + +extern uint64_t stats_n_padding_cells_processed; +extern uint64_t stats_n_create_cells_processed; +extern uint64_t stats_n_created_cells_processed; +extern uint64_t stats_n_relay_cells_processed; +extern uint64_t stats_n_destroy_cells_processed; + +#endif + diff --git a/src/or/config.c b/src/or/config.c index 70b99d7554..e3d5e606f9 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -12,6 +12,28 @@ #define CONFIG_PRIVATE #include "or.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "cpuworker.h" +#include "dirserv.h" +#include "dirvote.h" +#include "dns.h" +#include "geoip.h" +#include "hibernate.h" +#include "main.h" +#include "networkstatus.h" +#include "policies.h" +#include "relay.h" +#include "rendclient.h" +#include "rendservice.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" #ifdef MS_WINDOWS #include <shlobj.h> #endif @@ -61,11 +83,12 @@ static config_abbrev_t _option_abbrevs[] = { PLURAL(LongLivedPort), PLURAL(HiddenServiceNode), PLURAL(HiddenServiceExcludeNode), - PLURAL(NumCpu), + PLURAL(NumCPU), PLURAL(RendNode), PLURAL(RendExcludeNode), PLURAL(StrictEntryNode), PLURAL(StrictExitNode), + PLURAL(StrictNode), { "l", "Log", 1, 0}, { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0}, { "AutomapHostSuffixes", "AutomapHostsSuffixes", 0, 0}, @@ -83,10 +106,12 @@ static config_abbrev_t _option_abbrevs[] = { { "NumEntryNodes", "NumEntryGuards", 0, 0}, { "ResolvConf", "ServerDNSResolvConfFile", 0, 1}, { "SearchDomains", "ServerDNSSearchDomains", 0, 1}, - { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0 }, + { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0}, { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0}, { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0}, { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0}, + { "StrictEntryNodes", "StrictNodes", 0, 1}, + { "StrictExitNodes", "StrictNodes", 0, 1}, { NULL, NULL, 0, 0}, }; @@ -134,6 +159,7 @@ static config_var_t _option_vars[] = { V(AccountingMax, MEMUNIT, "0 bytes"), V(AccountingStart, STRING, NULL), V(Address, STRING, NULL), + V(AllowDotExit, BOOL, "0"), V(AllowInvalidNodes, CSV, "middle,rendezvous"), V(AllowNonRFC953Hostnames, BOOL, "0"), V(AllowSingleHopCircuits, BOOL, "0"), @@ -162,10 +188,15 @@ static config_var_t _option_vars[] = { V(BridgePassword, STRING, NULL), V(BridgeRecordUsageByCountry, BOOL, "1"), V(BridgeRelay, BOOL, "0"), - V(CircuitBuildTimeout, INTERVAL, "1 minute"), + V(CellStatistics, BOOL, "0"), + V(LearnCircuitBuildTimeout, BOOL, "1"), + V(CircuitBuildTimeout, INTERVAL, "0"), V(CircuitIdleTimeout, INTERVAL, "1 hour"), + V(CircuitStreamTimeout, INTERVAL, "0"), + V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/ V(ClientDNSRejectInternalAddresses, BOOL,"1"), V(ClientOnly, BOOL, "0"), + V(ConsensusParams, STRING, NULL), V(ConnLimit, UINT, "1000"), V(ConstrainedSockets, BOOL, "0"), V(ConstrainedSockSize, MEMUNIT, "8192"), @@ -186,18 +217,19 @@ static config_var_t _option_vars[] = { V(DirPort, UINT, "0"), V(DirPortFrontPage, FILENAME, NULL), OBSOLETE("DirPostPeriod"), -#ifdef ENABLE_GEOIP_STATS - V(DirRecordUsageByCountry, BOOL, "0"), - V(DirRecordUsageGranularity, UINT, "4"), - V(DirRecordUsageRetainIPs, INTERVAL, "14 days"), - V(DirRecordUsageSaveInterval, INTERVAL, "6 hours"), -#endif + OBSOLETE("DirRecordUsageByCountry"), + OBSOLETE("DirRecordUsageGranularity"), + OBSOLETE("DirRecordUsageRetainIPs"), + OBSOLETE("DirRecordUsageSaveInterval"), + V(DirReqStatistics, BOOL, "0"), VAR("DirServer", LINELIST, DirServers, NULL), + V(DisableAllSwap, BOOL, "0"), V(DNSPort, UINT, "0"), V(DNSListenAddress, LINELIST, NULL), V(DownloadExtraInfo, BOOL, "0"), V(EnforceDistinctSubnets, BOOL, "1"), V(EntryNodes, ROUTERSET, NULL), + V(EntryStatistics, BOOL, "0"), V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"), V(ExcludeNodes, ROUTERSET, NULL), V(ExcludeExitNodes, ROUTERSET, NULL), @@ -205,12 +237,20 @@ static config_var_t _option_vars[] = { V(ExitNodes, ROUTERSET, NULL), V(ExitPolicy, LINELIST, NULL), V(ExitPolicyRejectPrivate, BOOL, "1"), + V(ExitPortStatistics, BOOL, "0"), + V(ExtraInfoStatistics, BOOL, "0"), + +#if defined (WINCE) + V(FallbackNetworkstatusFile, FILENAME, "fallback-consensus"), +#else V(FallbackNetworkstatusFile, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "fallback-consensus"), +#endif V(FascistFirewall, BOOL, "0"), V(FirewallPorts, CSV, ""), V(FastFirstHopPK, BOOL, "1"), V(FetchDirInfoEarly, BOOL, "0"), + V(FetchDirInfoExtraEarly, BOOL, "0"), V(FetchServerDescriptors, BOOL, "1"), V(FetchHidServDescriptors, BOOL, "1"), V(FetchUselessDescriptors, BOOL, "0"), @@ -222,6 +262,8 @@ static config_var_t _option_vars[] = { #endif OBSOLETE("Group"), V(HardwareAccel, BOOL, "0"), + V(AccelName, STRING, NULL), + V(AccelDir, FILENAME, NULL), V(HashedControlPassword, LINELIST, NULL), V(HidServDirectoryV2, BOOL, "1"), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), @@ -233,11 +275,15 @@ static config_var_t _option_vars[] = { VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL), V(HidServAuth, LINELIST, NULL), V(HSAuthoritativeDir, BOOL, "0"), - V(HSAuthorityRecordStats, BOOL, "0"), - V(HttpProxy, STRING, NULL), - V(HttpProxyAuthenticator, STRING, NULL), - V(HttpsProxy, STRING, NULL), - V(HttpsProxyAuthenticator, STRING, NULL), + OBSOLETE("HSAuthorityRecordStats"), + V(HTTPProxy, STRING, NULL), + V(HTTPProxyAuthenticator, STRING, NULL), + V(HTTPSProxy, STRING, NULL), + V(HTTPSProxyAuthenticator, STRING, NULL), + V(Socks4Proxy, STRING, NULL), + V(Socks5Proxy, STRING, NULL), + V(Socks5ProxyUsername, STRING, NULL), + V(Socks5ProxyPassword, STRING, NULL), OBSOLETE("IgnoreVersion"), V(KeepalivePeriod, INTERVAL, "5 minutes"), VAR("Log", LINELIST, Logs, NULL), @@ -254,17 +300,20 @@ static config_var_t _option_vars[] = { V(MyFamily, STRING, NULL), V(NewCircuitPeriod, INTERVAL, "30 seconds"), VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"), - V(NatdListenAddress, LINELIST, NULL), - V(NatdPort, UINT, "0"), + V(NATDListenAddress, LINELIST, NULL), + V(NATDPort, UINT, "0"), V(Nickname, STRING, NULL), - V(NoPublish, BOOL, "0"), + V(WarnUnsafeSocks, BOOL, "1"), + OBSOLETE("NoPublish"), VAR("NodeFamily", LINELIST, NodeFamilies, NULL), - V(NumCpus, UINT, "1"), + V(NumCPUs, UINT, "1"), V(NumEntryGuards, UINT, "3"), V(ORListenAddress, LINELIST, NULL), V(ORPort, UINT, "0"), V(OutboundBindAddress, STRING, NULL), OBSOLETE("PathlenCoinWeight"), + V(PerConnBWBurst, MEMUNIT, "0"), + V(PerConnBWRate, MEMUNIT, "0"), V(PidFile, STRING, NULL), V(TestingTorNetwork, BOOL, "0"), V(PreferTunneledDirConns, BOOL, "1"), @@ -278,6 +327,7 @@ static config_var_t _option_vars[] = { V(RecommendedClientVersions, LINELIST, NULL), V(RecommendedServerVersions, LINELIST, NULL), OBSOLETE("RedirectExit"), + V(RefuseUnknownExits, STRING, "auto"), V(RejectPlaintextPorts, CSV, ""), V(RelayBandwidthBurst, MEMUNIT, "0"), V(RelayBandwidthRate, MEMUNIT, "0"), @@ -287,8 +337,9 @@ static config_var_t _option_vars[] = { V(RephistTrackTime, INTERVAL, "24 hours"), OBSOLETE("RouterFile"), V(RunAsDaemon, BOOL, "0"), - V(RunTesting, BOOL, "0"), - V(SafeLogging, BOOL, "1"), +// V(RunTesting, BOOL, "0"), + OBSOLETE("RunTesting"), // currently unused + V(SafeLogging, STRING, "1"), V(SafeSocks, BOOL, "0"), V(ServerDNSAllowBrokenConfig, BOOL, "1"), V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"), @@ -304,8 +355,7 @@ static config_var_t _option_vars[] = { V(SocksPort, UINT, "9050"), V(SocksTimeout, INTERVAL, "2 minutes"), OBSOLETE("StatusFetchPeriod"), - V(StrictEntryNodes, BOOL, "0"), - V(StrictExitNodes, BOOL, "0"), + V(StrictNodes, BOOL, "0"), OBSOLETE("SysLog"), V(TestSocks, BOOL, "0"), OBSOLETE("TestVia"), @@ -330,6 +380,7 @@ static config_var_t _option_vars[] = { V(V3AuthDistDelay, INTERVAL, "5 minutes"), V(V3AuthNIntervalsValid, UINT, "3"), V(V3AuthUseLegacyKey, BOOL, "0"), + V(V3BandwidthsFile, FILENAME, NULL), VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"), V(VirtualAddrNetwork, STRING, "127.192.0.0/10"), V(WarnPlaintextPorts, CSV, "23,109,110,143"), @@ -340,6 +391,7 @@ static config_var_t _option_vars[] = { VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword, NULL), V(MinUptimeHidServDirectoryV2, INTERVAL, "24 hours"), + { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; @@ -362,6 +414,7 @@ static config_var_t testing_tor_network_defaults[] = { V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"), V(TestingAuthDirTimeToLearnReachability, INTERVAL, "0 minutes"), V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"), + V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; #undef VAR @@ -377,6 +430,9 @@ static config_var_t _state_vars[] = { V(AccountingExpectedUsage, MEMUNIT, NULL), V(AccountingIntervalStart, ISOTIME, NULL), V(AccountingSecondsActive, INTERVAL, NULL), + V(AccountingSecondsToReachSoftLimit,INTERVAL, NULL), + V(AccountingSoftLimitHitAt, ISOTIME, NULL), + V(AccountingBytesAtSoftLimit, MEMUNIT, NULL), VAR("EntryGuard", LINELIST_S, EntryGuards, NULL), VAR("EntryGuardDownSince", LINELIST_S, EntryGuards, NULL), @@ -390,12 +446,23 @@ static config_var_t _state_vars[] = { V(BWHistoryWriteEnds, ISOTIME, NULL), V(BWHistoryWriteInterval, UINT, "900"), V(BWHistoryWriteValues, CSV, ""), + V(BWHistoryDirReadEnds, ISOTIME, NULL), + V(BWHistoryDirReadInterval, UINT, "900"), + V(BWHistoryDirReadValues, CSV, ""), + V(BWHistoryDirWriteEnds, ISOTIME, NULL), + V(BWHistoryDirWriteInterval, UINT, "900"), + V(BWHistoryDirWriteValues, CSV, ""), V(TorVersion, STRING, NULL), V(LastRotatedOnionKey, ISOTIME, NULL), V(LastWritten, ISOTIME, NULL), + V(TotalBuildTimes, UINT, NULL), + V(CircuitBuildAbandonedCount, UINT, "0"), + VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL), + VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL), + { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; @@ -410,213 +477,6 @@ typedef struct config_var_description_t { const char *description; } config_var_description_t; -/** Descriptions of the configuration options, to be displayed by online - * option browsers */ -/* XXXX022 did anybody want this? at all? If not, kill it.*/ -static config_var_description_t options_description[] = { - /* ==== general options */ - { "AvoidDiskWrites", "If non-zero, try to write to disk less frequently than" - " we would otherwise." }, - { "BandwidthRate", "A token bucket limits the average incoming bandwidth on " - "this node to the specified number of bytes per second." }, - { "BandwidthBurst", "Limit the maximum token buffer size (also known as " - "burst) to the given number of bytes." }, - { "ConnLimit", "Minimum number of simultaneous sockets we must have." }, - { "ConstrainedSockets", "Shrink tx and rx buffers for sockets to avoid " - "system limits on vservers and related environments. See man page for " - "more information regarding this option." }, - { "ConstrainedSockSize", "Limit socket buffers to this size when " - "ConstrainedSockets is enabled." }, - /* ControlListenAddress */ - { "ControlPort", "If set, Tor will accept connections from the same machine " - "(localhost only) on this port, and allow those connections to control " - "the Tor process using the Tor Control Protocol (described in " - "control-spec.txt).", }, - { "CookieAuthentication", "If this option is set to 1, don't allow any " - "connections to the control port except when the connecting process " - "can read a file that Tor creates in its data directory." }, - { "DataDirectory", "Store working data, state, keys, and caches here." }, - { "DirServer", "Tor only trusts directories signed with one of these " - "servers' keys. Used to override the standard list of directory " - "authorities." }, - /* { "FastFirstHopPK", "" }, */ - /* FetchServerDescriptors, FetchHidServDescriptors, - * FetchUselessDescriptors */ - { "HardwareAccel", "If set, Tor tries to use hardware crypto accelerators " - "when it can." }, - /* HashedControlPassword */ - { "HTTPProxy", "Force Tor to make all HTTP directory requests through this " - "host:port (or host:80 if port is not set)." }, - { "HTTPProxyAuthenticator", "A username:password pair to be used with " - "HTTPProxy." }, - { "HTTPSProxy", "Force Tor to make all TLS (SSL) connections through this " - "host:port (or host:80 if port is not set)." }, - { "HTTPSProxyAuthenticator", "A username:password pair to be used with " - "HTTPSProxy." }, - { "KeepalivePeriod", "Send a padding cell every N seconds to keep firewalls " - "from closing our connections while Tor is not in use." }, - { "Log", "Where to send logging messages. Format is " - "minSeverity[-maxSeverity] (stderr|stdout|syslog|file FILENAME)." }, - { "OutboundBindAddress", "Make all outbound connections originate from the " - "provided IP address (only useful for multiple network interfaces)." }, - { "PIDFile", "On startup, write our PID to this file. On clean shutdown, " - "remove the file." }, - { "PreferTunneledDirConns", "If non-zero, avoid directory servers that " - "don't support tunneled connections." }, - /* PreferTunneledDirConns */ - /* ProtocolWarnings */ - /* RephistTrackTime */ - { "RunAsDaemon", "If set, Tor forks and daemonizes to the background when " - "started. Unix only." }, - { "SafeLogging", "If set to 0, Tor logs potentially sensitive strings " - "rather than replacing them with the string [scrubbed]." }, - { "TunnelDirConns", "If non-zero, when a directory server we contact " - "supports it, we will build a one-hop circuit and make an encrypted " - "connection via its ORPort." }, - { "User", "On startup, setuid to this user." }, - - /* ==== client options */ - { "AllowInvalidNodes", "Where on our circuits should Tor allow servers " - "that the directory authorities haven't called \"valid\"?" }, - { "AllowNonRFC953Hostnames", "If set to 1, we don't automatically reject " - "hostnames for having invalid characters." }, - /* CircuitBuildTimeout, CircuitIdleTimeout */ - { "ClientOnly", "If set to 1, Tor will under no circumstances run as a " - "server, even if ORPort is enabled." }, - { "EntryNodes", "A list of preferred entry nodes to use for the first hop " - "in circuits, when possible." }, - /* { "EnforceDistinctSubnets" , "" }, */ - { "ExitNodes", "A list of preferred nodes to use for the last hop in " - "circuits, when possible." }, - { "ExcludeNodes", "A list of nodes never to use when building a circuit." }, - { "FascistFirewall", "If set, Tor will only create outgoing connections to " - "servers running on the ports listed in FirewallPorts." }, - { "FirewallPorts", "A list of ports that we can connect to. Only used " - "when FascistFirewall is set." }, - { "LongLivedPorts", "A list of ports for services that tend to require " - "high-uptime connections." }, - { "MapAddress", "Force Tor to treat all requests for one address as if " - "they were for another." }, - { "NewCircuitPeriod", "Force Tor to consider whether to build a new circuit " - "every NUM seconds." }, - { "MaxCircuitDirtiness", "Do not attach new streams to a circuit that has " - "been used more than this many seconds ago." }, - /* NatdPort, NatdListenAddress */ - { "NodeFamily", "A list of servers that constitute a 'family' and should " - "never be used in the same circuit." }, - { "NumEntryGuards", "How many entry guards should we keep at a time?" }, - /* PathlenCoinWeight */ - { "ReachableAddresses", "Addresses we can connect to, as IP/bits:port-port. " - "By default, we assume all addresses are reachable." }, - /* reachablediraddresses, reachableoraddresses. */ - /* SafeSOCKS */ - { "SOCKSPort", "The port where we listen for SOCKS connections from " - "applications." }, - { "SOCKSListenAddress", "Bind to this address to listen to connections from " - "SOCKS-speaking applications." }, - { "SOCKSPolicy", "Set an entry policy to limit which addresses can connect " - "to the SOCKSPort." }, - /* SocksTimeout */ - { "StrictExitNodes", "If set, Tor will fail to operate when none of the " - "configured ExitNodes can be used." }, - { "StrictEntryNodes", "If set, Tor will fail to operate when none of the " - "configured EntryNodes can be used." }, - /* TestSocks */ - { "TrackHostsExit", "Hosts and domains which should, if possible, be " - "accessed from the same exit node each time we connect to them." }, - { "TrackHostsExitExpire", "Time after which we forget which exit we were " - "using to connect to hosts in TrackHostsExit." }, - /* "TransPort", "TransListenAddress */ - { "UseEntryGuards", "Set to 0 if we want to pick from the whole set of " - "servers for the first position in each circuit, rather than picking a " - "set of 'Guards' to prevent profiling attacks." }, - - /* === server options */ - { "Address", "The advertised (external) address we should use." }, - /* Accounting* options. */ - /* AssumeReachable */ - { "ContactInfo", "Administrative contact information to advertise for this " - "server." }, - { "ExitPolicy", "Address/port ranges for which to accept or reject outgoing " - "connections on behalf of Tor users." }, - /* { "ExitPolicyRejectPrivate, "" }, */ - { "MaxAdvertisedBandwidth", "If set, we will not advertise more than this " - "amount of bandwidth for our bandwidth rate, regardless of how much " - "bandwidth we actually detect." }, - { "MaxOnionsPending", "Reject new attempts to extend circuits when we " - "already have this many pending." }, - { "MyFamily", "Declare a list of other servers as belonging to the same " - "family as this one, so that clients will not use two from the same " - "family in the same circuit." }, - { "Nickname", "Set the server nickname." }, - { "NoPublish", "{DEPRECATED}" }, - { "NumCPUs", "How many processes to use at once for public-key crypto." }, - { "ORPort", "Advertise this port to listen for connections from Tor clients " - "and servers." }, - { "ORListenAddress", "Bind to this address to listen for connections from " - "clients and servers, instead of the default 0.0.0.0:ORPort." }, - { "PublishServerDescriptor", "Set to 0 to keep the server from " - "uploading info to the directory authorities." }, - /* ServerDNS: DetectHijacking, ResolvConfFile, SearchDomains */ - { "ShutdownWaitLength", "Wait this long for clients to finish when " - "shutting down because of a SIGINT." }, - - /* === directory cache options */ - { "DirPort", "Serve directory information from this port, and act as a " - "directory cache." }, - { "DirPortFrontPage", "Serve a static html disclaimer on DirPort." }, - { "DirListenAddress", "Bind to this address to listen for connections from " - "clients and servers, instead of the default 0.0.0.0:DirPort." }, - { "DirPolicy", "Set a policy to limit who can connect to the directory " - "port." }, - - /* Authority options: AuthDirBadExit, AuthDirInvalid, AuthDirReject, - * AuthDirRejectUnlisted, AuthDirListBadExits, AuthoritativeDirectory, - * DirAllowPrivateAddresses, HSAuthoritativeDir, - * NamingAuthoritativeDirectory, RecommendedVersions, - * RecommendedClientVersions, RecommendedServerVersions, RendPostPeriod, - * RunTesting, V1AuthoritativeDirectory, VersioningAuthoritativeDirectory, */ - - /* Hidden service options: HiddenService: dir,excludenodes, nodes, - * options, port. PublishHidServDescriptor */ - - /* Nonpersistent options: __LeaveStreamsUnattached, __AllDirActionsPrivate */ - { NULL, NULL }, -}; - -/** Online description of state variables. */ -static config_var_description_t state_description[] = { - { "AccountingBytesReadInInterval", - "How many bytes have we read in this accounting period?" }, - { "AccountingBytesWrittenInInterval", - "How many bytes have we written in this accounting period?" }, - { "AccountingExpectedUsage", - "How many bytes did we expect to use per minute? (0 for no estimate.)" }, - { "AccountingIntervalStart", "When did this accounting period begin?" }, - { "AccountingSecondsActive", "How long have we been awake in this period?" }, - - { "BWHistoryReadEnds", "When does the last-recorded read-interval end?" }, - { "BWHistoryReadInterval", "How long is each read-interval (in seconds)?" }, - { "BWHistoryReadValues", "Number of bytes read in each interval." }, - { "BWHistoryWriteEnds", "When does the last-recorded write-interval end?" }, - { "BWHistoryWriteInterval", "How long is each write-interval (in seconds)?"}, - { "BWHistoryWriteValues", "Number of bytes written in each interval." }, - - { "EntryGuard", "One of the nodes we have chosen as a fixed entry" }, - { "EntryGuardDownSince", - "The last entry guard has been unreachable since this time." }, - { "EntryGuardUnlistedSince", - "The last entry guard has been unusable since this time." }, - - { "LastRotatedOnionKey", - "The last time at which we changed the medium-term private key used for " - "building circuits." }, - { "LastWritten", "When was this state file last regenerated?" }, - - { "TorVersion", "Which version of Tor generated this state file?" }, - { NULL, NULL }, -}; - /** Type of a callback to validate whether a given configuration is * well-formed and consistent. See options_trial_assign() for documentation * of arguments. */ @@ -635,8 +495,6 @@ typedef struct { config_var_t *vars; /**< List of variables we recognize, their default * values, and where we stick them in the structure. */ validate_fn_t validate_fn; /**< Function to validate config. */ - /** Documentation for configuration variables. */ - config_var_description_t *descriptions; /** If present, extra is a LINELIST variable for unrecognized * lines. Otherwise, unrecognized lines are an error. */ config_var_t *extra; @@ -700,20 +558,6 @@ static uint64_t config_parse_memunit(const char *s, int *ok); static int config_parse_interval(const char *s, int *ok); static void init_libevent(void); static int opt_streq(const char *s1, const char *s2); -/** Versions of libevent. */ -typedef enum { - /* Note: we compare these, so it's important that "old" precede everything, - * and that "other" come last. */ - LE_OLD=0, LE_10C, LE_10D, LE_10E, LE_11, LE_11A, LE_11B, LE_12, LE_12A, - LE_13, LE_13A, LE_13B, LE_13C, LE_13D, LE_13E, - LE_140, LE_141, LE_142, LE_143, LE_144, LE_145, LE_146, LE_147, LE_148, - LE_1499, - LE_OTHER -} le_version_t; -static le_version_t decode_libevent_version(const char *v, int *bincompat_out); -#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD) -static void check_libevent_version(const char *m, int server); -#endif /** Magic value for or_options_t. */ #define OR_OPTIONS_MAGIC 9090909 @@ -726,7 +570,6 @@ static config_format_t options_format = { _option_abbrevs, _option_vars, (validate_fn_t)options_validate, - options_description, NULL }; @@ -747,7 +590,6 @@ static config_format_t state_format = { _state_abbrevs, _state_vars, (validate_fn_t)or_state_validate, - state_description, &state_extra_var, }; @@ -812,13 +654,13 @@ set_options(or_options_t *new_val, char **msg) "Acting on config options left us in a broken state. Dying."); exit(1); } - if (old_options) - config_free(&options_format, old_options); + + config_free(&options_format, old_options); return 0; } -extern const char tor_svn_revision[]; /* from tor_main.c */ +extern const char tor_git_revision[]; /* from tor_main.c */ /** The version of this Tor process, as parsed. */ static char *_version = NULL; @@ -828,10 +670,10 @@ const char * get_version(void) { if (_version == NULL) { - if (strlen(tor_svn_revision)) { - size_t len = strlen(VERSION)+strlen(tor_svn_revision)+8; + if (strlen(tor_git_revision)) { + size_t len = strlen(VERSION)+strlen(tor_git_revision)+16; _version = tor_malloc(len); - tor_snprintf(_version, len, "%s (r%s)", VERSION, tor_svn_revision); + tor_snprintf(_version, len, "%s (git-%s)", VERSION, tor_git_revision); } else { _version = tor_strdup(VERSION); } @@ -844,8 +686,10 @@ get_version(void) static void or_options_free(or_options_t *options) { - if (options->_ExcludeExitNodesUnion) - routerset_free(options->_ExcludeExitNodesUnion); + if (!options) + return; + + routerset_free(options->_ExcludeExitNodesUnion); config_free(&options_format, options); } @@ -854,43 +698,72 @@ or_options_free(or_options_t *options) void config_free_all(void) { - if (global_options) { - or_options_free(global_options); - global_options = NULL; - } - if (global_state) { - config_free(&state_format, global_state); - global_state = NULL; - } - if (global_cmdline_options) { - config_free_lines(global_cmdline_options); - global_cmdline_options = NULL; - } + or_options_free(global_options); + global_options = NULL; + + config_free(&state_format, global_state); + global_state = NULL; + + config_free_lines(global_cmdline_options); + global_cmdline_options = NULL; + tor_free(torrc_fname); tor_free(_version); tor_free(global_dirfrontpagecontents); } -/** If options->SafeLogging is on, return a not very useful string, - * else return address. +/** Make <b>address</b> -- a piece of information related to our operation as + * a client -- safe to log according to the settings in options->SafeLogging, + * and return it. + * + * (We return "[scrubbed]" if SafeLogging is "1", and address otherwise.) + */ +const char * +safe_str_client(const char *address) +{ + tor_assert(address); + if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL) + return "[scrubbed]"; + else + return address; +} + +/** Make <b>address</b> -- a piece of information of unspecified sensitivity + * -- safe to log according to the settings in options->SafeLogging, and + * return it. + * + * (We return "[scrubbed]" if SafeLogging is anything besides "0", and address + * otherwise.) */ const char * safe_str(const char *address) { tor_assert(address); - if (get_options()->SafeLogging) + if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE) return "[scrubbed]"; else return address; } +/** Equivalent to escaped(safe_str_client(address)). See reentrancy note on + * escaped(): don't use this outside the main thread, or twice in the same + * log statement. */ +const char * +escaped_safe_str_client(const char *address) +{ + if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL) + return "[scrubbed]"; + else + return escaped(address); +} + /** Equivalent to escaped(safe_str(address)). See reentrancy note on * escaped(): don't use this outside the main thread, or twice in the same * log statement. */ const char * escaped_safe_str(const char *address) { - if (get_options()->SafeLogging) + if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE) return "[scrubbed]"; else return escaped(address); @@ -1089,10 +962,12 @@ options_act_reversible(or_options_t *old_options, char **msg) } /* Launch the listeners. (We do this before we setuid, so we can bind to - * ports under 1024.) */ - if (retry_all_listeners(replaced_listeners, new_listeners) < 0) { - *msg = tor_strdup("Failed to bind one of the listener ports."); - goto rollback; + * ports under 1024.) We don't want to rebind if we're hibernating. */ + 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; + } } } @@ -1106,6 +981,15 @@ options_act_reversible(or_options_t *old_options, char **msg) } #endif + /* Attempt to lock all current and future memory with mlockall() only once */ + if (options->DisableAllSwap) { + if (tor_mlockall() == -1) { + *msg = tor_strdup("DisableAllSwap failure. Do you have proper " + "permissions?"); + goto done; + } + } + /* Setuid/setgid as appropriate */ if (options->User) { if (switch_id(options->User) != 0) { @@ -1118,11 +1002,9 @@ options_act_reversible(or_options_t *old_options, char **msg) /* Ensure data directory is private; create if possible. */ if (check_private_dir(options->DataDirectory, running_tor ? CPD_CREATE : CPD_CHECK)<0) { - char buf[1024]; - int tmp = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Couldn't access/create private data directory \"%s\"", options->DataDirectory); - *msg = tor_strdup(tmp >= 0 ? buf : "internal error"); goto done; /* No need to roll back, since you can't change the value. */ } @@ -1133,10 +1015,8 @@ options_act_reversible(or_options_t *old_options, char **msg) tor_snprintf(fn, len, "%s"PATH_SEPARATOR"cached-status", options->DataDirectory); if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK) < 0) { - char buf[1024]; - int tmp = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Couldn't access/create private data directory \"%s\"", fn); - *msg = tor_strdup(tmp >= 0 ? buf : "internal error"); tor_free(fn); goto done; } @@ -1236,7 +1116,6 @@ get_effective_bwrate(or_options_t *options) bw = options->MaxAdvertisedBandwidth; if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate) bw = options->RelayBandwidthRate; - /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */ return (uint32_t)bw; } @@ -1314,14 +1193,14 @@ options_act(or_options_t *old_options) return 0; /* Finish backgrounding the process */ - if (running_tor && options->RunAsDaemon) { + if (options->RunAsDaemon) { /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */ finish_daemon(options->DataDirectory); } /* Write our PID to the PID file. If we do not have write permissions we * will log a warning */ - if (running_tor && options->PidFile) + if (options->PidFile) write_pidfile(options->PidFile); /* Register addressmap directives */ @@ -1354,18 +1233,66 @@ 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; + } + + /* Change the cell EWMA settings */ + cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus()); + /* Check for transitions that need action. */ if (old_options) { - if (options->UseEntryGuards && !old_options->UseEntryGuards) { + + if ((options->UseEntryGuards && !old_options->UseEntryGuards) || + (options->ExcludeNodes && + !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes)) || + (options->ExcludeExitNodes && + !routerset_equal(old_options->ExcludeExitNodes, + options->ExcludeExitNodes)) || + (options->EntryNodes && + !routerset_equal(old_options->EntryNodes, options->EntryNodes)) || + (options->ExitNodes && + !routerset_equal(old_options->ExitNodes, options->ExitNodes)) || + options->StrictNodes != old_options->StrictNodes) { log_info(LD_CIRC, - "Switching to entry guards; abandoning previous circuits"); + "Changed to using entry guards, or changed preferred or " + "excluded node lists. Abandoning previous circuits."); circuit_mark_all_unused_circs(); circuit_expire_all_dirty_circs(); } +/* How long should we delay counting bridge stats after becoming a bridge? + * We use this so we don't count people who used our bridge thinking it is + * a relay. If you change this, don't forget to change the log message + * below. It's 4 hours (the time it takes to stop being used by clients) + * plus some extra time for clock skew. */ +#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60) + if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) { - log_info(LD_GENERAL, "Bridge status changed. Forgetting GeoIP stats."); - geoip_remove_old_clients(time(NULL)+(2*60*60)); + int was_relay = 0; + if (options->BridgeRelay) { + time_t int_start = time(NULL); + if (old_options->ORPort == options->ORPort) { + int_start += RELAY_BRIDGE_STATS_DELAY; + was_relay = 1; + } + geoip_bridge_stats_init(int_start); + log_info(LD_CONFIG, "We are acting as a bridge now. Starting new " + "GeoIP stats interval%s.", was_relay ? " in 6 " + "hours from now" : ""); + } else { + geoip_bridge_stats_term(); + log_info(LD_GENERAL, "We are no longer acting as a bridge. " + "Forgetting GeoIP stats."); + } } if (options_transition_affects_workers(old_options, options)) { @@ -1377,7 +1304,7 @@ options_act(or_options_t *old_options) return -1; } ip_address_changed(0); - if (has_completed_circuit || !any_predicted_circuits(time(NULL))) + if (can_complete_circuit || !any_predicted_circuits(time(NULL))) inform_testing_reachability(); } cpuworkers_rotate(); @@ -1390,6 +1317,10 @@ options_act(or_options_t *old_options) if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir) init_keys(); + + if (options->PerConnBWRate != old_options->PerConnBWRate || + options->PerConnBWBurst != old_options->PerConnBWBurst) + connection_or_update_token_buckets(get_connection_array(), options); } /* Maybe load geoip file */ @@ -1412,13 +1343,63 @@ options_act(or_options_t *old_options) geoip_load_file(actual_fname, options); tor_free(actual_fname); } -#ifdef ENABLE_GEOIP_STATS - log_warn(LD_CONFIG, "We are configured to measure GeoIP statistics, but " - "the way these statistics are measured has changed " - "significantly in later versions of Tor. The results may not be " - "as expected if you are used to later versions. Be sure you " - "know what you are doing."); -#endif + + 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) { + time_t now = time(NULL); + if ((!old_options || !old_options->CellStatistics) && + options->CellStatistics) + rep_hist_buffer_stats_init(now); + if ((!old_options || !old_options->DirReqStatistics) && + options->DirReqStatistics) + geoip_dirreq_stats_init(now); + if ((!old_options || !old_options->EntryStatistics) && + options->EntryStatistics) + geoip_entry_stats_init(now); + if ((!old_options || !old_options->ExitPortStatistics) && + options->ExitPortStatistics) + rep_hist_exit_stats_init(now); + if (!old_options) + 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."); + } + + if (old_options && old_options->CellStatistics && + !options->CellStatistics) + rep_hist_buffer_stats_term(); + if (old_options && old_options->DirReqStatistics && + !options->DirReqStatistics) + geoip_dirreq_stats_term(); + if (old_options && old_options->EntryStatistics && + !options->EntryStatistics) + geoip_entry_stats_term(); + if (old_options && old_options->ExitPortStatistics && + !options->ExitPortStatistics) + rep_hist_exit_stats_term(); + /* Check if we need to parse and add the EntryNodes config option. */ if (options->EntryNodes && (!old_options || @@ -1491,7 +1472,10 @@ expand_abbrev(config_format_t *fmt, const char *option, int command_line, fmt->abbrevs[i].abbreviated, fmt->abbrevs[i].full); } - return fmt->abbrevs[i].full; + /* Keep going through the list in case we want to rewrite it more. + * (We could imagine recursing here, but I don't want to get the + * user into an infinite loop if we craft our list wrong.) */ + option = fmt->abbrevs[i].full; } } return option; @@ -1536,7 +1520,10 @@ config_get_commandlines(int argc, char **argv, config_line_t **result) *new = tor_malloc_zero(sizeof(config_line_t)); s = argv[i]; - while (*s == '-') + /* Each keyword may be prefixed with one or two dashes. */ + if (*s == '-') + s++; + if (*s == '-') s++; (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1)); @@ -1628,19 +1615,6 @@ config_free_lines(config_line_t *front) } } -/** Return the description for a given configuration variable, or NULL if no - * description exists. */ -static const char * -config_find_description(config_format_t *fmt, const char *name) -{ - int i; - for (i=0; fmt->descriptions[i].name; ++i) { - if (!strcasecmp(name, fmt->descriptions[i].name)) - return fmt->descriptions[i].description; - } - return NULL; -} - /** 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. @@ -1671,6 +1645,16 @@ config_find_option(config_format_t *fmt, const char *key) return NULL; } +/** Return the number of option entries in <b>fmt</b>. */ +static int +config_count_options(config_format_t *fmt) +{ + int i; + for (i=0; fmt->vars[i].name; ++i) + ; + return i; +} + /* * Functions to assign config options. */ @@ -1684,8 +1668,7 @@ static int config_assign_value(config_format_t *fmt, or_options_t *options, config_line_t *c, char **msg) { - int i, r, ok; - char buf[1024]; + int i, ok; config_var_t *var; void *lvalue; @@ -1701,10 +1684,9 @@ config_assign_value(config_format_t *fmt, or_options_t *options, case CONFIG_TYPE_UINT: i = (int)tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL); if (!ok) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Int keyword '%s %s' is malformed or out of bounds.", c->key, c->value); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } *(int *)lvalue = i; @@ -1713,10 +1695,9 @@ config_assign_value(config_format_t *fmt, or_options_t *options, case CONFIG_TYPE_INTERVAL: { i = config_parse_interval(c->value, &ok); if (!ok) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Interval '%s %s' is malformed or out of bounds.", c->key, c->value); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } *(int *)lvalue = i; @@ -1726,10 +1707,9 @@ config_assign_value(config_format_t *fmt, or_options_t *options, case CONFIG_TYPE_MEMUNIT: { uint64_t u64 = config_parse_memunit(c->value, &ok); if (!ok) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Value '%s %s' is malformed or out of bounds.", c->key, c->value); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } *(uint64_t *)lvalue = u64; @@ -1739,10 +1719,9 @@ config_assign_value(config_format_t *fmt, or_options_t *options, case CONFIG_TYPE_BOOL: i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL); if (!ok) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Boolean '%s %s' expects 0 or 1.", c->key, c->value); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } *(int *)lvalue = i; @@ -1760,9 +1739,8 @@ config_assign_value(config_format_t *fmt, or_options_t *options, case CONFIG_TYPE_ISOTIME: if (parse_iso_time(c->value, (time_t *)lvalue)) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Invalid time '%s' for keyword '%s'", c->value, c->key); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } break; @@ -1773,9 +1751,8 @@ config_assign_value(config_format_t *fmt, or_options_t *options, } *(routerset_t**)lvalue = routerset_new(); if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) { - tor_snprintf(buf, sizeof(buf), "Invalid exit list '%s' for option '%s'", + tor_asprintf(msg, "Invalid exit list '%s' for option '%s'", c->value, c->key); - *msg = tor_strdup(buf); return -1; } break; @@ -1800,9 +1777,8 @@ config_assign_value(config_format_t *fmt, or_options_t *options, log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key); break; case CONFIG_TYPE_LINELIST_V: - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "You may not provide a value for virtual option '%s'", c->key); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; default: tor_assert(0); @@ -1823,7 +1799,7 @@ config_assign_value(config_format_t *fmt, or_options_t *options, static int config_assign_line(config_format_t *fmt, or_options_t *options, config_line_t *c, int use_defaults, - int clear_first, char **msg) + int clear_first, bitarray_t *options_seen, char **msg) { config_var_t *var; @@ -1838,13 +1814,12 @@ config_assign_line(config_format_t *fmt, or_options_t *options, config_line_append((config_line_t**)lvalue, c->key, c->value); return 0; } else { - char buf[1024]; - int tmp = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Unknown option '%s'. Failing.", c->key); - *msg = tor_strdup(tmp >= 0 ? buf : "internal error"); return -1; } } + /* Put keyword into canonical case. */ if (strcmp(var->name, c->key)) { tor_free(c->key); @@ -1867,6 +1842,18 @@ config_assign_line(config_format_t *fmt, or_options_t *options, return 0; } + if (options_seen && (var->type != CONFIG_TYPE_LINELIST && + var->type != CONFIG_TYPE_LINELIST_S)) { + /* We're tracking which options we've seen, and this option is not + * supposed to occur more than once. */ + int var_index = (int)(var - fmt->vars); + if (bitarray_is_set(options_seen, var_index)) { + log_warn(LD_CONFIG, "Option '%s' used more than once; all but the last " + "value will be ignored.", var->name); + } + bitarray_set(options_seen, var_index); + } + if (config_assign_value(fmt, options, c, msg) < 0) return -2; return 0; @@ -1967,7 +1954,6 @@ get_assigned_option(config_format_t *fmt, void *options, { config_var_t *var; const void *value; - char buf[32]; config_line_t *result; tor_assert(options && key); @@ -2008,19 +1994,16 @@ get_assigned_option(config_format_t *fmt, void *options, 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. */ - tor_snprintf(buf, sizeof(buf), "%d", *(int*)value); - result->value = tor_strdup(buf); + tor_asprintf(&result->value, "%d", *(int*)value); escape_val = 0; /* Can't need escape. */ break; case CONFIG_TYPE_MEMUNIT: - tor_snprintf(buf, sizeof(buf), U64_FORMAT, + tor_asprintf(&result->value, U64_FORMAT, U64_PRINTF_ARG(*(uint64_t*)value)); - result->value = tor_strdup(buf); escape_val = 0; /* Can't need escape. */ break; case CONFIG_TYPE_DOUBLE: - tor_snprintf(buf, sizeof(buf), "%f", *(double*)value); - result->value = tor_strdup(buf); + tor_asprintf(&result->value, "%f", *(double*)value); escape_val = 0; /* Can't need escape. */ break; case CONFIG_TYPE_BOOL: @@ -2139,6 +2122,8 @@ config_assign(config_format_t *fmt, void *options, config_line_t *list, int use_defaults, int clear_first, char **msg) { config_line_t *p; + bitarray_t *options_seen; + const int n_options = config_count_options(fmt); CHECK(fmt, options); @@ -2158,14 +2143,18 @@ config_assign(config_format_t *fmt, void *options, config_line_t *list, config_reset_line(fmt, options, p->key, use_defaults); } + options_seen = bitarray_init_zero(n_options); /* pass 3: assign. */ while (list) { int r; if ((r=config_assign_line(fmt, options, list, use_defaults, - clear_first, msg))) + clear_first, options_seen, msg))) { + bitarray_free(options_seen); return r; + } list = list->next; } + bitarray_free(options_seen); return 0; } @@ -2308,20 +2297,10 @@ list_torrc_options(void) smartlist_t *lines = smartlist_create(); for (i = 0; _option_vars[i].name; ++i) { config_var_t *var = &_option_vars[i]; - const char *desc; if (var->type == CONFIG_TYPE_OBSOLETE || var->type == CONFIG_TYPE_LINELIST_V) continue; - desc = config_find_description(&options_format, var->name); printf("%s\n", var->name); - if (desc) { - wrap_string(lines, desc, 76, " ", " "); - SMARTLIST_FOREACH(lines, char *, cp, { - printf("%s", cp); - tor_free(cp); - }); - smartlist_clear(lines); - } } smartlist_free(lines); } @@ -2340,7 +2319,7 @@ resolve_my_address(int warn_severity, or_options_t *options, uint32_t *addr_out, char **hostname_out) { struct in_addr in; - uint32_t addr; + uint32_t addr; /* host order */ char hostname[256]; int explicit_ip=1; int explicit_hostname=1; @@ -2370,8 +2349,8 @@ resolve_my_address(int warn_severity, or_options_t *options, if (tor_inet_aton(hostname, &in) == 0) { /* then we have to resolve it */ explicit_ip = 0; - if (tor_lookup_hostname(hostname, &addr)) { - uint32_t interface_ip; + if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */ + uint32_t interface_ip; /* host order */ if (explicit_hostname) { log_fn(warn_severity, LD_CONFIG, @@ -2392,7 +2371,7 @@ resolve_my_address(int warn_severity, or_options_t *options, log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for " "local interface. Using that.", tmpbuf); strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); - } else { + } else { /* resolved hostname into addr */ in.s_addr = htonl(addr); if (!explicit_hostname && @@ -2566,7 +2545,10 @@ config_free(config_format_t *fmt, void *options) { int i; - tor_assert(options); + if (!options) + return; + + tor_assert(fmt); for (i=0; fmt->vars[i].name; ++i) option_clear(fmt, options, &(fmt->vars[i])); @@ -2668,6 +2650,8 @@ is_listening_on_low_port(uint16_t port_option, const config_line_t *listen_options) { #ifdef MS_WINDOWS + (void) port_option; + (void) listen_options; return 0; /* No port is too low for windows. */ #else const config_line_t *l; @@ -2717,7 +2701,6 @@ config_dump(config_format_t *fmt, void *options, int minimal, config_line_t *line, *assigned; char *result; int i; - const char *desc; char *msg = NULL; defaults = config_alloc(fmt); @@ -2745,24 +2728,13 @@ config_dump(config_format_t *fmt, void *options, int minimal, option_is_same(fmt, options, defaults, fmt->vars[i].name)) comment_option = 1; - desc = config_find_description(fmt, fmt->vars[i].name); line = assigned = get_assigned_option(fmt, options, fmt->vars[i].name, 1); - if (line && desc) { - /* Only dump the description if there's something to describe. */ - wrap_string(elements, desc, 78, "# ", "# "); - } - for (; line; line = line->next) { - size_t len = strlen(line->key) + strlen(line->value) + 5; char *tmp; - tmp = tor_malloc(len); - if (tor_snprintf(tmp, len, "%s%s %s\n", - comment_option ? "# " : "", - line->key, line->value)<0) { - log_err(LD_BUG,"Internal error writing option value"); - tor_assert(0); - } + tor_asprintf(&tmp, "%s%s %s\n", + comment_option ? "# " : "", + line->key, line->value); smartlist_add(elements, tmp); } config_free_lines(assigned); @@ -2771,13 +2743,8 @@ config_dump(config_format_t *fmt, void *options, int minimal, if (fmt->extra) { line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset); for (; line; line = line->next) { - size_t len = strlen(line->key) + strlen(line->value) + 3; char *tmp; - tmp = tor_malloc(len); - if (tor_snprintf(tmp, len, "%s %s\n", line->key, line->value)<0) { - log_err(LD_BUG,"Internal error writing option value"); - tor_assert(0); - } + tor_asprintf(&tmp, "%s %s\n", line->key, line->value); smartlist_add(elements, tmp); } } @@ -2793,7 +2760,7 @@ config_dump(config_format_t *fmt, void *options, int minimal, * the configuration in <b>options</b>. If <b>minimal</b> is true, do not * include options that are the same as Tor's defaults. */ -static char * +char * options_dump(or_options_t *options, int minimal) { return config_dump(&options_format, options, minimal, 0); @@ -2806,7 +2773,6 @@ static int validate_ports_csv(smartlist_t *sl, const char *name, char **msg) { int i; - char buf[1024]; tor_assert(name); if (!sl) @@ -2816,9 +2782,7 @@ validate_ports_csv(smartlist_t *sl, const char *name, char **msg) { i = atoi(cp); if (i < 1 || i > 65535) { - int r = tor_snprintf(buf, sizeof(buf), - "Port '%s' out of range in %s", cp, name); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); + tor_asprintf(msg, "Port '%s' out of range in %s", cp, name); return -1; } }); @@ -2832,18 +2796,15 @@ validate_ports_csv(smartlist_t *sl, const char *name, char **msg) static int ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) { - int r; - char buf[1024]; if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) { /* This handles an understandable special case where somebody says "2gb" * whereas our actual maximum is 2gb-1 (INT_MAX) */ --*value; } if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) { - r = tor_snprintf(buf, sizeof(buf), "%s ("U64_FORMAT") must be at most %d", - desc, U64_PRINTF_ARG(*value), - ROUTER_MAX_DECLARED_BANDWIDTH); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); + tor_asprintf(msg, "%s ("U64_FORMAT") must be at most %d", + desc, U64_PRINTF_ARG(*value), + ROUTER_MAX_DECLARED_BANDWIDTH); return -1; } return 0; @@ -2894,15 +2855,14 @@ compute_publishserverdescriptor(or_options_t *options) /** Highest allowable value for RendPostPeriod. */ #define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2) -/** Lowest allowable value for CircuitBuildTimeout; values too low will - * increase network load because of failing connections being retried, and - * might prevent users from connecting to the network at all. */ -#define MIN_CIRCUIT_BUILD_TIMEOUT 30 - /** Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor * will generate too many circuits and potentially overload the network. */ #define MIN_MAX_CIRCUIT_DIRTINESS 10 +/** Lowest allowable value for CircuitStreamTimeout; if this is too low, Tor + * will generate too many circuits and potentially overload the network. */ +#define MIN_CIRCUIT_STREAM_TIMEOUT 10 + /** 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 @@ -2919,10 +2879,9 @@ static int options_validate(or_options_t *old_options, or_options_t *options, int from_setconf, char **msg) { - int i, r; + int i; config_line_t *cl; const char *uname = get_uname(); - char buf[1024]; #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END #define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END @@ -2939,7 +2898,7 @@ options_validate(or_options_t *old_options, or_options_t *options, !strcmpstart(uname, "Windows Me"))) { log(LOG_WARN, LD_CONFIG, "Tor is running as a server, but you are " "running %s; this probably won't work. See " - "http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#ServerOS " + "https://wiki.torproject.org/TheOnionRouter/TorFAQ#ServerOS " "for details.", uname); } @@ -2958,8 +2917,8 @@ options_validate(or_options_t *old_options, or_options_t *options, 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."); + 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. */ @@ -2978,8 +2937,8 @@ options_validate(or_options_t *old_options, or_options_t *options, old = old_options ? old_options->TransListenAddress : NULL; tp = "transparent proxy"; } else { - opt = options->NatdListenAddress; - old = old_options ? old_options->NatdListenAddress : NULL; + opt = options->NATDListenAddress; + old = old_options ? old_options->NATDListenAddress : NULL; tp = "natd proxy"; } @@ -3017,10 +2976,9 @@ options_validate(or_options_t *old_options, or_options_t *options, } } else { if (!is_legal_nickname(options->Nickname)) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Nickname '%s' is wrong length or contains illegal characters.", options->Nickname); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } } @@ -3037,14 +2995,6 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options_init_logs(options, 1)<0) /* Validate the log(s) */ REJECT("Failed to validate Log options. See logs for details."); - if (options->NoPublish) { - log(LOG_WARN, LD_CONFIG, - "NoPublish is obsolete. Use PublishServerDescriptor instead."); - SMARTLIST_FOREACH(options->PublishServerDescriptor, char *, s, - tor_free(s)); - smartlist_clear(options->PublishServerDescriptor); - } - if (authdir_mode(options)) { /* confirm that our address isn't broken, so we can complain now */ uint32_t tmp; @@ -3052,6 +3002,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."); @@ -3066,14 +3022,14 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->TransPort < 0 || options->TransPort > 65535) REJECT("TransPort option out of bounds."); - if (options->NatdPort < 0 || options->NatdPort > 65535) - REJECT("NatdPort option out of bounds."); + if (options->NATDPort < 0 || options->NATDPort > 65535) + REJECT("NATDPort option out of bounds."); if (options->SocksPort == 0 && options->TransPort == 0 && - options->NatdPort == 0 && options->ORPort == 0 && + options->NATDPort == 0 && options->ORPort == 0 && options->DNSPort == 0 && !options->RendConfigLines) log(LOG_WARN, LD_CONFIG, - "SocksPort, TransPort, NatdPort, DNSPort, and ORPort are all " + "SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all " "undefined, and there aren't any hidden services configured. " "Tor will still run, but probably won't do anything."); @@ -3107,19 +3063,11 @@ options_validate(or_options_t *old_options, or_options_t *options, routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes); } - if (options->StrictExitNodes && - (!options->ExitNodes) && - (!old_options || - (old_options->StrictExitNodes != options->StrictExitNodes) || - (!routerset_equal(old_options->ExitNodes,options->ExitNodes)))) - COMPLAIN("StrictExitNodes set, but no ExitNodes listed."); - - if (options->StrictEntryNodes && - (!options->EntryNodes) && - (!old_options || - (old_options->StrictEntryNodes != options->StrictEntryNodes) || - (!routerset_equal(old_options->EntryNodes,options->EntryNodes)))) - COMPLAIN("StrictEntryNodes set, but no EntryNodes listed."); + 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(). */ @@ -3157,6 +3105,10 @@ options_validate(or_options_t *old_options, or_options_t *options, options->V3AuthoritativeDir)) REJECT("AuthoritativeDir is set, but none of " "(Bridge/HS/V1/V2/V3)AuthoritativeDir is set."); + /* If we have a v3bandwidthsfile and it's broken, complain on startup */ + if (options->V3BandwidthsFile && !old_options) { + dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL); + } } if (options->AuthoritativeDir && !options->DirPort) @@ -3168,15 +3120,14 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->AuthoritativeDir && options->ClientOnly) REJECT("Running as authoritative directory, but ClientOnly also set."); - if (options->HSAuthorityRecordStats && !options->HSAuthoritativeDir) - REJECT("HSAuthorityRecordStats is set but we're not running as " - "a hidden service authority."); + if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly) + REJECT("FetchDirInfoExtraEarly requires that you also set " + "FetchDirInfoEarly"); if (options->ConnLimit <= 0) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "ConnLimit must be greater than 0, but was set to %d", options->ConnLimit); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } @@ -3295,18 +3246,29 @@ options_validate(or_options_t *old_options, or_options_t *options, else if (!strcasecmp(cp, "rendezvous")) options->_AllowInvalid |= ALLOW_INVALID_RENDEZVOUS; else { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "Unrecognized value '%s' in AllowInvalidNodes", cp); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } }); } + if (!options->SafeLogging || + !strcasecmp(options->SafeLogging, "0")) { + options->_SafeLogging = SAFELOG_SCRUB_NONE; + } else if (!strcasecmp(options->SafeLogging, "relay")) { + options->_SafeLogging = SAFELOG_SCRUB_RELAY; + } else if (!strcasecmp(options->SafeLogging, "1")) { + options->_SafeLogging = SAFELOG_SCRUB_ALL; + } else { + tor_asprintf(msg, + "Unrecognized value '%s' in SafeLogging", + escaped(options->SafeLogging)); + return -1; + } + if (compute_publishserverdescriptor(options) < 0) { - r = tor_snprintf(buf, sizeof(buf), - "Unrecognized value in PublishServerDescriptor"); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); + tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor"); return -1; } @@ -3326,29 +3288,30 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->RendPostPeriod < MIN_REND_POST_PERIOD) { - log(LOG_WARN,LD_CONFIG,"RendPostPeriod option is too short; " - "raising to %d seconds.", MIN_REND_POST_PERIOD); + log_warn(LD_CONFIG, "RendPostPeriod option is too short; " + "raising to %d seconds.", MIN_REND_POST_PERIOD); options->RendPostPeriod = MIN_REND_POST_PERIOD; } if (options->RendPostPeriod > MAX_DIR_PERIOD) { - log(LOG_WARN, LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.", - MAX_DIR_PERIOD); + log_warn(LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.", + MAX_DIR_PERIOD); options->RendPostPeriod = MAX_DIR_PERIOD; } - if (options->CircuitBuildTimeout < MIN_CIRCUIT_BUILD_TIMEOUT) { - log(LOG_WARN, LD_CONFIG, "CircuitBuildTimeout option is too short; " - "raising to %d seconds.", MIN_CIRCUIT_BUILD_TIMEOUT); - options->CircuitBuildTimeout = MIN_CIRCUIT_BUILD_TIMEOUT; - } - if (options->MaxCircuitDirtiness < MIN_MAX_CIRCUIT_DIRTINESS) { - log(LOG_WARN, LD_CONFIG, "MaxCircuitDirtiness option is too short; " - "raising to %d seconds.", MIN_MAX_CIRCUIT_DIRTINESS); + log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too short; " + "raising to %d seconds.", MIN_MAX_CIRCUIT_DIRTINESS); options->MaxCircuitDirtiness = MIN_MAX_CIRCUIT_DIRTINESS; } + if (options->CircuitStreamTimeout && + options->CircuitStreamTimeout < MIN_CIRCUIT_STREAM_TIMEOUT) { + log_warn(LD_CONFIG, "CircuitStreamTimeout option is too short; " + "raising to %d seconds.", MIN_CIRCUIT_STREAM_TIMEOUT); + options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT; + } + if (options->KeepalivePeriod < 1) REJECT("KeepalivePeriod option must be positive."); @@ -3367,34 +3330,37 @@ options_validate(or_options_t *old_options, or_options_t *options, if (ensure_bandwidth_cap(&options->RelayBandwidthBurst, "RelayBandwidthBurst", msg) < 0) return -1; + if (ensure_bandwidth_cap(&options->PerConnBWRate, + "PerConnBWRate", msg) < 0) + return -1; + if (ensure_bandwidth_cap(&options->PerConnBWBurst, + "PerConnBWBurst", msg) < 0) + return -1; if (server_mode(options)) { if (options->BandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "BandwidthRate is set to %d bytes/second. " "For servers, it must be at least %d.", (int)options->BandwidthRate, ROUTER_REQUIRED_MIN_BANDWIDTH); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } else if (options->MaxAdvertisedBandwidth < ROUTER_REQUIRED_MIN_BANDWIDTH/2) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "MaxAdvertisedBandwidth is set to %d bytes/second. " "For servers, it must be at least %d.", (int)options->MaxAdvertisedBandwidth, ROUTER_REQUIRED_MIN_BANDWIDTH/2); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } if (options->RelayBandwidthRate && options->RelayBandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "RelayBandwidthRate is set to %d bytes/second. " "For servers, it must be at least %d.", (int)options->RelayBandwidthRate, ROUTER_REQUIRED_MIN_BANDWIDTH); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } } @@ -3419,34 +3385,73 @@ options_validate(or_options_t *old_options, or_options_t *options, if (accounting_parse_options(options, 1)<0) REJECT("Failed to parse accounting options. See logs for details."); - if (options->HttpProxy) { /* parse it now */ - if (parse_addr_port(LOG_WARN, options->HttpProxy, NULL, - &options->HttpProxyAddr, &options->HttpProxyPort) < 0) - REJECT("HttpProxy failed to parse or resolve. Please fix."); - if (options->HttpProxyPort == 0) { /* give it a default */ - options->HttpProxyPort = 80; + if (options->HTTPProxy) { /* parse it now */ + if (tor_addr_port_parse(options->HTTPProxy, + &options->HTTPProxyAddr, &options->HTTPProxyPort) < 0) + REJECT("HTTPProxy failed to parse or resolve. Please fix."); + if (options->HTTPProxyPort == 0) { /* give it a default */ + options->HTTPProxyPort = 80; + } + } + + if (options->HTTPProxyAuthenticator) { + if (strlen(options->HTTPProxyAuthenticator) >= 48) + REJECT("HTTPProxyAuthenticator is too long (>= 48 chars)."); + } + + if (options->HTTPSProxy) { /* parse it now */ + if (tor_addr_port_parse(options->HTTPSProxy, + &options->HTTPSProxyAddr, &options->HTTPSProxyPort) <0) + REJECT("HTTPSProxy failed to parse or resolve. Please fix."); + if (options->HTTPSProxyPort == 0) { /* give it a default */ + options->HTTPSProxyPort = 443; } } - if (options->HttpProxyAuthenticator) { - if (strlen(options->HttpProxyAuthenticator) >= 48) - REJECT("HttpProxyAuthenticator is too long (>= 48 chars)."); + if (options->HTTPSProxyAuthenticator) { + if (strlen(options->HTTPSProxyAuthenticator) >= 48) + REJECT("HTTPSProxyAuthenticator is too long (>= 48 chars)."); } - if (options->HttpsProxy) { /* parse it now */ - if (parse_addr_port(LOG_WARN, options->HttpsProxy, NULL, - &options->HttpsProxyAddr, &options->HttpsProxyPort) <0) - REJECT("HttpsProxy failed to parse or resolve. Please fix."); - if (options->HttpsProxyPort == 0) { /* give it a default */ - options->HttpsProxyPort = 443; + if (options->Socks4Proxy) { /* parse it now */ + if (tor_addr_port_parse(options->Socks4Proxy, + &options->Socks4ProxyAddr, + &options->Socks4ProxyPort) <0) + REJECT("Socks4Proxy failed to parse or resolve. Please fix."); + if (options->Socks4ProxyPort == 0) { /* give it a default */ + options->Socks4ProxyPort = 1080; } } - if (options->HttpsProxyAuthenticator) { - if (strlen(options->HttpsProxyAuthenticator) >= 48) - REJECT("HttpsProxyAuthenticator is too long (>= 48 chars)."); + if (options->Socks5Proxy) { /* parse it now */ + if (tor_addr_port_parse(options->Socks5Proxy, + &options->Socks5ProxyAddr, + &options->Socks5ProxyPort) <0) + REJECT("Socks5Proxy failed to parse or resolve. Please fix."); + if (options->Socks5ProxyPort == 0) { /* give it a default */ + options->Socks5ProxyPort = 1080; + } } + if (options->Socks4Proxy && options->Socks5Proxy) + REJECT("You cannot specify both Socks4Proxy and SOCKS5Proxy"); + + if (options->Socks5ProxyUsername) { + size_t len; + + len = strlen(options->Socks5ProxyUsername); + if (len < 1 || len > 255) + REJECT("Socks5ProxyUsername must be between 1 and 255 characters."); + + if (!options->Socks5ProxyPassword) + REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername."); + + len = strlen(options->Socks5ProxyPassword); + if (len < 1 || len > 255) + REJECT("Socks5ProxyPassword must be between 1 and 255 characters."); + } else if (options->Socks5ProxyPassword) + REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername."); + if (options->HashedControlPassword) { smartlist_t *sl = decode_hashed_passwords(options->HashedControlPassword); if (!sl) { @@ -3510,6 +3515,13 @@ options_validate(or_options_t *old_options, or_options_t *options, "upgrade your Tor controller as soon as possible."); } + if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) { + log_warn(LD_CONFIG, "You set the CookieAuthFileGroupReadable but did " + "not configure a the path for the cookie file via " + "CookieAuthFile. This means your cookie will not be group " + "readable."); + } + if (options->UseEntryGuards && ! options->NumEntryGuards) REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0"); @@ -3543,11 +3555,10 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->ConstrainedSockSize < MIN_CONSTRAINED_TCP_BUFFER || options->ConstrainedSockSize > MAX_CONSTRAINED_TCP_BUFFER || options->ConstrainedSockSize % 1024) { - r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "ConstrainedSockSize is invalid. Must be a value between %d and %d " "in 1024 byte increments.", MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } if (options->DirPort) { @@ -3595,6 +3606,12 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->PreferTunneledDirConns && !options->TunnelDirConns) REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set."); + if ((options->Socks4Proxy || options->Socks5Proxy) && + !options->HTTPProxy && !options->PreferTunneledDirConns) + REJECT("When Socks4Proxy or Socks5Proxy is configured, " + "PreferTunneledDirConns and TunnelDirConns must both be " + "set to 1, or HTTPProxy must be configured."); + if (options->AutomapHostsSuffixes) { SMARTLIST_FOREACH(options->AutomapHostsSuffixes, char *, suf, { @@ -3609,6 +3626,13 @@ options_validate(or_options_t *old_options, or_options_t *options, "a non-default set of DirServers."); } + if (options->AllowSingleHopExits && !options->DirServers) { + COMPLAIN("You have set AllowSingleHopExits; now your relay will allow " + "others to make one-hop exits. However, since by default most " + "clients avoid relays that set this option, most clients will " + "ignore you."); + } + /*XXXX022 checking for defaults manually like this is a bit fragile.*/ /* Keep changes to hard-coded values synchronous to man page and default @@ -3674,6 +3698,26 @@ options_validate(or_options_t *old_options, or_options_t *options, "testing Tor network!"); } + if (options->AccelName && !options->HardwareAccel) + options->HardwareAccel = 1; + if (options->AccelDir && !options->AccelName) + REJECT("Can't use hardware crypto accelerator dir without engine name."); + + if (options->PublishServerDescriptor) + SMARTLIST_FOREACH(options->PublishServerDescriptor, const char *, pubdes, { + if (!strcmp(pubdes, "1") || !strcmp(pubdes, "0")) + if (smartlist_len(options->PublishServerDescriptor) > 1) { + COMPLAIN("You have passed a list of multiple arguments to the " + "PublishServerDescriptor option that includes 0 or 1. " + "0 or 1 should only be used as the sole argument. " + "This configuration will be rejected in a future release."); + break; + } + }); + + if (options->BridgeRelay == 1 && options->ORPort == 0) + REJECT("BridgeRelay is 1, ORPort is 0. This is an invalid combination."); + return 0; #undef REJECT #undef COMPLAIN @@ -3712,12 +3756,10 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val, } if (strcmp(old->DataDirectory,new_val->DataDirectory)!=0) { - char buf[1024]; - int r = tor_snprintf(buf, sizeof(buf), + tor_asprintf(msg, "While Tor is running, changing DataDirectory " "(\"%s\"->\"%s\") is not allowed.", old->DataDirectory, new_val->DataDirectory); - *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } @@ -3726,19 +3768,22 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val, return -1; } - if (!opt_streq(old->Group, new_val->Group)) { - *msg = tor_strdup("While Tor is running, changing Group is not allowed."); + if ((old->HardwareAccel != new_val->HardwareAccel) + || !opt_streq(old->AccelName, new_val->AccelName) + || !opt_streq(old->AccelDir, new_val->AccelDir)) { + *msg = tor_strdup("While Tor is running, changing OpenSSL hardware " + "acceleration engine is not allowed."); return -1; } - if (old->HardwareAccel != new_val->HardwareAccel) { - *msg = tor_strdup("While Tor is running, changing HardwareAccel is " - "not allowed."); + if (old->TestingTorNetwork != new_val->TestingTorNetwork) { + *msg = tor_strdup("While Tor is running, changing TestingTorNetwork " + "is not allowed."); return -1; } - if (old->TestingTorNetwork != new_val->TestingTorNetwork) { - *msg = tor_strdup("While Tor is running, changing TestingTorNetwork " + if (old->DisableAllSwap != new_val->DisableAllSwap) { + *msg = tor_strdup("While Tor is running, changing DisableAllSwap " "is not allowed."); return -1; } @@ -3753,7 +3798,7 @@ options_transition_affects_workers(or_options_t *old_options, or_options_t *new_options) { if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) || - old_options->NumCpus != new_options->NumCpus || + old_options->NumCPUs != new_options->NumCPUs || old_options->ORPort != new_options->ORPort || old_options->ServerDNSSearchDomains != new_options->ServerDNSSearchDomains || @@ -3785,7 +3830,6 @@ 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->NoPublish != new_options->NoPublish || old_options->_PublishServerDescriptor != new_options->_PublishServerDescriptor || get_effective_bwrate(old_options) != get_effective_bwrate(new_options) || @@ -3808,6 +3852,7 @@ get_windows_conf_root(void) { static int is_set = 0; static char path[MAX_PATH+1]; + TCHAR tpath[MAX_PATH] = {0}; LPITEMIDLIST idl; IMalloc *m; @@ -3825,7 +3870,7 @@ get_windows_conf_root(void) #define APPDATA_PATH CSIDL_APPDATA #endif if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, APPDATA_PATH, &idl))) { - GetCurrentDirectory(MAX_PATH, path); + getcwd(path,MAX_PATH); is_set = 1; log_warn(LD_CONFIG, "I couldn't find your application data folder: are you " @@ -3834,8 +3879,15 @@ get_windows_conf_root(void) return path; } /* Convert the path from an "ID List" (whatever that is!) to a path. */ - result = SHGetPathFromIDList(idl, path); - /* Now we need to free the */ + result = SHGetPathFromIDList(idl, tpath); +#ifdef UNICODE + wcstombs(path,tpath,MAX_PATH); +#else + strlcpy(path,tpath,sizeof(path)); +#endif + + /* Now we need to free the memory that the path-idl was stored in. In + * typical Windows fashion, we can't just call 'free()' on it. */ SHGetMalloc(&m); if (m) { m->lpVtbl->Free(m, idl); @@ -3883,10 +3935,7 @@ check_nickname_list(const char *lst, const char *name, char **msg) SMARTLIST_FOREACH(sl, const char *, s, { if (!is_legal_nickname_or_hexdigest(s)) { - char buf[1024]; - int tmp = tor_snprintf(buf, sizeof(buf), - "Invalid nickname '%s' in %s line", s, name); - *msg = tor_strdup(tmp >= 0 ? buf : "internal error"); + tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name); r = -1; break; } @@ -3910,13 +3959,7 @@ find_torrc_filename(int argc, char **argv, log(LOG_WARN, LD_CONFIG, "Duplicate -f options on command line."); tor_free(fname); } -#ifdef MS_WINDOWS - /* XXX one day we might want to extend expand_filename to work - * under Windows as well. */ - fname = tor_strdup(argv[i+1]); -#else fname = expand_filename(argv[i+1]); -#endif *using_default_torrc = 0; ++i; } else if (!strcmp(argv[i],"--ignore-missing-torrc")) { @@ -4022,6 +4065,12 @@ options_init_from_torrc(int argc, char **argv) printf("Tor version %s.\n",get_version()); exit(0); } + if (argc > 1 && (!strcmp(argv[1],"--digests"))) { + printf("Tor version %s.\n",get_version()); + printf("%s", libor_get_digests()); + printf("%s", tor_get_digests()); + exit(0); + } /* Go through command-line variables */ if (!global_cmdline_options) { @@ -4189,12 +4238,9 @@ options_init_from_string(const char *cf, err: config_free(&options_format, newoptions); if (*msg) { - int len = (int)strlen(*msg)+256; - char *newmsg = tor_malloc(len); - - tor_snprintf(newmsg, len, "Failed to parse/validate config: %s", *msg); - tor_free(*msg); - *msg = newmsg; + char *old_msg = *msg; + tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg); + tor_free(old_msg); } return err; } @@ -4582,7 +4628,7 @@ normalize_data_directory(or_options_t *options) } /** Check and normalize the value of options->DataDirectory; return 0 if it - * sane, -1 otherwise. */ + * is sane, -1 otherwise. */ static int validate_data_directory(or_options_t *options) { @@ -4614,7 +4660,6 @@ write_configuration_file(const char *fname, or_options_t *options) { char *old_val=NULL, *new_val=NULL, *new_conf=NULL; int rename_old = 0, r; - size_t len; tor_assert(fname); @@ -4641,9 +4686,7 @@ write_configuration_file(const char *fname, or_options_t *options) goto err; } - len = strlen(new_conf)+256; - new_val = tor_malloc(len); - tor_snprintf(new_val, len, "%s\n%s\n\n%s", + tor_asprintf(&new_val, "%s\n%s\n\n%s", GENERATED_FILE_PREFIX, GENERATED_FILE_COMMENT, new_conf); if (rename_old) { @@ -4693,15 +4736,12 @@ write_configuration_file(const char *fname, or_options_t *options) int options_save_current(void) { - if (torrc_fname) { - /* This fails if we can't write to our configuration file. - * - * 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. Let's just warn instead. */ - return write_configuration_file(torrc_fname, get_options()); - } - return write_configuration_file(get_default_conf_file(), get_options()); + /* This fails if we can't write to our configuration file. + * + * 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()); } /** Mapping from a unit name to a multiplier for converting that unit into a @@ -4766,30 +4806,47 @@ static struct unit_table_t time_units[] = { static uint64_t config_parse_units(const char *val, struct unit_table_t *u, int *ok) { - uint64_t v; + uint64_t v = 0; + double d = 0; + int use_float = 0; char *cp; tor_assert(ok); v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp); - if (!*ok) - return 0; + if (!*ok || (cp && *cp == '.')) { + d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp); + if (!*ok) + goto done; + use_float = 1; + } + if (!cp) { *ok = 1; - return v; + v = use_float ? DBL_TO_U64(d) : v; + goto done; } - while (TOR_ISSPACE(*cp)) - ++cp; + + cp = (char*) eat_whitespace(cp); + for ( ;u->unit;++u) { if (!strcasecmp(u->unit, cp)) { - v *= u->multiplier; + if (use_float) + v = u->multiplier * d; + else + v *= u->multiplier; *ok = 1; - return v; + goto done; } } log_warn(LD_CONFIG, "Unknown unit '%s'.", cp); *ok = 0; - return 0; + done: + + if (*ok) + return v; + else + return 0; } /** Parse a string in the format "number unit", where unit is a unit of @@ -4799,7 +4856,8 @@ config_parse_units(const char *val, struct unit_table_t *u, int *ok) static uint64_t config_parse_memunit(const char *s, int *ok) { - return config_parse_units(s, memory_units, ok); + uint64_t u = config_parse_units(s, memory_units, ok); + return u; } /** Parse a string in the format "number unit", where unit is a unit of time. @@ -4821,256 +4879,37 @@ config_parse_interval(const char *s, int *ok) return (int)r; } -/* This is what passes for version detection on OSX. We set - * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before - * 10.4.0 (aka 1040). */ -#ifdef __APPLE__ -#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ -#define MACOSX_KQUEUE_IS_BROKEN \ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040) -#else -#define MACOSX_KQUEUE_IS_BROKEN 0 -#endif -#endif - /** * Initialize the libevent library. */ static void init_libevent(void) { + const char *badness=NULL; + configure_libevent_logging(); /* If the kernel complains that some method (say, epoll) doesn't * exist, we don't care about it, since libevent will cope. */ suppress_libevent_log_msg("Function not implemented"); -#ifdef __APPLE__ - if (MACOSX_KQUEUE_IS_BROKEN || - decode_libevent_version(event_get_version(), NULL) < LE_11B) { - setenv("EVENT_NOKQUEUE","1",1); - } -#endif - /* In libevent versions before 2.0, it's hard to keep binary compatibility - * between upgrades, and unpleasant to detect when the version we compiled - * against is unlike the version we have linked against. Here's how. */ -#if defined(_EVENT_VERSION) && defined(HAVE_EVENT_GET_VERSION) - /* We have a header-file version and a function-call version. Easy. */ - if (strcmp(_EVENT_VERSION, event_get_version())) { - int compat1 = -1, compat2 = -1; - int verybad, prettybad ; - decode_libevent_version(_EVENT_VERSION, &compat1); - decode_libevent_version(event_get_version(), &compat2); - verybad = compat1 != compat2; - prettybad = (compat1 == -1 || compat2 == -1) && compat1 != compat2; - - log(verybad ? LOG_WARN : (prettybad ? LOG_NOTICE : LOG_INFO), - LD_GENERAL, "We were compiled with headers from version %s " - "of Libevent, but we're using a Libevent library that says it's " - "version %s.", _EVENT_VERSION, event_get_version()); - if (verybad) - log_warn(LD_GENERAL, "This will almost certainly make Tor crash."); - else if (prettybad) - log_notice(LD_GENERAL, "If Tor crashes, this might be why."); - else - log_info(LD_GENERAL, "I think these versions are binary-compatible."); - } -#elif defined(HAVE_EVENT_GET_VERSION) - /* event_get_version but no _EVENT_VERSION. We might be in 1.4.0-beta or - earlier, where that's normal. To see whether we were compiled with an - earlier version, let's see whether the struct event defines MIN_HEAP_IDX. - */ -#ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX - /* The header files are 1.4.0-beta or later. If the version is not - * 1.4.0-beta, we are incompatible. */ - { - if (strcmp(event_get_version(), "1.4.0-beta")) { - log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have " - "Libevent 1.4.0-beta header files, whereas you have linked " - "against Libevent %s. This will probably make Tor crash.", - event_get_version()); - } - } -#else - /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or - later, we're probably fine. */ - { - const char *v = event_get_version(); - if ((v[0] == '1' && v[2] == '.' && v[3] > '3') || v[0] > '1') { - log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have " - "Libevent header file from 1.3e or earlier, whereas you have " - "linked against Libevent %s. This will probably make Tor " - "crash.", event_get_version()); - } - } -#endif + tor_check_libevent_header_compatibility(); -#elif defined(_EVENT_VERSION) -#warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd." -#else - /* Your libevent is ancient. */ -#endif + tor_libevent_initialize(); - event_init(); suppress_libevent_log_msg(NULL); -#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. */ - log(LOG_NOTICE, LD_GENERAL, - "Initialized libevent version %s using method %s. Good.", - event_get_version(), event_get_method()); - check_libevent_version(event_get_method(), get_options()->ORPort != 0); -#else - log(LOG_NOTICE, LD_GENERAL, - "Initialized old libevent (version 1.0b or earlier)."); - log(LOG_WARN, LD_GENERAL, - "You have a *VERY* old version of libevent. It is likely to be buggy; " - "please build Tor with a more recent version."); -#endif -} - -/** Table mapping return value of event_get_version() to le_version_t. */ -static const struct { - const char *name; le_version_t version; int bincompat; -} le_version_table[] = { - /* earlier versions don't have get_version. */ - { "1.0c", LE_10C, 1}, - { "1.0d", LE_10D, 1}, - { "1.0e", LE_10E, 1}, - { "1.1", LE_11, 1 }, - { "1.1a", LE_11A, 1 }, - { "1.1b", LE_11B, 1 }, - { "1.2", LE_12, 1 }, - { "1.2a", LE_12A, 1 }, - { "1.3", LE_13, 1 }, - { "1.3a", LE_13A, 1 }, - { "1.3b", LE_13B, 1 }, - { "1.3c", LE_13C, 1 }, - { "1.3d", LE_13D, 1 }, - { "1.3e", LE_13E, 1 }, - { "1.4.0-beta", LE_140, 2 }, - { "1.4.1-beta", LE_141, 2 }, - { "1.4.2-rc", LE_142, 2 }, - { "1.4.3-stable", LE_143, 2 }, - { "1.4.4-stable", LE_144, 2 }, - { "1.4.5-stable", LE_145, 2 }, - { "1.4.6-stable", LE_146, 2 }, - { "1.4.7-stable", LE_147, 2 }, - { "1.4.8-stable", LE_148, 2 }, - { "1.4.99-trunk", LE_1499, 3 }, - { NULL, LE_OTHER, 0 } -}; -/** Return the le_version_t for the current version of libevent. If the - * version is very new, return LE_OTHER. If the version is so old that it - * doesn't support event_get_version(), return LE_OLD. */ -static le_version_t -decode_libevent_version(const char *v, int *bincompat_out) -{ - int i; - for (i=0; le_version_table[i].name; ++i) { - if (!strcmp(le_version_table[i].name, v)) { - if (bincompat_out) - *bincompat_out = le_version_table[i].bincompat; - return le_version_table[i].version; - } - } - if (v[0] != '1' && bincompat_out) - *bincompat_out = 100; - else if (!strcmpstart(v, "1.4") && bincompat_out) - *bincompat_out = 2; - return LE_OTHER; -} - -#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD) -/** - * Compare the given libevent method and version to a list of versions - * which are known not to work. Warn the user as appropriate. - */ -static void -check_libevent_version(const char *m, int server) -{ - int buggy = 0, iffy = 0, slow = 0, thread_unsafe = 0; - le_version_t version; - const char *v = event_get_version(); - const char *badness = NULL; - const char *sad_os = ""; - - version = decode_libevent_version(v, NULL); - - /* XXX Would it be worthwhile disabling the methods that we know - * are buggy, rather than just warning about them and then proceeding - * to use them? If so, we should probably not wrap this whole thing - * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */ - /* XXXX The problem is that it's not trivial to get libevent to change it's - * method once it's initialized, and it's not trivial to tell what method it - * will use without initializing it. I guess we could preemptively disable - * buggy libevent modes based on the version _before_ initializing it, - * though, but then there's no good way (afaict) to warn "I would have used - * kqueue, but instead I'm using select." -NM */ - if (!strcmp(m, "kqueue")) { - if (version < LE_11B) - buggy = 1; - } else if (!strcmp(m, "epoll")) { - if (version < LE_11) - iffy = 1; - } else if (!strcmp(m, "poll")) { - if (version < LE_10E) - buggy = 1; - else if (version < LE_11) - slow = 1; - } else if (!strcmp(m, "select")) { - if (version < LE_11) - slow = 1; - } else if (!strcmp(m, "win32")) { - if (version < LE_11B) - buggy = 1; - } - - /* Libevent versions before 1.3b do very badly on operating systems with - * user-space threading implementations. */ -#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) - if (server && version < LE_13B) { - thread_unsafe = 1; - sad_os = "BSD variants"; - } -#elif defined(__APPLE__) || defined(__darwin__) - if (server && version < LE_13B) { - thread_unsafe = 1; - sad_os = "Mac OS X"; - } -#endif - - if (thread_unsafe) { - log(LOG_WARN, LD_GENERAL, - "Libevent version %s often crashes when running a Tor server with %s. " - "Please use the latest version of libevent (1.3b or later)",v,sad_os); - badness = "BROKEN"; - } else if (buggy) { - log(LOG_WARN, LD_GENERAL, - "There are serious bugs in using %s with libevent %s. " - "Please use the latest version of libevent.", m, v); - badness = "BROKEN"; - } else if (iffy) { - log(LOG_WARN, LD_GENERAL, - "There are minor bugs in using %s with libevent %s. " - "You may want to use the latest version of libevent.", m, v); - badness = "BUGGY"; - } else if (slow && server) { - log(LOG_WARN, LD_GENERAL, - "libevent %s can be very slow with %s. " - "When running a server, please use the latest version of libevent.", - v,m); - badness = "SLOW"; - } + tor_check_libevent_version(tor_libevent_get_method(), + get_options()->ORPort != 0, + &badness); if (badness) { + const char *v = tor_libevent_get_version_str(); + const char *m = tor_libevent_get_method(); control_event_general_status(LOG_WARN, "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO", v, m, badness); } - } -#endif /** Return the persistent state struct for this Tor. */ or_state_t * @@ -5152,22 +4991,61 @@ or_state_validate(or_state_t *old_state, or_state_t *state, } /** Replace the current persistent state with <b>new_state</b> */ -static void +static int or_state_set(or_state_t *new_state) { char *err = NULL; + int ret = 0; tor_assert(new_state); - if (global_state) - config_free(&state_format, global_state); + config_free(&state_format, global_state); global_state = new_state; if (entry_guards_parse_state(global_state, 1, &err)<0) { log_warn(LD_GENERAL,"%s",err); tor_free(err); + ret = -1; } if (rep_hist_load_state(global_state, &err)<0) { log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err); tor_free(err); + ret = -1; + } + if (circuit_build_times_parse_state(&circ_times, global_state) < 0) { + ret = -1; + } + return ret; +} + +/** + * Save a broken state file to a backup location. + */ +static void +or_state_save_broken(char *fname) +{ + int i; + file_status_t status; + size_t len = strlen(fname)+16; + char *fname2 = tor_malloc(len); + for (i = 0; i < 100; ++i) { + tor_snprintf(fname2, len, "%s.%d", fname, i); + status = file_status(fname2); + if (status == FN_NOENT) + break; + } + if (i == 100) { + log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad " + "state files to move aside. Discarding the old state file.", + fname); + unlink(fname); + } else { + log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside " + "to \"%s\". This could be a bug in Tor; please tell " + "the developers.", fname, fname2); + if (rename(fname, fname2) < 0) { + log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The " + "OS gave an error of %s", strerror(errno)); + } } + tor_free(fname2); } /** Reload the persistent state from disk, generating a new state as needed. @@ -5229,31 +5107,8 @@ or_state_load(void) " This is a bug in Tor."); goto done; } else if (badstate && contents) { - int i; - file_status_t status; - size_t len = strlen(fname)+16; - char *fname2 = tor_malloc(len); - for (i = 0; i < 100; ++i) { - tor_snprintf(fname2, len, "%s.%d", fname, i); - status = file_status(fname2); - if (status == FN_NOENT) - break; - } - if (i == 100) { - log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad " - "state files to move aside. Discarding the old state file.", - fname); - unlink(fname); - } else { - log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside " - "to \"%s\". This could be a bug in Tor; please tell " - "the developers.", fname, fname2); - if (rename(fname, fname2) < 0) { - log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The " - "OS gave an error of %s", strerror(errno)); - } - } - tor_free(fname2); + or_state_save_broken(fname); + tor_free(contents); config_free(&state_format, new_state); @@ -5265,7 +5120,9 @@ or_state_load(void) } else { log_info(LD_GENERAL, "Initialized state"); } - or_state_set(new_state); + if (or_state_set(new_state) == -1) { + or_state_save_broken(fname); + } new_state = NULL; if (!contents) { global_state->next_write = 0; @@ -5288,7 +5145,6 @@ or_state_save(time_t now) { char *state, *contents; char tbuf[ISO_TIME_LEN+1]; - size_t len; char *fname; tor_assert(global_state); @@ -5300,20 +5156,16 @@ or_state_save(time_t now) * to avoid redundant writes. */ entry_guards_update_state(global_state); rep_hist_update_state(global_state); + circuit_build_times_update_state(&circ_times, global_state); if (accounting_is_enabled(get_options())) accounting_run_housekeeping(now); - global_state->LastWritten = time(NULL); tor_free(global_state->TorVersion); - len = strlen(get_version())+8; - global_state->TorVersion = tor_malloc(len); - tor_snprintf(global_state->TorVersion, len, "Tor %s", get_version()); + tor_asprintf(&global_state->TorVersion, "Tor %s", get_version()); state = config_dump(&state_format, global_state, 1, 0); - len = strlen(state)+256; - contents = tor_malloc(len); format_local_iso_time(tbuf, time(NULL)); - tor_snprintf(contents, len, + tor_asprintf(&contents, "# Tor state file last generated on %s local time\n" "# Other times below are in GMT\n" "# You *do not* need to edit this file.\n\n%s", @@ -5322,10 +5174,13 @@ or_state_save(time_t now) fname = get_datadir_fname("state"); if (write_str_to_file(fname, contents, 0)<0) { log_warn(LD_FS, "Unable to write state to file \"%s\"", fname); + global_state->LastWritten = -1; tor_free(fname); tor_free(contents); return -1; } + + global_state->LastWritten = time(NULL); log_info(LD_GENERAL, "Saved state to \"%s\"", fname); tor_free(fname); tor_free(contents); @@ -5357,18 +5212,18 @@ remove_file_if_very_old(const char *fname, time_t now) * types. */ int getinfo_helper_config(control_connection_t *conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { (void) conn; + (void) errmsg; if (!strcmp(question, "config/names")) { smartlist_t *sl = smartlist_create(); int i; for (i = 0; _option_vars[i].name; ++i) { config_var_t *var = &_option_vars[i]; - const char *type, *desc; + const char *type; char *line; - size_t len; - desc = config_find_description(&options_format, var->name); switch (var->type) { case CONFIG_TYPE_STRING: type = "String"; break; case CONFIG_TYPE_FILENAME: type = "Filename"; break; @@ -5389,14 +5244,7 @@ getinfo_helper_config(control_connection_t *conn, } if (!type) continue; - len = strlen(var->name)+strlen(type)+16; - if (desc) - len += strlen(desc); - line = tor_malloc(len); - if (desc) - tor_snprintf(line, len, "%s %s %s\n",var->name,type,desc); - else - tor_snprintf(line, len, "%s %s\n",var->name,type); + tor_asprintf(&line, "%s %s\n",var->name,type); smartlist_add(sl, line); } *answer = smartlist_join_strings(sl, "", 0, NULL); diff --git a/src/or/config.h b/src/or/config.h new file mode 100644 index 0000000000..7a4ba5c60f --- /dev/null +++ b/src/or/config.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file config.h + * \brief Header file for config.c. + **/ + +#ifndef _TOR_CONFIG_H +#define _TOR_CONFIG_H + +const char *get_dirportfrontpage(void); +or_options_t *get_options(void); +int set_options(or_options_t *new_val, char **msg); +void config_free_all(void); +const char *safe_str_client(const char *address); +const char *safe_str(const char *address); +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); +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, + uint32_t *addr, char **hostname_out); +int is_local_addr(const tor_addr_t *addr) ATTR_PURE; +void options_init(or_options_t *options); +char *options_dump(or_options_t *options, int minimal); +int options_init_from_torrc(int argc, char **argv); +setopt_err_t options_init_from_string(const char *cf, + int command, const char *command_arg, char **msg); +int option_is_recognized(const char *key); +const char *option_get_canonical_name(const char *key); +config_line_t *option_get_assignment(or_options_t *options, + 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 *sub1, const char *sub2, + const char *suffix); +#define get_datadir_fname2_suffix(sub1, sub2, suffix) \ + options_get_datadir_fname2_suffix(get_options(), (sub1), (sub2), (suffix)) +/** Return a newly allocated string containing datadir/sub1. See + * get_datadir_fname2_suffix. */ +#define get_datadir_fname(sub1) get_datadir_fname2_suffix((sub1), NULL, NULL) +/** Return a newly allocated string containing datadir/sub1/sub2. See + * get_datadir_fname2_suffix. */ +#define get_datadir_fname2(sub1,sub2) \ + get_datadir_fname2_suffix((sub1), (sub2), NULL) +/** Return a newly allocated string containing datadir/sub1suffix. See + * get_datadir_fname2_suffix. */ +#define get_datadir_fname_suffix(sub1, suffix) \ + get_datadir_fname2_suffix((sub1), NULL, (suffix)) + +or_state_t *get_or_state(void); +int or_state_save(time_t now); + +int options_need_geoip_info(or_options_t *options, const char **reason_out); +int getinfo_helper_config(control_connection_t *conn, + const char *question, char **answer, + const char **errmsg); + +const char *tor_get_digests(void); +uint32_t get_effective_bwrate(or_options_t *options); +uint32_t get_effective_bwburst(or_options_t *options); + +#ifdef CONFIG_PRIVATE +/* Used only by config.c and test.c */ +or_options_t *options_new(void); +#endif + +#endif + diff --git a/src/or/config_codedigest.c b/src/or/config_codedigest.c new file mode 100644 index 0000000000..be9eaa331d --- /dev/null +++ b/src/or/config_codedigest.c @@ -0,0 +1,11 @@ + +const char *tor_get_digests(void); + +const char * +tor_get_digests(void) +{ + return "" +#include "or_sha1.i" + ; +} + diff --git a/src/or/connection.c b/src/or/connection.c index 5036be4507..85cede856c 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -11,6 +11,30 @@ **/ #include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "cpuworker.h" +#include "directory.h" +#include "dirserv.h" +#include "dns.h" +#include "dnsserv.h" +#include "geoip.h" +#include "main.h" +#include "policies.h" +#include "reasons.h" +#include "relay.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rephist.h" +#include "router.h" +#include "routerparse.h" static connection_t *connection_create_listener( struct sockaddr *listensockaddr, @@ -21,7 +45,8 @@ static void connection_init(time_t now, connection_t *conn, int type, static int connection_init_accepted_conn(connection_t *conn, uint8_t listener_type); static int connection_handle_listener_read(connection_t *conn, int new_type); -static int connection_read_bucket_should_increase(or_connection_t *conn); +static int connection_bucket_should_increase(int bucket, + or_connection_t *conn); static int connection_finished_flushing(connection_t *conn); static int connection_flushed_some(connection_t *conn); static int connection_finished_connecting(connection_t *conn); @@ -32,6 +57,10 @@ static int connection_process_inbuf(connection_t *conn, int package_partial); static void client_check_address_changed(int sock); static void set_constrained_socket_buffers(int sock, int size); +static 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); + /** 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. */ static uint32_t last_interface_ip = 0; @@ -92,8 +121,7 @@ conn_state_to_string(int type, int state) case CONN_TYPE_OR: switch (state) { case OR_CONN_STATE_CONNECTING: return "connect()ing"; - case OR_CONN_STATE_PROXY_FLUSHING: return "proxy flushing"; - case OR_CONN_STATE_PROXY_READING: return "proxy reading"; + 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)"; @@ -177,6 +205,9 @@ or_connection_new(int socket_family) or_conn->timestamp_last_added_nonpadding = time(NULL); or_conn->next_circ_id = crypto_rand_int(1<<15); + or_conn->active_circuit_pqueue = smartlist_create(); + or_conn->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick(); + return or_conn; } @@ -202,6 +233,7 @@ control_connection_new(int socket_family) tor_malloc_zero(sizeof(control_connection_t)); connection_init(time(NULL), TO_CONN(control_conn), CONN_TYPE_CONTROL, socket_family); + log_notice(LD_CONTROL, "New control connection opened."); return control_conn; } @@ -299,25 +331,6 @@ connection_link_connections(connection_t *conn_a, connection_t *conn_b) conn_b->linked_conn = conn_a; } -/** Tell libevent that we don't care about <b>conn</b> any more. */ -void -connection_unregister_events(connection_t *conn) -{ - if (conn->read_event) { - if (event_del(conn->read_event)) - log_warn(LD_BUG, "Error removing read event for %d", conn->s); - tor_free(conn->read_event); - } - if (conn->write_event) { - if (event_del(conn->write_event)) - log_warn(LD_BUG, "Error removing write event for %d", conn->s); - tor_free(conn->write_event); - } - if (conn->dns_server_port) { - dnsserv_close_listener(conn); - } -} - /** Deallocate memory used by <b>conn</b>. Deallocate its buffers if * necessary, close its socket if necessary, and mark the directory as dirty * if <b>conn</b> is an OR or OP connection. @@ -327,6 +340,9 @@ _connection_free(connection_t *conn) { void *mem; size_t memlen; + if (!conn) + return; + switch (conn->type) { case CONN_TYPE_OR: tor_assert(conn->magic == OR_CONNECTION_MAGIC); @@ -384,14 +400,11 @@ _connection_free(connection_t *conn) if (connection_speaks_cells(conn)) { or_connection_t *or_conn = TO_OR_CONN(conn); - if (or_conn->tls) { - tor_tls_free(or_conn->tls); - or_conn->tls = NULL; - } - if (or_conn->handshake_state) { - or_handshake_state_free(or_conn->handshake_state); - or_conn->handshake_state = NULL; - } + tor_tls_free(or_conn->tls); + or_conn->tls = NULL; + or_handshake_state_free(or_conn->handshake_state); + or_conn->handshake_state = NULL; + smartlist_free(or_conn->active_circuit_pqueue); tor_free(or_conn->nickname); } if (CONN_IS_EDGE(conn)) { @@ -401,8 +414,8 @@ _connection_free(connection_t *conn) memset(edge_conn->socks_request, 0xcc, sizeof(socks_request_t)); tor_free(edge_conn->socks_request); } - if (edge_conn->rend_data) - rend_data_free(edge_conn->rend_data); + + rend_data_free(edge_conn->rend_data); } if (conn->type == CONN_TYPE_CONTROL) { control_connection_t *control_conn = TO_CONTROL_CONN(conn); @@ -415,16 +428,15 @@ _connection_free(connection_t *conn) if (conn->type == CONN_TYPE_DIR) { dir_connection_t *dir_conn = TO_DIR_CONN(conn); tor_free(dir_conn->requested_resource); - if (dir_conn->zlib_state) - tor_zlib_free(dir_conn->zlib_state); + + tor_zlib_free(dir_conn->zlib_state); if (dir_conn->fingerprint_stack) { SMARTLIST_FOREACH(dir_conn->fingerprint_stack, char *, cp, tor_free(cp)); smartlist_free(dir_conn->fingerprint_stack); } - if (dir_conn->cached_dir) - cached_dir_decref(dir_conn->cached_dir); - if (dir_conn->rend_data) - rend_data_free(dir_conn->rend_data); + + cached_dir_decref(dir_conn->cached_dir); + rend_data_free(dir_conn->rend_data); } if (conn->s >= 0) { @@ -439,7 +451,7 @@ _connection_free(connection_t *conn) connection_or_remove_from_identity_map(TO_OR_CONN(conn)); } - memset(conn, 0xAA, memlen); /* poison memory */ + memset(mem, 0xCC, memlen); /* poison memory */ tor_free(mem); } @@ -448,7 +460,8 @@ _connection_free(connection_t *conn) void connection_free(connection_t *conn) { - tor_assert(conn); + if (!conn) + return; tor_assert(!connection_is_on_closeable_list(conn)); tor_assert(!connection_in_array(conn)); if (conn->linked_conn) { @@ -544,13 +557,6 @@ connection_about_to_close_connection(connection_t *conn) * failed: forget about this router, and maybe try again. */ connection_dir_request_failed(dir_conn); } - if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC && dir_conn->rend_data) { - /* Give it a try. However, there is no re-fetching for v0 rend - * descriptors; if the response is empty or the descriptor is - * unusable, close pending connections (unless a v2 request is - * still in progress). */ - rend_client_desc_trynow(dir_conn->rend_data->onion_address, 0); - } /* 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 @@ -573,7 +579,7 @@ connection_about_to_close_connection(connection_t *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); + !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, @@ -589,7 +595,7 @@ connection_about_to_close_connection(connection_t *conn) 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 (or_conn->identity_digest) { + } 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)); @@ -833,16 +839,16 @@ static void warn_too_many_conns(void) { #define WARN_TOO_MANY_CONNS_INTERVAL (6*60*60) - static time_t last_warned = 0; - time_t now = time(NULL); - int n_conns = get_n_open_sockets(); - if (last_warned + WARN_TOO_MANY_CONNS_INTERVAL < now) { + static ratelim_t last_warned = RATELIM_INIT(WARN_TOO_MANY_CONNS_INTERVAL); + char *m; + if ((m = rate_limit_log(&last_warned, approx_time()))) { + int n_conns = get_n_open_sockets(); log_warn(LD_NET,"Failing because we have %d connections already. Please " - "raise your ulimit -n.", n_conns); - last_warned = now; + "raise your ulimit -n.%s", n_conns, m); + tor_free(m); + control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d", + n_conns); } - control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d", - n_conns); } /** Bind a new non-blocking socket listening to the socket described @@ -1254,7 +1260,7 @@ connection_connect(connection_t *conn, const char *address, return -1; } - if (options->OutboundBindAddress) { + if (options->OutboundBindAddress && !tor_addr_is_loopback(addr)) { struct sockaddr_in ext_addr; memset(&ext_addr, 0, sizeof(ext_addr)); @@ -1285,7 +1291,8 @@ connection_connect(connection_t *conn, const char *address, dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf)); tor_assert(dest_addr_len > 0); - log_debug(LD_NET,"Connecting to %s:%u.",escaped_safe_str(address),port); + log_debug(LD_NET, "Connecting to %s:%u.", + escaped_safe_str_client(address), port); if (connect(s, dest_addr, dest_addr_len) < 0) { int e = tor_socket_errno(s); @@ -1293,7 +1300,8 @@ connection_connect(connection_t *conn, const char *address, /* yuck. kill it. */ *socket_error = e; log_info(LD_NET, - "connect() to %s:%u failed: %s",escaped_safe_str(address), + "connect() to %s:%u failed: %s", + escaped_safe_str_client(address), port, tor_socket_strerror(e)); tor_close_socket(s); return -1; @@ -1307,7 +1315,8 @@ connection_connect(connection_t *conn, const char *address, /* it succeeded. we're connected. */ log_fn(inprogress?LOG_DEBUG:LOG_INFO, LD_NET, - "Connection to %s:%u %s (sock %d).",escaped_safe_str(address), + "Connection to %s:%u %s (sock %d).", + escaped_safe_str_client(address), port, inprogress?"in progress":"established", s); conn->s = s; if (connection_add(conn) < 0) /* no space, forget it */ @@ -1315,6 +1324,353 @@ connection_connect(connection_t *conn, const char *address, return inprogress ? 0 : 1; } +/** Convert state number to string representation for logging purposes. + */ +static const char * +connection_proxy_state_to_string(int state) +{ + static const char *unknown = "???"; + static const char *states[] = { + "PROXY_NONE", + "PROXY_HTTPS_WANT_CONNECT_OK", + "PROXY_SOCKS4_WANT_CONNECT_OK", + "PROXY_SOCKS5_WANT_AUTH_METHOD_NONE", + "PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929", + "PROXY_SOCKS5_WANT_AUTH_RFC1929_OK", + "PROXY_SOCKS5_WANT_CONNECT_OK", + "PROXY_CONNECTED", + }; + + if (state < PROXY_NONE || state > PROXY_CONNECTED) + return unknown; + + return states[state]; +} + +/** Write a proxy request of <b>type</b> (socks4, socks5, https) to conn + * for conn->addr:conn->port, authenticating with the auth details given + * in the configuration (if available). SOCKS 5 and HTTP CONNECT proxies + * support authentication. + * + * Returns -1 if conn->addr is incompatible with the proxy protocol, and + * 0 otherwise. + * + * Use connection_read_proxy_handshake() to complete the handshake. + */ +int +connection_proxy_connect(connection_t *conn, int type) +{ + or_options_t *options; + + tor_assert(conn); + + options = get_options(); + + switch (type) { + case PROXY_CONNECT: { + char buf[1024]; + char *base64_authenticator=NULL; + const char *authenticator = options->HTTPSProxyAuthenticator; + + /* Send HTTP CONNECT and authentication (if available) in + * one request */ + + if (authenticator) { + base64_authenticator = alloc_http_authenticator(authenticator); + if (!base64_authenticator) + log_warn(LD_OR, "Encoding https authenticator failed"); + } + + if (base64_authenticator) { + tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", + fmt_addr(&conn->addr), + conn->port, base64_authenticator); + tor_free(base64_authenticator); + } else { + tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n", + fmt_addr(&conn->addr), conn->port); + } + + connection_write_to_buf(buf, strlen(buf), conn); + conn->proxy_state = PROXY_HTTPS_WANT_CONNECT_OK; + break; + } + + case PROXY_SOCKS4: { + unsigned char buf[9]; + uint16_t portn; + uint32_t ip4addr; + + /* Send a SOCKS4 connect request with empty user id */ + + if (tor_addr_family(&conn->addr) != AF_INET) { + log_warn(LD_NET, "SOCKS4 client is incompatible with IPv6"); + return -1; + } + + ip4addr = tor_addr_to_ipv4n(&conn->addr); + portn = htons(conn->port); + + buf[0] = 4; /* version */ + buf[1] = SOCKS_COMMAND_CONNECT; /* command */ + memcpy(buf + 2, &portn, 2); /* port */ + memcpy(buf + 4, &ip4addr, 4); /* addr */ + buf[8] = 0; /* userid (empty) */ + + connection_write_to_buf((char *)buf, sizeof(buf), conn); + conn->proxy_state = PROXY_SOCKS4_WANT_CONNECT_OK; + break; + } + + case PROXY_SOCKS5: { + unsigned char buf[4]; /* fields: vers, num methods, method list */ + + /* Send a SOCKS5 greeting (connect request must wait) */ + + buf[0] = 5; /* version */ + + /* number of auth methods */ + if (options->Socks5ProxyUsername) { + buf[1] = 2; + buf[2] = 0x00; /* no authentication */ + buf[3] = 0x02; /* rfc1929 Username/Passwd auth */ + conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929; + } else { + buf[1] = 1; + buf[2] = 0x00; /* no authentication */ + conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_NONE; + } + + connection_write_to_buf((char *)buf, 2 + buf[1], conn); + break; + } + + default: + log_err(LD_BUG, "Invalid proxy protocol, %d", type); + tor_fragile_assert(); + return -1; + } + + log_debug(LD_NET, "set state %s", + connection_proxy_state_to_string(conn->proxy_state)); + + return 0; +} + +/** Read conn's inbuf. If the http response from the proxy is all + * here, make sure it's good news, then return 1. If it's bad news, + * return -1. Else return 0 and hope for better luck next time. + */ +static int +connection_read_https_proxy_response(connection_t *conn) +{ + char *headers; + char *reason=NULL; + int status_code; + time_t date_header; + + switch (fetch_from_buf_http(conn->inbuf, + &headers, MAX_HEADERS_SIZE, + NULL, NULL, 10000, 0)) { + case -1: /* overflow */ + log_warn(LD_PROTOCOL, + "Your https proxy sent back an oversized response. Closing."); + return -1; + case 0: + log_info(LD_NET,"https proxy response not all here yet. Waiting."); + return 0; + /* case 1, fall through */ + } + + if (parse_http_response(headers, &status_code, &date_header, + NULL, &reason) < 0) { + log_warn(LD_NET, + "Unparseable headers from proxy (connecting to '%s'). Closing.", + conn->address); + tor_free(headers); + return -1; + } + if (!reason) reason = tor_strdup("[no reason given]"); + + if (status_code == 200) { + log_info(LD_NET, + "HTTPS connect to '%s' successful! (200 %s) Starting TLS.", + conn->address, escaped(reason)); + tor_free(reason); + return 1; + } + /* else, bad news on the status code */ + log_warn(LD_NET, + "The https proxy sent back an unexpected status code %d (%s). " + "Closing.", + status_code, escaped(reason)); + tor_free(reason); + return -1; +} + +/** Send SOCKS5 CONNECT command to <b>conn</b>, copying <b>conn->addr</b> + * and <b>conn->port</b> into the request. + */ +static void +connection_send_socks5_connect(connection_t *conn) +{ + unsigned char buf[1024]; + size_t reqsize = 6; + uint16_t port = htons(conn->port); + + buf[0] = 5; /* version */ + buf[1] = SOCKS_COMMAND_CONNECT; /* command */ + buf[2] = 0; /* reserved */ + + if (tor_addr_family(&conn->addr) == AF_INET) { + uint32_t addr = tor_addr_to_ipv4n(&conn->addr); + + buf[3] = 1; + reqsize += 4; + memcpy(buf + 4, &addr, 4); + memcpy(buf + 8, &port, 2); + } else { /* AF_INET6 */ + buf[3] = 4; + reqsize += 16; + memcpy(buf + 4, tor_addr_to_in6(&conn->addr), 16); + memcpy(buf + 20, &port, 2); + } + + connection_write_to_buf((char *)buf, reqsize, conn); + + conn->proxy_state = PROXY_SOCKS5_WANT_CONNECT_OK; +} + +/** Call this from connection_*_process_inbuf() to advance the proxy + * handshake. + * + * No matter what proxy protocol is used, if this function returns 1, the + * handshake is complete, and the data remaining on inbuf may contain the + * start of the communication with the requested server. + * + * Returns 0 if the current buffer contains an incomplete response, and -1 + * on error. + */ +int +connection_read_proxy_handshake(connection_t *conn) +{ + int ret = 0; + char *reason = NULL; + + log_debug(LD_NET, "enter state %s", + connection_proxy_state_to_string(conn->proxy_state)); + + switch (conn->proxy_state) { + case PROXY_HTTPS_WANT_CONNECT_OK: + ret = connection_read_https_proxy_response(conn); + if (ret == 1) + conn->proxy_state = PROXY_CONNECTED; + break; + + case PROXY_SOCKS4_WANT_CONNECT_OK: + ret = fetch_from_buf_socks_client(conn->inbuf, + 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); + /* no auth needed, do connect */ + if (ret == 1) { + connection_send_socks5_connect(conn); + ret = 0; + } + break; + + case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929: + ret = fetch_from_buf_socks_client(conn->inbuf, + conn->proxy_state, + &reason); + + /* send auth if needed, otherwise do connect */ + if (ret == 1) { + connection_send_socks5_connect(conn); + ret = 0; + } else if (ret == 2) { + unsigned char buf[1024]; + size_t reqsize, usize, psize; + const char *user, *pass; + + user = get_options()->Socks5ProxyUsername; + pass = get_options()->Socks5ProxyPassword; + tor_assert(user && pass); + + /* XXX len of user and pass must be <= 255 !!! */ + usize = strlen(user); + psize = strlen(pass); + tor_assert(usize <= 255 && psize <= 255); + reqsize = 3 + usize + psize; + + buf[0] = 1; /* negotiation version */ + buf[1] = usize; + memcpy(buf + 2, user, usize); + buf[2 + usize] = psize; + memcpy(buf + 3 + usize, pass, psize); + + connection_write_to_buf((char *)buf, reqsize, conn); + + conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_RFC1929_OK; + ret = 0; + } + break; + + case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK: + ret = fetch_from_buf_socks_client(conn->inbuf, + conn->proxy_state, + &reason); + /* send the connect request */ + if (ret == 1) { + connection_send_socks5_connect(conn); + ret = 0; + } + break; + + case PROXY_SOCKS5_WANT_CONNECT_OK: + ret = fetch_from_buf_socks_client(conn->inbuf, + conn->proxy_state, + &reason); + if (ret == 1) + conn->proxy_state = PROXY_CONNECTED; + break; + + default: + log_err(LD_BUG, "Invalid proxy_state for reading, %d", + conn->proxy_state); + tor_fragile_assert(); + ret = -1; + break; + } + + log_debug(LD_NET, "leaving state %s", + connection_proxy_state_to_string(conn->proxy_state)); + + if (ret < 0) { + if (reason) { + log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d (%s)", + conn->address, conn->port, escaped(reason)); + tor_free(reason); + } else { + log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d", + conn->address, conn->port); + } + } else if (ret == 1) { + log_info(LD_NET, "Proxy Client: connection to %s:%d successful", + conn->address, conn->port); + } + + return ret; +} + /** * Launch any configured listener connections of type <b>type</b>. (A * listener is configured if <b>port_option</b> is non-zero. If any @@ -1506,8 +1862,8 @@ retry_all_listeners(smartlist_t *replaced_conns, replaced_conns, new_conns, 0, AF_INET)<0) return -1; - if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NatdListenAddress, - options->NatdPort, "127.0.0.1", + if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NATDListenAddress, + options->NATDPort, "127.0.0.1", replaced_conns, new_conns, 0, AF_INET)<0) return -1; @@ -1643,6 +1999,7 @@ connection_bucket_write_limit(connection_t *conn, time_t now) int base = connection_speaks_cells(conn) ? CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE; int priority = conn->type != CONN_TYPE_DIR; + int conn_bucket = (int)conn->outbuf_flushlen; int global_bucket = global_write_bucket; if (!connection_is_rate_limited(conn)) { @@ -1650,12 +2007,22 @@ connection_bucket_write_limit(connection_t *conn, time_t now) return conn->outbuf_flushlen; } + if (connection_speaks_cells(conn)) { + /* use the per-conn write limit if it's lower, but if it's less + * than zero just use zero */ + or_connection_t *or_conn = TO_OR_CONN(conn); + if (conn->state == OR_CONN_STATE_OPEN) + if (or_conn->write_bucket < conn_bucket) + conn_bucket = or_conn->write_bucket >= 0 ? + or_conn->write_bucket : 0; + } + if (connection_counts_as_relayed_traffic(conn, now) && global_relayed_write_bucket <= global_write_bucket) global_bucket = global_relayed_write_bucket; - return connection_bucket_round_robin(base, priority, global_bucket, - conn->outbuf_flushlen); + return connection_bucket_round_robin(base, priority, + global_bucket, conn_bucket); } /** Return 1 if the global write buckets are low enough that we @@ -1709,14 +2076,12 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority) return 0; } -/** We just read num_read and wrote num_written onto conn. - * Decrement buckets appropriately. */ +/** 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 (!connection_is_rate_limited(conn)) - return; /* local IPs are free */ 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", @@ -1728,10 +2093,24 @@ connection_buckets_decrement(connection_t *conn, time_t now, tor_fragile_assert(); } - if (num_read > 0) + /* Count bytes of answering direct and tunneled directory requests */ + if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) { + if (num_read > 0) + rep_hist_note_dir_bytes_read(num_read, now); + if (num_written > 0) + rep_hist_note_dir_bytes_written(num_written, now); + } + + if (!connection_is_rate_limited(conn)) + return; /* local IPs are free */ + if (num_read > 0) { rep_hist_note_bytes_read(num_read, now); - if (num_written > 0) + } + if (num_written > 0) { rep_hist_note_bytes_written(num_written, now); + } + if (conn->type == CONN_TYPE_EXIT) + rep_hist_note_exit_bytes(conn->port, num_written, num_read); if (connection_counts_as_relayed_traffic(conn, now)) { global_relayed_read_bucket -= (int)num_read; @@ -1739,8 +2118,10 @@ connection_buckets_decrement(connection_t *conn, time_t now, } global_read_bucket -= (int)num_read; global_write_bucket -= (int)num_written; - if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) + if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) { TO_OR_CONN(conn)->read_bucket -= (int)num_read; + TO_OR_CONN(conn)->write_bucket -= (int)num_written; + } } /** If we have exhausted our global buckets, or the buckets for conn, @@ -1779,12 +2160,10 @@ connection_consider_empty_write_buckets(connection_t *conn) } else if (connection_counts_as_relayed_traffic(conn, approx_time()) && global_relayed_write_bucket <= 0) { reason = "global relayed write bucket exhausted. Pausing."; -#if 0 } else if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN && TO_OR_CONN(conn)->write_bucket <= 0) { reason = "connection write bucket exhausted. Pausing."; -#endif } else return; /* all good, no need to stop it */ @@ -1880,14 +2259,19 @@ connection_bucket_refill(int seconds_elapsed, time_t now) { if (connection_speaks_cells(conn)) { or_connection_t *or_conn = TO_OR_CONN(conn); - if (connection_read_bucket_should_increase(or_conn)) { + 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, "or_conn->read_bucket"); - //log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, - // 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, + "or_conn->write_bucket"); } } @@ -1908,8 +2292,10 @@ connection_bucket_refill(int seconds_elapsed, time_t now) if (conn->write_blocked_on_bw == 1 && global_write_bucket > 0 /* and we're allowed to write */ && (!connection_counts_as_relayed_traffic(conn, now) || - global_relayed_write_bucket > 0)) { - /* even if we're relayed traffic */ + global_relayed_write_bucket > 0) /* even if it's relayed traffic */ + && (!connection_speaks_cells(conn) || + conn->state != OR_CONN_STATE_OPEN || + TO_OR_CONN(conn)->write_bucket > 0)) { LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET, "waking up conn (fd %d) for write", conn->s)); conn->write_blocked_on_bw = 0; @@ -1918,17 +2304,17 @@ connection_bucket_refill(int seconds_elapsed, time_t now) }); } -/** Is the receiver bucket for connection <b>conn</b> low enough that we +/** Is the <b>bucket</b> for connection <b>conn</b> low enough that we * should add another pile of tokens to it? */ static int -connection_read_bucket_should_increase(or_connection_t *conn) +connection_bucket_should_increase(int bucket, or_connection_t *conn) { tor_assert(conn); if (conn->_base.state != OR_CONN_STATE_OPEN) return 0; /* only open connections play the rate limiting game */ - if (conn->read_bucket >= conn->bandwidthburst) + if (bucket >= conn->bandwidthburst) return 0; return 1; @@ -1946,8 +2332,8 @@ connection_read_bucket_should_increase(or_connection_t *conn) * Mark the connection and return -1 if you want to close it, else * return 0. */ -int -connection_handle_read(connection_t *conn) +static int +connection_handle_read_impl(connection_t *conn) { int max_to_read=-1, try_to_read; size_t before, n_read = 0; @@ -1975,7 +2361,7 @@ connection_handle_read(connection_t *conn) return 0; } -loop_again: + loop_again: try_to_read = max_to_read; tor_assert(!conn->marked_for_close); @@ -2016,12 +2402,16 @@ loop_again: return -1; } if (conn->linked_conn) { - /* The other side's handle_write will never actually get called, so + /* The other side's handle_write() will never actually get called, so * we need to invoke the appropriate callbacks ourself. */ connection_t *linked = conn->linked_conn; if (n_read) { - /* Probably a no-op, but hey. */ + /* Probably a no-op, since linked conns typically don't count for + * bandwidth rate limiting. But do it anyway so we can keep stats + * accurately. Note that since we read the bytes from conn, and + * we're writing the bytes onto the linked connection, we count + * these as <i>written</i> bytes. */ connection_buckets_decrement(linked, approx_time(), 0, n_read); if (connection_flushed_some(linked) < 0) @@ -2033,7 +2423,7 @@ loop_again: if (!buf_datalen(linked->outbuf) && conn->active_on_link) connection_stop_reading_from_linked_conn(conn); } - /* If we hit the EOF, call connection_reached_eof. */ + /* If we hit the EOF, call connection_reached_eof(). */ if (!conn->marked_for_close && conn->inbuf_reached_eof && connection_reached_eof(conn) < 0) { @@ -2042,6 +2432,16 @@ loop_again: return 0; } +int +connection_handle_read(connection_t *conn) +{ + int res; + + tor_gettimeofday_cache_clear(); + res = connection_handle_read_impl(conn); + return res; +} + /** Pull in new bytes from conn-\>s or conn-\>linked_conn onto conn-\>inbuf, * either directly or via TLS. Reduce the token buckets by the number of bytes * read. @@ -2075,7 +2475,7 @@ connection_read_to_buf(connection_t *conn, int *max_to_read, int *socket_error) } if (connection_speaks_cells(conn) && - conn->state > OR_CONN_STATE_PROXY_READING) { + conn->state > OR_CONN_STATE_PROXY_HANDSHAKING) { int pending; or_connection_t *or_conn = TO_OR_CONN(conn); size_t initial_size; @@ -2243,8 +2643,8 @@ connection_outbuf_too_full(connection_t *conn) * Mark the connection and return -1 if you want to close it, else * return 0. */ -int -connection_handle_write(connection_t *conn, int force) +static int +connection_handle_write_impl(connection_t *conn, int force) { int e; socklen_t len=(socklen_t)sizeof(e); @@ -2259,7 +2659,7 @@ connection_handle_write(connection_t *conn, int force) return 0; /* do nothing */ if (conn->in_flushed_some) { - log_warn(LD_BUG, "called recursively from inside conn->in_flushed_some()"); + log_warn(LD_BUG, "called recursively from inside conn->in_flushed_some"); return 0; } @@ -2303,7 +2703,7 @@ connection_handle_write(connection_t *conn, int force) : connection_bucket_write_limit(conn, now); if (connection_speaks_cells(conn) && - conn->state > OR_CONN_STATE_PROXY_READING) { + conn->state > OR_CONN_STATE_PROXY_HANDSHAKING) { or_connection_t *or_conn = TO_OR_CONN(conn); if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING || conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) { @@ -2322,6 +2722,13 @@ connection_handle_write(connection_t *conn, int force) /* else open, or closing */ result = flush_buf_tls(or_conn->tls, conn->outbuf, max_to_write, &conn->outbuf_flushlen); + + /* If we just flushed the last bytes, check if this tunneled dir + * request is done. */ + if (buf_datalen(conn->outbuf) == 0 && conn->dirreq_id) + geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED, + DIRREQ_OR_CONN_BUFFER_FLUSHED); + switch (result) { CASE_TOR_TLS_ERROR_ANY: case TOR_TLS_CLOSE: @@ -2341,8 +2748,8 @@ connection_handle_write(connection_t *conn, int force) if (!connection_is_reading(conn)) { connection_stop_writing(conn); conn->write_blocked_on_bw = 1; - /* we'll start reading again when the next second arrives, - * and then also start writing again. + /* we'll start reading again when we get more tokens in our + * read bucket; then we'll start writing again too. */ } /* else no problem, we're already reading */ @@ -2404,6 +2811,15 @@ connection_handle_write(connection_t *conn, int force) return 0; } +int +connection_handle_write(connection_t *conn, int force) +{ + int res; + tor_gettimeofday_cache_clear(); + res = connection_handle_write_impl(conn, force); + return res; +} + /** 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 @@ -2577,13 +2993,11 @@ connection_get_by_type_state(int type, int state) /** Return a connection of type <b>type</b> that has rendquery equal * to <b>rendquery</b>, and that is not marked for close. If state - * is non-zero, conn must be of that state too. If rendversion is - * nonnegative, conn must be fetching that rendversion, too. + * is non-zero, conn must be of that state too. */ connection_t * connection_get_by_type_state_rendquery(int type, int state, - const char *rendquery, - int rendversion) + const char *rendquery) { smartlist_t *conns = get_connection_array(); @@ -2598,8 +3012,6 @@ connection_get_by_type_state_rendquery(int type, int state, (!state || state == conn->state)) { if (type == CONN_TYPE_DIR && TO_DIR_CONN(conn)->rend_data && - (rendversion < 0 || - rendversion == TO_DIR_CONN(conn)->rend_data->rend_desc_version) && !rend_cmp_service_ids(rendquery, TO_DIR_CONN(conn)->rend_data->onion_address)) return conn; @@ -2717,10 +3129,10 @@ alloc_http_authenticator(const char *authenticator) static void client_check_address_changed(int sock) { - uint32_t iface_ip, ip_out; + uint32_t iface_ip, ip_out; /* host order */ struct sockaddr_in out_addr; socklen_t out_addr_len = (socklen_t) sizeof(out_addr); - uint32_t *ip; + uint32_t *ip; /* host order */ if (!last_interface_ip) get_interface_address(LOG_INFO, &last_interface_ip); @@ -2734,7 +3146,7 @@ client_check_address_changed(int sock) return; } - /* Okay. If we've used this address previously, we're okay. */ + /* If we've used this address previously, we're okay. */ ip_out = ntohl(out_addr.sin_addr.s_addr); SMARTLIST_FOREACH(outgoing_addrs, uint32_t*, ip_ptr, if (*ip_ptr == ip_out) return; @@ -3033,7 +3445,7 @@ assert_connection_ok(connection_t *conn, time_t now) } // tor_assert(conn->addr && conn->port); tor_assert(conn->address); - if (conn->state > OR_CONN_STATE_PROXY_READING) + if (conn->state > OR_CONN_STATE_PROXY_HANDSHAKING) tor_assert(or_conn->tls); } diff --git a/src/or/connection.h b/src/or/connection.h new file mode 100644 index 0000000000..f38927e788 --- /dev/null +++ b/src/or/connection.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file connection.h + * \brief Header file for connection.c. + **/ + +#ifndef _TOR_CONNECTION_H +#define _TOR_CONNECTION_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); +control_connection_t *control_connection_new(int socket_family); +connection_t *connection_new(int type, int socket_family); + +void connection_link_connections(connection_t *conn_a, connection_t *conn_b); +void connection_free(connection_t *conn); +void connection_free_all(void); +void connection_about_to_close_connection(connection_t *conn); +void connection_close_immediate(connection_t *conn); +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_) + +void connection_expire_held_open(void); + +int connection_connect(connection_t *conn, const char *address, + const tor_addr_t *addr, + uint16_t port, int *socket_error); + +int connection_proxy_connect(connection_t *conn, int type); +int connection_read_proxy_handshake(connection_t *conn); + +int retry_all_listeners(smartlist_t *replaced_conns, + smartlist_t *new_conns); + +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); +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_wants_to_flush(connection_t *conn); +int connection_outbuf_too_full(connection_t *conn); +int connection_handle_write(connection_t *conn, int force); +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, + connection_t *conn); +static void connection_write_to_buf_zlib(const char *string, size_t len, + dir_connection_t *conn, int done); +static INLINE void +connection_write_to_buf(const char *string, size_t len, connection_t *conn) +{ + _connection_write_to_buf_impl(string, len, conn, 0); +} +static INLINE void +connection_write_to_buf_zlib(const char *string, size_t len, + dir_connection_t *conn, int done) +{ + _connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1); +} + +connection_t *connection_get_by_global_id(uint64_t id); + +connection_t *connection_get_by_type(int type); +connection_t *connection_get_by_type_purpose(int type, int purpose); +connection_t *connection_get_by_type_addr_port_purpose(int type, + const tor_addr_t *addr, + uint16_t port, int purpose); +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); + +#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR) +int connection_is_listener(connection_t *conn); +int connection_state_is_open(connection_t *conn); +int connection_state_is_connecting(connection_t *conn); + +char *alloc_http_authenticator(const char *authenticator); + +void assert_connection_ok(connection_t *conn, time_t now); +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); + +#endif + diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 9ecdf5c7a9..2bfa88e6a9 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -10,6 +10,28 @@ **/ #include "or.h" +#include "buffers.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "dns.h" +#include "dnsserv.h" +#include "dirserv.h" +#include "hibernate.h" +#include "main.h" +#include "policies.h" +#include "reasons.h" +#include "relay.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rendservice.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" #ifdef HAVE_LINUX_TYPES_H #include <linux/types.h> @@ -125,7 +147,7 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) return 0; case AP_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN: - if (connection_edge_package_raw_inbuf(conn, package_partial) < 0) { + 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; @@ -330,11 +352,13 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING); log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.", - escaped_safe_str(conn->address),conn->port, + escaped_safe_str(conn->address), conn->port, safe_str(fmt_addr(&conn->addr))); + rep_hist_note_exit_stream_opened(conn->port); + conn->state = EXIT_CONN_STATE_OPEN; - connection_watch_events(conn, EV_READ); /* stop writing, continue reading */ + connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ if (connection_wants_to_flush(conn)) /* in case there are any queued relay * cells */ connection_start_writing(conn); @@ -375,13 +399,16 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) static int compute_retry_timeout(edge_connection_t *conn) { + int timeout = get_options()->CircuitStreamTimeout; + if (timeout) /* if our config options override the default, use them */ + return timeout; if (conn->num_socks_retries < 2) /* try 0 and try 1 */ return 10; return 15; } /** Find all general-purpose AP streams waiting for a response that sent their - * begin/resolve cell >=15 seconds ago. Detach from their current circuit, and + * begin/resolve cell too long ago. Detach from their current circuit, and * mark their current circuit as unsuitable for new streams. Then call * connection_ap_handshake_attach_circuit() to attach to a new circuit (if * available) or launch a new one. @@ -423,7 +450,8 @@ connection_ap_expire_beginning(void) log_fn(severity, LD_APP, "Tried for %d seconds to get a connection to %s:%d. " "Giving up. (%s)", - seconds_since_born, safe_str(conn->socks_request->address), + 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); @@ -440,7 +468,7 @@ connection_ap_expire_beginning(void) 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(conn->socks_request->address)); + safe_str_client(conn->socks_request->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); continue; } @@ -450,7 +478,7 @@ connection_ap_expire_beginning(void) "Rend stream is %d seconds late. Giving up on address" " '%s.onion'.", seconds_idle, - safe_str(conn->socks_request->address)); + safe_str_client(conn->socks_request->address)); connection_edge_end(conn, END_STREAM_REASON_TIMEOUT); connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); } @@ -460,7 +488,8 @@ connection_ap_expire_beginning(void) log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP, "We tried for %d seconds to connect to '%s' using exit '%s'." " Retrying on a new circuit.", - seconds_idle, safe_str(conn->socks_request->address), + seconds_idle, + safe_str_client(conn->socks_request->address), conn->cpath_layer ? conn->cpath_layer->extend_info->nickname : "*unnamed*"); /* send an end down the circuit */ @@ -571,14 +600,14 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info) !edge_conn->chosen_exit_retries) continue; r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0); - r2 = router_get_by_nickname(info->nickname, 0); + r2 = router_get_by_digest(info->identity_digest); if (!r1 || !r2 || r1 != r2) continue; tor_assert(edge_conn->socks_request); if (edge_conn->chosen_exit_optional) { log_info(LD_APP, "Giving up on enclave exit '%s' for destination %s.", - safe_str(edge_conn->chosen_exit_name), - escaped_safe_str(edge_conn->socks_request->address)); + 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 */ /* if this port is dangerous, warn or reject it now that we don't @@ -683,7 +712,11 @@ addressmap_init(void) static void addressmap_ent_free(void *_ent) { - addressmap_entry_t *ent = _ent; + addressmap_entry_t *ent; + if (!_ent) + return; + + ent = _ent; tor_free(ent->new_address); tor_free(ent); } @@ -692,7 +725,11 @@ addressmap_ent_free(void *_ent) static void addressmap_virtaddress_ent_free(void *_ent) { - virtaddress_entry_t *ent = _ent; + virtaddress_entry_t *ent; + if (!_ent) + return; + + ent = _ent; tor_free(ent->ipv4_address); tor_free(ent->hostname_address); tor_free(ent); @@ -782,14 +819,11 @@ addressmap_clean(time_t now) void addressmap_free_all(void) { - if (addressmap) { - strmap_free(addressmap, addressmap_ent_free); - addressmap = NULL; - } - if (virtaddress_reversemap) { - strmap_free(virtaddress_reversemap, addressmap_virtaddress_ent_free); - virtaddress_reversemap = NULL; - } + strmap_free(addressmap, addressmap_ent_free); + addressmap = NULL; + + strmap_free(virtaddress_reversemap, addressmap_virtaddress_ent_free); + virtaddress_reversemap = NULL; } /** Look at address, and rewrite it until it doesn't want any @@ -816,9 +850,9 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) return (rewrites > 0); /* done, no rewrite needed */ } - cp = tor_strdup(escaped_safe_str(ent->new_address)); + cp = tor_strdup(escaped_safe_str_client(ent->new_address)); log_info(LD_APP, "Addressmap: rewriting %s to %s", - escaped_safe_str(address), cp); + escaped_safe_str_client(address), cp); if (ent->expires > 1 && ent->expires < expires) expires = ent->expires; tor_free(cp); @@ -826,7 +860,7 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) } log_warn(LD_CONFIG, "Loop detected: we've rewritten %s 16 times! Using it as-is.", - escaped_safe_str(address)); + escaped_safe_str_client(address)); /* it's fine to rewrite a rewrite, but don't loop forever */ if (expires_out) *expires_out = TIME_MAX; @@ -848,9 +882,9 @@ addressmap_rewrite_reverse(char *address, size_t maxlen, time_t *expires_out) tor_snprintf(s, len, "REVERSE[%s]", address); ent = strmap_get(addressmap, s); if (ent) { - cp = tor_strdup(escaped_safe_str(ent->new_address)); + cp = tor_strdup(escaped_safe_str_client(ent->new_address)); log_info(LD_APP, "Rewrote reverse lookup %s -> %s", - escaped_safe_str(s), cp); + escaped_safe_str_client(s), cp); tor_free(cp); strlcpy(address, ent->new_address, maxlen); r = 1; @@ -912,7 +946,9 @@ addressmap_register(const char *address, char *new_address, time_t expires, if (expires > 1) { log_info(LD_APP,"Temporary addressmap ('%s' to '%s') not performed, " "since it's already mapped to '%s'", - safe_str(address), safe_str(new_address), safe_str(ent->new_address)); + safe_str_client(address), + safe_str_client(new_address), + safe_str_client(ent->new_address)); tor_free(new_address); return; } @@ -931,7 +967,8 @@ addressmap_register(const char *address, char *new_address, time_t expires, ent->source = source; log_info(LD_CONFIG, "Addressmap: (re)mapped '%s' to '%s'", - safe_str(address), safe_str(ent->new_address)); + safe_str_client(address), + safe_str_client(ent->new_address)); control_event_address_mapped(address, ent->new_address, expires, NULL); } @@ -951,7 +988,8 @@ client_dns_incr_failures(const char *address) if (ent->num_resolve_failures < SHORT_MAX) ++ent->num_resolve_failures; /* don't overflow */ log_info(LD_APP, "Address %s now has %d resolve failures.", - safe_str(address), ent->num_resolve_failures); + safe_str_client(address), + ent->num_resolve_failures); return ent->num_resolve_failures; } @@ -1230,8 +1268,10 @@ addressmap_register_virtual_address(int type, char *new_address) log_warn(LD_BUG, "Internal confusion: I thought that '%s' was mapped to by " "'%s', but '%s' really maps to '%s'. This is a harmless bug.", - safe_str(new_address), safe_str(*addrp), safe_str(*addrp), - ent?safe_str(ent->new_address):"(nothing)"); + safe_str_client(new_address), + safe_str_client(*addrp), + safe_str_client(*addrp), + ent?safe_str_client(ent->new_address):"(nothing)"); } tor_free(*addrp); @@ -1252,7 +1292,8 @@ addressmap_register_virtual_address(int type, char *new_address) (type == RESOLVED_TYPE_IPV4) ? vent->ipv4_address : vent->hostname_address)); log_info(LD_APP, "Map from %s to %s okay.", - safe_str(*addrp),safe_str(new_address)); + safe_str_client(*addrp), + safe_str_client(new_address)); } #endif @@ -1367,6 +1408,26 @@ consider_plaintext_ports(edge_connection_t *conn, uint16_t port) * different one? */ #define TRACKHOSTEXITS_RETRIES 5 +/** Call connection_ap_handshake_rewrite_and_attach() unless a controller + * asked us to leave streams unattached. Return 0 in that case. + * + * See connection_ap_handshake_rewrite_and_attach()'s + * documentation for arguments and return value. + */ +int +connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn, + origin_circuit_t *circ, + crypt_path_t *cpath) +{ + or_options_t *options = get_options(); + + if (options->LeaveStreamsUnattached) { + conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; + return 0; + } + return connection_ap_handshake_rewrite_and_attach(conn, circ, cpath); +} + /** Connection <b>conn</b> just finished its socks handshake, or the * controller asked us to take care of it. If <b>circ</b> is defined, * then that's where we'll want to attach it. Otherwise we have to @@ -1400,7 +1461,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, tor_strlower(socks->address); /* normalize it */ strlcpy(orig_address, socks->address, sizeof(orig_address)); log_debug(LD_APP,"Client asked for %s:%d", - safe_str(socks->address), + safe_str_client(socks->address), socks->port); if (socks->command == SOCKS_COMMAND_RESOLVE && @@ -1417,7 +1478,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, RESOLVED_TYPE_IPV4, tor_strdup(socks->address)); tor_assert(new_addr); log_info(LD_APP, "Automapping %s to %s", - escaped_safe_str(socks->address), safe_str(new_addr)); + escaped_safe_str_client(socks->address), + safe_str_client(new_addr)); strlcpy(socks->address, new_addr, sizeof(socks->address)); } } @@ -1474,7 +1536,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, * information. */ log_warn(LD_APP,"Missing mapping for virtual address '%s'. Refusing.", - socks->address); /* don't safe_str() this yet. */ + safe_str_client(socks->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_INTERNAL); return -1; } @@ -1482,11 +1544,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, /* Parse the address provided by SOCKS. Modify it in-place if it * specifies a hidden-service (.onion) or particular exit node (.exit). */ - addresstype = parse_extended_hostname(socks->address); + addresstype = parse_extended_hostname(socks->address, + remapped_to_exit || options->AllowDotExit); if (addresstype == BAD_HOSTNAME) { log_warn(LD_APP, "Invalid onion hostname %s; rejecting", - safe_str(socks->address)); + safe_str_client(socks->address)); control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s", escaped(socks->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); @@ -1495,7 +1558,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, if (addresstype == EXIT_HOSTNAME) { /* foo.exit -- modify conn->chosen_exit_node to specify the exit - * node, and conn->address to hold only the address portion.*/ + * node, and conn->address to hold only the address portion. */ char *s = strrchr(socks->address,'.'); tor_assert(!automap); if (s) { @@ -1506,7 +1569,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, *s = 0; } else { log_warn(LD_APP,"Malformed exit address '%s.exit'. Refusing.", - safe_str(socks->address)); + safe_str_client(socks->address)); control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s", escaped(socks->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); @@ -1522,7 +1585,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, } else { log_warn(LD_APP, "Unrecognized server in exit address '%s.exit'. Refusing.", - safe_str(socks->address)); + safe_str_client(socks->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return -1; } @@ -1536,7 +1599,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, escaped(socks->address)); log_warn(LD_APP, "Destination '%s' seems to be an invalid hostname. Failing.", - safe_str(socks->address)); + safe_str_client(socks->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return -1; } @@ -1545,18 +1608,6 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, uint32_t answer; struct in_addr in; /* Reply to resolves immediately if we can. */ - if (strlen(socks->address) > RELAY_PAYLOAD_SIZE) { - log_warn(LD_APP,"Address to be resolved is too large. Failing."); - control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s", - escaped(socks->address)); - connection_ap_handshake_socks_resolved(conn, - RESOLVED_TYPE_ERROR_TRANSIENT, - 0,NULL,-1,TIME_MAX); - connection_mark_unattached_ap(conn, - END_STREAM_REASON_SOCKSPROTOCOL | - END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); - return -1; - } if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */ /* leave it in network order */ answer = in.s_addr; @@ -1587,7 +1638,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, if (r) { log_info(LD_APP, "Redirecting address %s to exit at enclave router %s", - safe_str(socks->address), r->nickname); + safe_str_client(socks->address), r->nickname); /* use the hex digest, not nickname, in case there are two routers with this nickname */ conn->chosen_exit_name = @@ -1651,12 +1702,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, strlcpy(conn->rend_data->onion_address, socks->address, sizeof(conn->rend_data->onion_address)); log_info(LD_REND,"Got a hidden service request for ID '%s'", - safe_str(conn->rend_data->onion_address)); + safe_str_client(conn->rend_data->onion_address)); /* see if we already have it cached */ r = rend_cache_lookup_entry(conn->rend_data->onion_address, -1, &entry); if (r<0) { log_warn(LD_BUG,"Invalid service name '%s'", - safe_str(conn->rend_data->onion_address)); + safe_str_client(conn->rend_data->onion_address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return -1; } @@ -1678,32 +1729,15 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, if (r==0) { conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; log_info(LD_REND, "Unknown descriptor %s. Fetching.", - safe_str(conn->rend_data->onion_address)); - /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever - * arrives first. Exception: When using client authorization, only - * fetch v2 descriptors.*/ + safe_str_client(conn->rend_data->onion_address)); rend_client_refetch_v2_renddesc(conn->rend_data); - if (conn->rend_data->auth_type == REND_NO_AUTH) - rend_client_refetch_renddesc(conn->rend_data->onion_address); } else { /* r > 0 */ - if (now - entry->received < NUM_SECONDS_BEFORE_HS_REFETCH) { - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; - log_info(LD_REND, "Descriptor is here and fresh enough. Great."); - if (connection_ap_handshake_attach_circuit(conn) < 0) { - if (!conn->_base.marked_for_close) - connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); - return -1; - } - } else { - conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; - log_info(LD_REND, "Stale descriptor %s. Re-fetching.", - safe_str(conn->rend_data->onion_address)); - /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever - * arrives first. Exception: When using client authorization, only - * fetch v2 descriptors.*/ - rend_client_refetch_v2_renddesc(conn->rend_data); - if (conn->rend_data->auth_type == REND_NO_AUTH) - rend_client_refetch_renddesc(conn->rend_data->onion_address); + conn->_base.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) + connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); + return -1; } } return 0; @@ -1891,24 +1925,12 @@ connection_ap_handshake_process_socks(edge_connection_t *conn) return -1; } /* else socks handshake is done, continue processing */ - if (hostname_is_noconnect_address(socks->address)) - { - control_event_stream_status(conn, STREAM_EVENT_NEW, 0); - control_event_stream_status(conn, STREAM_EVENT_CLOSED, 0); - connection_mark_unattached_ap(conn, END_STREAM_REASON_DONE); - return -1; - } - if (SOCKS_COMMAND_IS_CONNECT(socks->command)) control_event_stream_status(conn, STREAM_EVENT_NEW, 0); else control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE, 0); - if (options->LeaveStreamsUnattached) { - conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; - return 0; - } - return connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); + return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); } /** connection_init_accepted_conn() found a new trans AP conn. @@ -1922,7 +1944,6 @@ int connection_ap_process_transparent(edge_connection_t *conn) { socks_request_t *socks; - or_options_t *options = get_options(); tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_AP); @@ -1946,11 +1967,7 @@ connection_ap_process_transparent(edge_connection_t *conn) control_event_stream_status(conn, STREAM_EVENT_NEW, 0); - if (options->LeaveStreamsUnattached) { - conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; - return 0; - } - return connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); + return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); } /** connection_edge_process_inbuf() found a conn in state natd_wait. See if @@ -1971,7 +1988,6 @@ connection_ap_process_natd(edge_connection_t *conn) size_t tlen = 30; int err, port_ok; socks_request_t *socks; - or_options_t *options = get_options(); tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_AP); @@ -1987,13 +2003,13 @@ connection_ap_process_natd(edge_connection_t *conn) if (err == 0) return 0; if (err < 0) { - log_warn(LD_APP,"Natd handshake failed (DEST too long). Closing"); + log_warn(LD_APP,"NATD handshake failed (DEST too long). Closing"); connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST); return -1; } if (strcmpstart(tmp_buf, "[DEST ")) { - log_warn(LD_APP,"Natd handshake was ill-formed; closing. The client " + log_warn(LD_APP,"NATD handshake was ill-formed; closing. The client " "said: %s", escaped(tmp_buf)); connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST); @@ -2002,7 +2018,7 @@ connection_ap_process_natd(edge_connection_t *conn) daddr = tbuf = &tmp_buf[0] + 6; /* after end of "[DEST " */ if (!(tbuf = strchr(tbuf, ' '))) { - log_warn(LD_APP,"Natd handshake was ill-formed; closing. The client " + log_warn(LD_APP,"NATD handshake was ill-formed; closing. The client " "said: %s", escaped(tmp_buf)); connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST); @@ -2016,7 +2032,7 @@ connection_ap_process_natd(edge_connection_t *conn) socks->port = (uint16_t) tor_parse_long(tbuf, 10, 1, 65535, &port_ok, &daddr); if (!port_ok) { - log_warn(LD_APP,"Natd handshake failed; port %s is ill-formed or out " + log_warn(LD_APP,"NATD handshake failed; port %s is ill-formed or out " "of range.", escaped(tbuf)); connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST); return -1; @@ -2027,13 +2043,9 @@ connection_ap_process_natd(edge_connection_t *conn) control_event_stream_status(conn, STREAM_EVENT_NEW, 0); - if (options->LeaveStreamsUnattached) { - conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; - return 0; - } conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; - return connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); + return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); } /** Iterate over the two bytes of stream_id until we get one that is not @@ -2046,7 +2058,7 @@ get_unique_stream_id_by_circ(origin_circuit_t *circ) streamid_t test_stream_id; uint32_t attempts=0; -again: + again: test_stream_id = circ->next_stream_id++; if (++attempts > 1<<16) { /* Make sure we don't loop forever if all stream_id's are used. */ @@ -2162,7 +2174,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) r = tor_addr_parse_reverse_lookup_name(&addr, a, AF_INET, 1); if (r <= 0) { log_warn(LD_APP, "Rejecting ill-formed reverse lookup of %s", - safe_str(a)); + safe_str_client(a)); connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); return -1; } @@ -2170,7 +2182,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) r = tor_addr_to_reverse_lookup_name(inaddr_buf, sizeof(inaddr_buf), &addr); if (r < 0) { log_warn(LD_BUG, "Couldn't generate reverse lookup hostname of %s", - safe_str(a)); + safe_str_client(a)); connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); return -1; } @@ -2180,12 +2192,6 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) tor_assert(payload_len <= (int)sizeof(inaddr_buf)); } - if (payload_len > RELAY_PAYLOAD_SIZE) { - /* This should be impossible: we don't accept addresses this big. */ - connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); - return -1; - } - log_debug(LD_APP, "Sending relay cell to begin stream %d.", ap_conn->stream_id); @@ -2217,7 +2223,8 @@ connection_ap_make_link(char *address, uint16_t port, edge_connection_t *conn; log_info(LD_APP,"Making internal %s tunnel to %s:%d ...", - want_onehop ? "direct" : "anonymized" , safe_str(address),port); + 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. */ @@ -2483,6 +2490,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(); assert_circuit_ok(circ); if (!CIRCUIT_IS_ORIGIN(circ)) @@ -2497,7 +2505,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) * that we have a stream connected to a circuit, and we don't connect to a * circuit until we have a pending/successful resolve. */ - if (!server_mode(get_options()) && + if (!server_mode(options) && circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay begin cell at non-server. Closing."); @@ -2531,21 +2539,30 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) tor_free(address); return 0; } - if (or_circ && or_circ->is_first_hop && - !get_options()->AllowSingleHopExits) { + if (or_circ && or_circ->p_conn && !options->AllowSingleHopExits && + (or_circ->is_first_hop || + (!connection_or_digest_is_known_relay( + or_circ->p_conn->identity_digest) && + should_refuse_unknown_exits(options)))) { /* Don't let clients use us as a single-hop proxy, unless the user - * has explicitly allowed that in the config. It attracts attackers + * has explicitly allowed that in the config. It attracts attackers * and users who'd be better off with, well, single-hop proxies. */ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Attempt to open a stream on first hop of circuit. Closing."); + "Attempt by %s to open a stream %s. Closing.", + safe_str(or_circ->p_conn->_base.address), + or_circ->is_first_hop ? "on first hop of circuit" : + "from unknown relay"); relay_send_end_cell_from_edge(rh.stream_id, circ, - END_STREAM_REASON_TORPROTOCOL, NULL); + or_circ->is_first_hop ? + END_STREAM_REASON_TORPROTOCOL : + END_STREAM_REASON_MISC, + NULL); tor_free(address); return 0; } } else if (rh.command == RELAY_COMMAND_BEGIN_DIR) { - if (!directory_permits_begindir_requests(get_options()) || + if (!directory_permits_begindir_requests(options) || circ->purpose != CIRCUIT_PURPOSE_OR) { relay_send_end_cell_from_edge(rh.stream_id, circ, END_STREAM_REASON_NOTDIRECTORY, NULL); @@ -2571,6 +2588,11 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) log_debug(LD_EXIT,"Creating new exit connection."); n_stream = edge_connection_new(CONN_TYPE_EXIT, AF_INET); + + /* Remember the tunneled request ID in the new edge connection, so that + * we can measure download times. */ + TO_CONN(n_stream)->dirreq_id = circ->dirreq_id; + n_stream->_base.purpose = EXIT_PURPOSE_CONNECT; n_stream->stream_id = rh.stream_id; @@ -2601,7 +2623,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) log_debug(LD_REND,"Finished assigning addr/port"); n_stream->cpath_layer = origin_circ->cpath->prev; /* link it */ - /* add it into the linked list of n_streams on this circuit */ + /* add it into the linked list of p_streams on this circuit */ n_stream->next_stream = origin_circ->p_streams; n_stream->on_circuit = circ; origin_circ->p_streams = n_stream; @@ -2628,7 +2650,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) if (rh.command == RELAY_COMMAND_BEGIN_DIR) { tor_assert(or_circ); if (or_circ->p_conn && !tor_addr_is_null(&or_circ->p_conn->real_addr)) - tor_addr_assign(&n_stream->_base.addr, &or_circ->p_conn->real_addr); + tor_addr_copy(&n_stream->_base.addr, &or_circ->p_conn->real_addr); return connection_exit_connect_dir(n_stream); } @@ -2721,7 +2743,7 @@ connection_exit_connect(edge_connection_t *edge_conn) if (!connection_edge_is_rendezvous_stream(edge_conn) && router_compare_to_my_exit_policy(edge_conn)) { log_info(LD_EXIT,"%s:%d failed exit policy. Closing.", - escaped_safe_str(conn->address), conn->port); + escaped_safe_str_client(conn->address), conn->port); connection_edge_end(edge_conn, END_STREAM_REASON_EXITPOLICY); circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn); connection_free(conn); @@ -2743,7 +2765,7 @@ connection_exit_connect(edge_connection_t *edge_conn) case 0: conn->state = EXIT_CONN_STATE_CONNECTING; - connection_watch_events(conn, EV_WRITE | EV_READ); + connection_watch_events(conn, READ_EVENT | WRITE_EVENT); /* writable indicates finish; * readable/error indicates broken link in windows-land. */ return; @@ -2756,7 +2778,7 @@ connection_exit_connect(edge_connection_t *edge_conn) log_warn(LD_BUG,"newly connected conn had data waiting!"); // connection_start_writing(conn); } - connection_watch_events(conn, EV_READ); + connection_watch_events(conn, READ_EVENT); /* also, deliver a 'connected' cell back through the circuit. */ if (connection_edge_is_rendezvous_stream(edge_conn)) { @@ -2803,13 +2825,17 @@ connection_exit_connect_dir(edge_connection_t *exitconn) dirconn = dir_connection_new(AF_INET); - tor_addr_assign(&dirconn->_base.addr, &exitconn->_base.addr); + tor_addr_copy(&dirconn->_base.addr, &exitconn->_base.addr); dirconn->_base.port = 0; dirconn->_base.address = tor_strdup(exitconn->_base.address); dirconn->_base.type = CONN_TYPE_DIR; dirconn->_base.purpose = DIR_PURPOSE_SERVER; dirconn->_base.state = DIR_CONN_STATE_SERVER_COMMAND_WAIT; + /* Note that the new dir conn belongs to the same tunneled request as + * the edge conn, so that we can measure download times. */ + TO_CONN(dirconn)->dirreq_id = TO_CONN(exitconn)->dirreq_id; + connection_link_connections(TO_CONN(dirconn), TO_CONN(exitconn)); if (connection_add(TO_CONN(exitconn))<0) { @@ -2860,10 +2886,16 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn) * to exit from it, or 0 if it probably will not allow it. * (We might be uncertain if conn's destination address has not yet been * resolved.) + * + * If <b>excluded_means_no</b> is 1 and Exclude*Nodes is set and excludes + * this relay, return 0. */ int -connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) +connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit, + int excluded_means_no) { + or_options_t *options = get_options(); + tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_AP); tor_assert(conn->socks_request); @@ -2909,20 +2941,35 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy)) return 0; } + if (options->_ExcludeExitNodesUnion && + (options->StrictNodes || excluded_means_no) && + routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) { + /* If we are trying to avoid this node as exit, and we have StrictNodes + * set, then this is not a suitable exit. Refuse it. + * + * If we don't have StrictNodes set, then this function gets called in + * two contexts. First, we've got a circuit open and we want to know + * whether we can use it. In that case, we somehow built this circuit + * despite having the last hop in ExcludeExitNodes, so we should be + * willing to use it. Second, we are evaluating whether this is an + * acceptable exit for a new circuit. In that case, skip it. */ + return 0; + } + return 1; } /** If address is of the form "y.onion" with a well-formed handle y: * Put a NUL after y, lower-case it, and return ONION_HOSTNAME. * - * If address is of the form "y.exit": + * If address is of the form "y.exit" and <b>allowdotexit</b> is true: * Put a NUL after y and return EXIT_HOSTNAME. * * Otherwise: * Return NORMAL_HOSTNAME and change nothing. */ hostname_type_t -parse_extended_hostname(char *address) +parse_extended_hostname(char *address, int allowdotexit) { char *s; char query[REND_SERVICE_ID_LEN_BASE32+1]; @@ -2931,8 +2978,16 @@ parse_extended_hostname(char *address) if (!s) return NORMAL_HOSTNAME; /* no dot, thus normal */ if (!strcmp(s+1,"exit")) { - *s = 0; /* NUL-terminate it */ - return EXIT_HOSTNAME; /* .exit */ + if (allowdotexit) { + *s = 0; /* NUL-terminate it */ + return EXIT_HOSTNAME; /* .exit */ + } else { + log_warn(LD_APP, "The \".exit\" notation is disabled in Tor due to " + "security risks. Set AllowDotExit in your torrc to enable " + "it."); + /* FFFF send a controller event too to notify Vidalia users */ + return BAD_HOSTNAME; + } } if (strcmp(s+1,"onion")) return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */ @@ -2945,17 +3000,9 @@ parse_extended_hostname(char *address) if (rend_valid_service_id(query)) { return ONION_HOSTNAME; /* success */ } -failed: + failed: /* otherwise, return to previous state and return 0 */ *s = '.'; return BAD_HOSTNAME; } -/** Check if the address is of the form "y.noconnect" - */ -int -hostname_is_noconnect_address(const char *address) -{ - return ! strcasecmpend(address, ".noconnect"); -} - diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h new file mode 100644 index 0000000000..cca82022c3 --- /dev/null +++ b/src/or/connection_edge.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file connection_edge.h + * \brief Header file for connection_edge.c. + **/ + +#ifndef _TOR_CONNECTION_EDGE_H +#define _TOR_CONNECTION_EDGE_H + +#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, + int line, const char *file); +int connection_edge_reached_eof(edge_connection_t *conn); +int connection_edge_process_inbuf(edge_connection_t *conn, + int package_partial); +int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn); +int connection_edge_end(edge_connection_t *conn, uint8_t reason); +int connection_edge_end_errno(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); + +edge_connection_t *connection_ap_make_link(char *address, uint16_t port, + const char *digest, + int use_begindir, int want_onehop); +void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, + size_t replylen, + int endreason); +void connection_ap_handshake_socks_resolved(edge_connection_t *conn, + int answer_type, + size_t answer_len, + const uint8_t *answer, + int ttl, + time_t expires); + +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 excluded_means_no); +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, + origin_circuit_t *circ, + int reason); +int connection_ap_process_transparent(edge_connection_t *conn); + +int address_is_invalid_destination(const char *address, int client); + +void addressmap_init(void); +void addressmap_clean(time_t now); +void addressmap_clear_configured(void); +void addressmap_clear_transient(void); +void addressmap_free_all(void); +int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out); +int addressmap_have_mapping(const char *address, int update_timeout); + +void addressmap_register(const char *address, char *new_address, + time_t expires, addressmap_entry_source_t source); +int parse_virtual_addr_network(const char *val, int validate_only, + char **msg); +int client_dns_incr_failures(const char *address); +void client_dns_clear_failures(const char *address); +void client_dns_set_addressmap(const char *address, uint32_t val, + const char *exitname, int ttl); +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, + origin_circuit_t *circ, + crypt_path_t *cpath); +int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, + origin_circuit_t *circ, + crypt_path_t *cpath); + +/** Possible return values for parse_extended_hostname. */ +typedef enum hostname_type_t { + NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME, BAD_HOSTNAME +} hostname_type_t; +hostname_type_t parse_extended_hostname(char *address, int allowdotexit); + +#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) +int get_pf_socket(void); +#endif + +#endif + diff --git a/src/or/connection_or.c b/src/or/connection_or.c index ab0d561962..45266a99b1 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -11,6 +11,22 @@ **/ #include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "command.h" +#include "config.h" +#include "connection.h" +#include "connection_or.h" +#include "control.h" +#include "dirserv.h" +#include "geoip.h" +#include "main.h" +#include "networkstatus.h" +#include "reasons.h" +#include "relay.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" static int connection_tls_finish_handshake(or_connection_t *conn); static int connection_or_process_cells_from_inbuf(or_connection_t *conn); @@ -80,10 +96,8 @@ connection_or_clear_identity_map(void) } }); - if (orconn_identity_map) { - digestmap_free(orconn_identity_map, NULL); - orconn_identity_map = NULL; - } + digestmap_free(orconn_identity_map, NULL); + orconn_identity_map = NULL; } /** Change conn->identity_digest to digest, and add conn into @@ -133,7 +147,7 @@ void cell_pack(packed_cell_t *dst, const cell_t *src) { char *dest = dst->body; - *(uint16_t*)dest = htons(src->circ_id); + set_uint16(dest, htons(src->circ_id)); *(uint8_t*)(dest+2) = src->command; memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE); } @@ -144,7 +158,7 @@ cell_pack(packed_cell_t *dst, const cell_t *src) static void cell_unpack(cell_t *dest, const char *src) { - dest->circ_id = ntohs(*(uint16_t*)(src)); + dest->circ_id = ntohs(get_uint16(src)); dest->command = *(uint8_t*)(src+2); memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE); } @@ -187,66 +201,6 @@ connection_or_reached_eof(or_connection_t *conn) return 0; } -/** Read conn's inbuf. If the http response from the proxy is all - * here, make sure it's good news, and begin the tls handshake. If - * it's bad news, close the connection and return -1. Else return 0 - * and hope for better luck next time. - */ -static int -connection_or_read_proxy_response(or_connection_t *or_conn) -{ - char *headers; - char *reason=NULL; - int status_code; - time_t date_header; - connection_t *conn = TO_CONN(or_conn); - - switch (fetch_from_buf_http(conn->inbuf, - &headers, MAX_HEADERS_SIZE, - NULL, NULL, 10000, 0)) { - case -1: /* overflow */ - log_warn(LD_PROTOCOL, - "Your https proxy sent back an oversized response. Closing."); - return -1; - case 0: - log_info(LD_OR,"https proxy response not all here yet. Waiting."); - return 0; - /* case 1, fall through */ - } - - if (parse_http_response(headers, &status_code, &date_header, - NULL, &reason) < 0) { - log_warn(LD_OR, - "Unparseable headers from proxy (connecting to '%s'). Closing.", - conn->address); - tor_free(headers); - return -1; - } - if (!reason) reason = tor_strdup("[no reason given]"); - - if (status_code == 200) { - log_info(LD_OR, - "HTTPS connect to '%s' successful! (200 %s) Starting TLS.", - conn->address, escaped(reason)); - tor_free(reason); - if (connection_tls_start_handshake(or_conn, 0) < 0) { - /* TLS handshaking error of some kind. */ - connection_mark_for_close(conn); - - return -1; - } - return 0; - } - /* else, bad news on the status code */ - log_warn(LD_OR, - "The https proxy sent back an unexpected status code %d (%s). " - "Closing.", - status_code, escaped(reason)); - tor_free(reason); - connection_mark_for_close(conn); - return -1; -} - /** Handle any new bytes that have come in on connection <b>conn</b>. * If conn is in 'open' state, hand it to * connection_or_process_cells_from_inbuf() @@ -255,11 +209,24 @@ connection_or_read_proxy_response(or_connection_t *or_conn) int connection_or_process_inbuf(or_connection_t *conn) { + int ret; tor_assert(conn); switch (conn->_base.state) { - case OR_CONN_STATE_PROXY_READING: - return connection_or_read_proxy_response(conn); + case OR_CONN_STATE_PROXY_HANDSHAKING: + ret = connection_read_proxy_handshake(TO_CONN(conn)); + + /* start TLS after handshake completion, or deal with error */ + if (ret == 1) { + tor_assert(TO_CONN(conn)->proxy_state == PROXY_CONNECTED); + if (connection_tls_start_handshake(conn, 0) < 0) + ret = -1; + } + if (ret < 0) { + connection_mark_for_close(TO_CONN(conn)); + } + + return ret; case OR_CONN_STATE_OPEN: case OR_CONN_STATE_OR_HANDSHAKING: return connection_or_process_cells_from_inbuf(conn); @@ -285,8 +252,7 @@ connection_or_flushed_some(or_connection_t *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) { - ssize_t n = (OR_CONN_HIGHWATER - datalen + CELL_NETWORK_SIZE-1) - / CELL_NETWORK_SIZE; + ssize_t n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, CELL_NETWORK_SIZE); time_t now = approx_time(); while (conn->active_circuits && n > 0) { int flushed; @@ -312,11 +278,7 @@ connection_or_finished_flushing(or_connection_t *conn) assert_connection_ok(TO_CONN(conn),0); switch (conn->_base.state) { - case OR_CONN_STATE_PROXY_FLUSHING: - log_debug(LD_OR,"finished sending CONNECT to proxy."); - conn->_base.state = OR_CONN_STATE_PROXY_READING; - connection_stop_writing(TO_CONN(conn)); - break; + case OR_CONN_STATE_PROXY_HANDSHAKING: case OR_CONN_STATE_OPEN: case OR_CONN_STATE_OR_HANDSHAKING: connection_stop_writing(TO_CONN(conn)); @@ -334,37 +296,34 @@ connection_or_finished_flushing(or_connection_t *conn) int connection_or_finished_connecting(or_connection_t *or_conn) { + int proxy_type; connection_t *conn; tor_assert(or_conn); conn = TO_CONN(or_conn); tor_assert(conn->state == OR_CONN_STATE_CONNECTING); - log_debug(LD_OR,"OR connect() to router at %s:%u finished.", + log_debug(LD_HANDSHAKE,"OR connect() to router at %s:%u finished.", conn->address,conn->port); control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); - if (get_options()->HttpsProxy) { - char buf[1024]; - char *base64_authenticator=NULL; - const char *authenticator = get_options()->HttpsProxyAuthenticator; + proxy_type = PROXY_NONE; - if (authenticator) { - base64_authenticator = alloc_http_authenticator(authenticator); - if (!base64_authenticator) - log_warn(LD_OR, "Encoding https authenticator failed"); - } - if (base64_authenticator) { - tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n" - "Proxy-Authorization: Basic %s\r\n\r\n", - fmt_addr(&conn->addr), - conn->port, base64_authenticator); - tor_free(base64_authenticator); - } else { - tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n", - fmt_addr(&conn->addr), conn->port); + 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) { + connection_mark_for_close(conn); + return -1; } - connection_write_to_buf(buf, strlen(buf), conn); - conn->state = OR_CONN_STATE_PROXY_FLUSHING; + + connection_start_reading(conn); + conn->state = OR_CONN_STATE_PROXY_HANDSHAKING; return 0; } @@ -376,6 +335,74 @@ connection_or_finished_connecting(or_connection_t *or_conn) return 0; } +/** Return 1 if identity digest <b>id_digest</b> is known to be a + * currently or recently running relay. Otherwise return 0. */ +int +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)) + return 1; /* Not in the consensus, but we have a descriptor for + * it. Probably it was in a recent consensus. "Yes". */ + return 0; +} + +/** Set the per-conn read and write limits for <b>conn</b>. If it's a known + * relay, we will rely on the global read and write buckets, so give it + * per-conn limits that are big enough they'll never matter. But if it's + * not a known relay, first check if we set PerConnBwRate/Burst, then + * check if the consensus sets them, else default to 'big enough'. + */ +static void +connection_or_update_token_buckets_helper(or_connection_t *conn, int reset, + or_options_t *options) +{ + int rate, burst; /* per-connection rate limiting params */ + if (connection_or_digest_is_known_relay(conn->identity_digest)) { + /* It's in the consensus, or we have a descriptor for it meaning it + * was probably in a recent consensus. It's a recognized relay: + * give it full bandwidth. */ + rate = (int)options->BandwidthRate; + burst = (int)options->BandwidthBurst; + } else { + /* Not a recognized relay. Squeeze it down based on the suggested + * bandwidth parameters in the consensus, but allow local config + * options to override. */ + rate = options->PerConnBWRate ? (int)options->PerConnBWRate : + (int)networkstatus_get_param(NULL, "perconnbwrate", + (int)options->BandwidthRate); + burst = options->PerConnBWBurst ? (int)options->PerConnBWBurst : + (int)networkstatus_get_param(NULL, "perconnbwburst", + (int)options->BandwidthBurst); + } + + conn->bandwidthrate = rate; + conn->bandwidthburst = burst; + if (reset) { /* set up the token buckets to be full */ + conn->read_bucket = conn->write_bucket = burst; + return; + } + /* If the new token bucket is smaller, take out the extra tokens. + * (If it's larger, don't -- the buckets can grow to reach the cap.) */ + if (conn->read_bucket > burst) + conn->read_bucket = burst; + if (conn->write_bucket > burst) + conn->write_bucket = burst; +} + +/** Either our set of relays or our per-conn rate limits have changed. + * Go through all the OR connections and update their token buckets. */ +void +connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options) +{ + SMARTLIST_FOREACH(conns, connection_t *, conn, + { + if (connection_speaks_cells(conn)) + connection_or_update_token_buckets_helper(TO_OR_CONN(conn), 0, 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. */ @@ -385,11 +412,9 @@ connection_or_init_conn_from_address(or_connection_t *conn, const char *id_digest, int started_here) { - or_options_t *options = get_options(); routerinfo_t *r = router_get_by_digest(id_digest); - conn->bandwidthrate = (int)options->BandwidthRate; - conn->read_bucket = conn->bandwidthburst = (int)options->BandwidthBurst; connection_or_set_identity_digest(conn, id_digest); + connection_or_update_token_buckets_helper(conn, 1, get_options()); conn->_base.port = port; tor_addr_copy(&conn->_base.addr, addr); @@ -581,11 +606,24 @@ connection_or_get_for_extend(const char *digest, #define TIME_BEFORE_OR_CONN_IS_TOO_OLD (60*60*24*7) /** Given the head of the linked list for all the or_connections with a given - * identity, set elements of that list as is_bad_for_new_circs() as - * appropriate. Helper for connection_or_set_bad_connections(). + * identity, set elements of that list as is_bad_for_new_circs as + * appropriate. Helper for connection_or_set_bad_connections(). + * + * Specifically, we set the is_bad_for_new_circs flag on: + * - all connections if <b>force</b> is true. + * - all connections that are too old. + * - all open non-canonical connections for which a canonical connection + * exists to the same router. + * - all open canonical connections for which a 'better' canonical + * connection exists to the same router. + * - all open non-canonical connections for which a 'better' non-canonical + * connection exists to the same router at the same address. + * + * See connection_or_is_better() for our idea of what makes one OR connection + * better than another. */ static void -connection_or_group_set_badness(or_connection_t *head) +connection_or_group_set_badness(or_connection_t *head, int force) { or_connection_t *or_conn = NULL, *best = NULL; int n_old = 0, n_inprogress = 0, n_canonical = 0, n_other = 0; @@ -597,8 +635,9 @@ connection_or_group_set_badness(or_connection_t *head) if (or_conn->_base.marked_for_close || or_conn->is_bad_for_new_circs) continue; - if (or_conn->_base.timestamp_created + TIME_BEFORE_OR_CONN_IS_TOO_OLD - < now) { + if (force || + or_conn->_base.timestamp_created + TIME_BEFORE_OR_CONN_IS_TOO_OLD + < now) { log_info(LD_OR, "Marking OR conn to %s:%d as too old for new circuits " "(fd %d, %d secs old).", @@ -631,7 +670,7 @@ connection_or_group_set_badness(or_connection_t *head) /* We have at least one open canonical connection to this router, * and this one is open but not canonical. Mark it bad. */ log_info(LD_OR, - "Marking OR conn to %s:%d as too old for new circuits: " + "Marking OR conn to %s:%d as unsuitable for new circuits: " "(fd %d, %d secs old). It is not canonical, and we have " "another connection to that OR that is.", or_conn->_base.address, or_conn->_base.port, or_conn->_base.s, @@ -671,7 +710,7 @@ connection_or_group_set_badness(or_connection_t *head) even when we're being forgiving. */ if (best->is_canonical) { log_info(LD_OR, - "Marking OR conn to %s:%d as too old for new circuits: " + "Marking OR conn to %s:%d as unsuitable for new circuits: " "(fd %d, %d secs old). We have a better canonical one " "(fd %d; %d secs old).", or_conn->_base.address, or_conn->_base.port, or_conn->_base.s, @@ -681,9 +720,9 @@ connection_or_group_set_badness(or_connection_t *head) } else if (!tor_addr_compare(&or_conn->real_addr, &best->real_addr, CMP_EXACT)) { log_info(LD_OR, - "Marking OR conn to %s:%d as too old for new circuits: " - "(fd %d, %d secs old). We have a better one " - "(fd %d; %d secs old).", + "Marking OR conn to %s:%d as unsuitable for new circuits: " + "(fd %d, %d secs old). We have a better one with the " + "same address (fd %d; %d secs old).", or_conn->_base.address, or_conn->_base.port, or_conn->_base.s, (int)(now - or_conn->_base.timestamp_created), best->_base.s, (int)(now - best->_base.timestamp_created)); @@ -693,27 +732,20 @@ connection_or_group_set_badness(or_connection_t *head) } } -/** Go through all the OR connections, and set the is_bad_for_new_circs - * flag on: - * - all connections that are too old. - * - all open non-canonical connections for which a canonical connection - * exists to the same router. - * - all open canonical connections for which a 'better' canonical - * connection exists to the same router. - * - all open non-canonical connections for which a 'better' non-canonical - * connection exists to the same router at the same address. - * - * See connection_or_is_better() for our idea of what makes one OR connection - * better than another. +/** Go through all the OR connections (or if <b>digest</b> is non-NULL, just + * the OR connections with that digest), and set the is_bad_for_new_circs + * flag based on the rules in connection_or_group_set_badness() (or just + * always set it if <b>force</b> is true). */ void -connection_or_set_bad_connections(void) +connection_or_set_bad_connections(const char *digest, int force) { if (!orconn_identity_map) return; DIGESTMAP_FOREACH(orconn_identity_map, identity, or_connection_t *, conn) { - connection_or_group_set_badness(conn); + if (!digest || !memcmp(digest, conn->identity_digest, DIGEST_LEN)) + connection_or_group_set_badness(conn, force); } DIGESTMAP_FOREACH_END; } @@ -753,6 +785,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, or_connection_t *conn; or_options_t *options = get_options(); int socket_error = 0; + int using_proxy = 0; tor_addr_t addr; tor_assert(_addr); @@ -771,19 +804,27 @@ 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); - if (options->HttpsProxy) { - /* we shouldn't connect directly. use the https proxy instead. */ - tor_addr_from_ipv4h(&addr, options->HttpsProxyAddr); - port = options->HttpsProxyPort; + /* 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; } switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr, port, &socket_error)) { case -1: /* If the connection failed immediately, and we're using - * an https proxy, our https proxy is down. Don't blame the - * Tor server. */ - if (!options->HttpsProxy) + * a proxy, our proxy is down. Don't blame the Tor server. */ + if (!using_proxy) entry_guard_register_connect_status(conn->identity_digest, 0, 1, time(NULL)); connection_or_connect_failed(conn, @@ -792,7 +833,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, connection_free(TO_CONN(conn)); return NULL; case 0: - connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE); + connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT); /* writable indicates finish, readable indicates broken link, error indicates broken link on windows */ return conn; @@ -819,13 +860,14 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving) { conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING; conn->tls = tor_tls_new(conn->_base.s, receiving); - tor_tls_set_logged_address(conn->tls, escaped_safe_str(conn->_base.address)); + 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; } connection_start_reading(TO_CONN(conn)); - log_debug(LD_OR,"starting TLS handshake on fd %d", conn->_base.s); + 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) { @@ -932,23 +974,26 @@ connection_or_nonopen_was_started_here(or_connection_t *conn) * return -1 if he is lying, broken, or otherwise something is wrong. * * If we initiated this connection (<b>started_here</b> is true), make sure - * the other side sent sent a correctly formed certificate. If I initiated the + * the other side sent a correctly formed certificate. If I initiated the * connection, make sure it's the right guy. * * Otherwise (if we _didn't_ initiate this connection), it's okay for * the certificate to be weird or absent. * * If we return 0, and the certificate is as expected, write a hash of the - * identity key into digest_rcvd, which must have DIGEST_LEN space in it. (If - * we return -1 this buffer is undefined.) If the certificate is invalid - * or missing on an incoming connection, we return 0 and set digest_rcvd to - * DIGEST_LEN 0 bytes. + * identity key into <b>digest_rcvd_out</b>, which must have DIGEST_LEN + * space in it. + * If the certificate is invalid or missing on an incoming connection, + * we return 0 and set <b>digest_rcvd_out</b> to DIGEST_LEN NUL bytes. + * (If we return -1, the contents of this buffer are undefined.) * * As side effects, * 1) Set conn->circ_id_type according to tor-spec.txt. * 2) If we're an authdirserver and we initiated the connection: drop all * descriptors that claim to be on that IP/port but that aren't * this guy; and note that this guy is reachable. + * 3) If this is a bridge and we didn't configure its identity + * fingerprint, remember the keyid we just learned. */ static int connection_or_check_valid_tls_handshake(or_connection_t *conn, @@ -959,19 +1004,23 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, 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(conn->_base.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; check_no_tls_errors(); has_cert = tor_tls_peer_has_cert(conn->tls); if (started_here && !has_cert) { - log_info(LD_PROTOCOL,"Tried connecting to router at %s:%d, but it didn't " + log_info(LD_HANDSHAKE,"Tried connecting to router at %s:%d, but it didn't " "send a cert! Closing.", safe_address, conn->_base.port); return -1; } else if (!has_cert) { - log_debug(LD_PROTOCOL,"Got incoming connection with no certificate. " + log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. " "That's ok."); } check_no_tls_errors(); @@ -980,15 +1029,16 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, int v = tor_tls_verify(started_here?severity:LOG_INFO, conn->tls, &identity_rcvd); if (started_here && v<0) { - log_fn(severity,LD_OR,"Tried connecting to router at %s:%d: It" + log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s:%d: It" " has a cert but it's invalid. Closing.", safe_address, conn->_base.port); return -1; } else if (v<0) { - log_info(LD_PROTOCOL,"Incoming connection gave us an invalid cert " + log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert " "chain; ignoring."); } else { - log_debug(LD_OR,"The certificate seems to be valid on %s connection " + log_debug(LD_HANDSHAKE, + "The certificate seems to be valid on %s connection " "with %s:%d", conn_type, safe_address, conn->_base.port); } check_no_tls_errors(); @@ -997,7 +1047,7 @@ 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(get_identity_key(), identity_rcvd)<0) { + 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; @@ -1015,9 +1065,13 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, conn->nickname[0] = '$'; base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, conn->identity_digest, DIGEST_LEN); - log_info(LD_OR, "Connected to router %s at %s:%d without knowing " + log_info(LD_HANDSHAKE, "Connected to router %s at %s:%d without knowing " "its key. Hoping for the best.", conn->nickname, conn->_base.address, conn->_base.port); + /* 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); } if (started_here) { @@ -1031,7 +1085,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, base16_encode(seen, sizeof(seen), digest_rcvd_out, DIGEST_LEN); base16_encode(expected, sizeof(expected), conn->identity_digest, DIGEST_LEN); - log_fn(severity, LD_OR, + 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); @@ -1073,8 +1127,8 @@ 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_OR,"tls handshake with %s done. verifying.", - safe_str(conn->_base.address)); + log_debug(LD_HANDSHAKE,"tls handshake with %s done. verifying.", + safe_str_client(conn->_base.address)); directory_set_dirty(); @@ -1082,6 +1136,8 @@ connection_tls_finish_handshake(or_connection_t *conn) digest_rcvd) < 0) return -1; + circuit_build_times_network_is_live(&circ_times); + if (tor_tls_used_v1_handshake(conn->tls)) { conn->link_proto = 1; if (!started_here) { @@ -1117,7 +1173,8 @@ connection_init_or_handshake_state(or_connection_t *conn, int started_here) void or_handshake_state_free(or_handshake_state_t *state) { - tor_assert(state); + if (!state) + return; memset(state, 0xBE, sizeof(or_handshake_state_t)); tor_free(state); } @@ -1134,6 +1191,7 @@ connection_or_set_state_open(or_connection_t *conn) control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED, 0); if (started_here) { + circuit_build_times_network_is_live(&circ_times); rep_hist_note_connect_succeeded(conn->identity_digest, now); if (entry_guard_register_connect_status(conn->identity_digest, 1, 0, now) < 0) { @@ -1158,10 +1216,10 @@ connection_or_set_state_open(or_connection_t *conn) } } } - if (conn->handshake_state) { - or_handshake_state_free(conn->handshake_state); - conn->handshake_state = NULL; - } + + or_handshake_state_free(conn->handshake_state); + conn->handshake_state = NULL; + connection_start_reading(TO_CONN(conn)); circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */ @@ -1235,6 +1293,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn) if (connection_fetch_var_cell_from_buf(conn, &var_cell)) { if (!var_cell) return 0; /* not yet. */ + circuit_build_times_network_is_live(&circ_times); command_process_var_cell(var_cell, conn); var_cell_free(var_cell); } else { @@ -1244,6 +1303,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn) available? */ return 0; /* not yet */ + circuit_build_times_network_is_live(&circ_times); connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, TO_CONN(conn)); /* retrieve cell info from buf (create the host-order struct from the @@ -1274,10 +1334,6 @@ connection_or_send_destroy(circid_t circ_id, or_connection_t *conn, int reason) cell.payload[0] = (uint8_t) reason; log_debug(LD_OR,"Sending destroy (circID %d).", circ_id); - /* XXXX It's possible that under some circumstances, we want the destroy - * to take precedence over other data waiting on the circuit's cell queue. - */ - connection_or_write_cell_to_buf(&cell, conn); return 0; } diff --git a/src/or/connection_or.h b/src/or/connection_or.h new file mode 100644 index 0000000000..216a9bd648 --- /dev/null +++ b/src/or/connection_or.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file connection_or.h + * \brief Header file for connection_or.c. + **/ + +#ifndef _TOR_CONNECTION_OR_H +#define _TOR_CONNECTION_OR_H + +void connection_or_remove_from_identity_map(or_connection_t *conn); +void connection_or_clear_identity_map(void); +or_connection_t *connection_or_get_for_extend(const char *digest, + const tor_addr_t *target_addr, + const char **msg_out, + int *launch_out); +void connection_or_set_bad_connections(const char *digest, int force); + +int connection_or_reached_eof(or_connection_t *conn); +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); +int connection_or_digest_is_known_relay(const char *id_digest); +void connection_or_update_token_buckets(smartlist_t *conns, + 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); + +int connection_tls_start_handshake(or_connection_t *conn, int receiving); +int connection_tls_continue_handshake(or_connection_t *conn); + +void or_handshake_state_free(or_handshake_state_t *state); +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); +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_netinfo(or_connection_t *conn); +int is_or_protocol_version_known(uint16_t version); + +void cell_pack(packed_cell_t *dest, const cell_t *src); +void var_cell_pack_header(const var_cell_t *cell, char *hdr_out); +var_cell_t *var_cell_new(uint16_t payload_len); +void var_cell_free(var_cell_t *cell); + +#endif + diff --git a/src/or/control.c b/src/or/control.c index 7eb2e042f2..ad316c4ebc 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -11,6 +11,26 @@ #define CONTROL_PRIVATE #include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "control.h" +#include "directory.h" +#include "dirserv.h" +#include "dnsserv.h" +#include "geoip.h" +#include "hibernate.h" +#include "main.h" +#include "networkstatus.h" +#include "policies.h" +#include "reasons.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" /** Yield true iff <b>s</b> is the state of a control_connection_t that has * finished authentication and is accepting commands. */ @@ -43,7 +63,8 @@ #define EVENT_STREAM_BANDWIDTH_USED 0x0014 #define EVENT_CLIENTS_SEEN 0x0015 #define EVENT_NEWCONSENSUS 0x0016 -#define _EVENT_MAX 0x0016 +#define EVENT_BUILDTIMEOUT_SET 0x0017 +#define _EVENT_MAX 0x0017 /* 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 @@ -54,13 +75,9 @@ **/ typedef uint32_t event_mask_t; -/** An event mask of all the events that controller with the LONG_NAMES option - * set is interested in receiving. */ -static event_mask_t global_event_mask1long = 0; - -/** An event mask of all the events that controller with the SHORT_NAMES option - * set is interested in receiving. */ -static event_mask_t global_event_mask1short = 0; +/** An event mask of all the events that any controller is interested in + * receiving. */ +static event_mask_t global_event_mask = 0; /** True iff we have disabled log messages from being sent to the controller */ static int disable_log_messages = 0; @@ -68,13 +85,7 @@ static int disable_log_messages = 0; /** Macro: true if any control connection is interested in events of type * <b>e</b>. */ #define EVENT_IS_INTERESTING(e) \ - ((global_event_mask1long|global_event_mask1short) & (1<<(e))) -/** Macro: true if any control connection with the LONG_NAMES option is - * interested in events of type <b>e</b>. */ -#define EVENT_IS_INTERESTING1L(e) (global_event_mask1long & (1<<(e))) -/** Macro: true if any control connection with the SHORT_NAMES option is - * interested in events of type <b>e</b>. */ -#define EVENT_IS_INTERESTING1S(e) (global_event_mask1short & (1<<(e))) + (global_event_mask & (1<<(e))) /** If we're using cookie-type authentication, how long should our cookies be? */ @@ -95,25 +106,13 @@ static char authentication_cookie[AUTHENTICATION_COOKIE_LEN]; * of this so we can respond to getinfo status/bootstrap-phase queries. */ static char last_sent_bootstrap_message[BOOTSTRAP_MSG_LEN]; -/** Flag for event_format_t. Indicates that we should use the old - * name format of nickname|hexdigest - */ -#define SHORT_NAMES 1 -/** Flag for event_format_t. Indicates that we should use the new - * name format of $hexdigest[=~]nickname +/** Flag for event_format_t. Indicates that we should use the one standard + format. */ -#define LONG_NAMES 2 -#define ALL_NAMES (SHORT_NAMES|LONG_NAMES) -/** Flag for event_format_t. Indicates that we should use the new event - * format where extra event fields are allowed using a NAME=VAL format. */ -#define EXTENDED_FORMAT 4 -/** Flag for event_format_t. Indicates that we are using the old event format - * where extra fields aren't allowed. */ -#define NONEXTENDED_FORMAT 8 -#define ALL_FORMATS (EXTENDED_FORMAT|NONEXTENDED_FORMAT) +#define ALL_FORMATS 1 /** Bit field of flags to select how to format a controller event. Recognized - * flags are SHORT_NAMES, LONG_NAMES, EXTENDED_FORMAT, NONEXTENDED_FORMAT. */ + * flag is ALL_FORMATS. */ typedef int event_format_t; static void connection_printf_to_buf(control_connection_t *conn, @@ -123,9 +122,6 @@ static void send_control_done(control_connection_t *conn); static void send_control_event(uint16_t event, event_format_t which, const char *format, ...) CHECK_PRINTF(3,4); -static void send_control_event_extended(uint16_t event, event_format_t which, - const char *format, ...) - CHECK_PRINTF(3,4); static int handle_control_setconf(control_connection_t *conn, uint32_t len, char *body); static int handle_control_resetconf(control_connection_t *conn, uint32_t len, @@ -139,8 +135,6 @@ static int handle_control_setevents(control_connection_t *conn, uint32_t len, static int handle_control_authenticate(control_connection_t *conn, uint32_t len, const char *body); -static int handle_control_saveconf(control_connection_t *conn, uint32_t len, - const char *body); static int handle_control_signal(control_connection_t *conn, uint32_t len, const char *body); static int handle_control_mapaddress(control_connection_t *conn, uint32_t len, @@ -174,7 +168,7 @@ static int handle_control_usefeature(control_connection_t *conn, const char *body); static int write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len); -static void orconn_target_get_name(int long_names, char *buf, size_t len, +static void orconn_target_get_name(char *buf, size_t len, or_connection_t *conn); static char *get_cookie_file(void); @@ -214,25 +208,19 @@ control_update_global_event_mask(void) { smartlist_t *conns = get_connection_array(); event_mask_t old_mask, new_mask; - old_mask = global_event_mask1short; - old_mask |= global_event_mask1long; + old_mask = global_event_mask; - global_event_mask1short = 0; - global_event_mask1long = 0; + global_event_mask = 0; SMARTLIST_FOREACH(conns, connection_t *, _conn, { if (_conn->type == CONN_TYPE_CONTROL && STATE_IS_OPEN(_conn->state)) { control_connection_t *conn = TO_CONTROL_CONN(_conn); - if (conn->use_long_names) - global_event_mask1long |= conn->event_mask; - else - global_event_mask1short |= conn->event_mask; + global_event_mask |= conn->event_mask; } }); - new_mask = global_event_mask1short; - new_mask |= global_event_mask1long; + new_mask = global_event_mask; /* Handle the aftermath. Set up the log callback to tell us only what * we want to hear...*/ @@ -312,7 +300,7 @@ connection_write_str_to_buf(const char *s, control_connection_t *conn) /** Given a <b>len</b>-character string in <b>data</b>, made of lines * terminated by CRLF, allocate a new string in *<b>out</b>, and copy the * contents of <b>data</b> into *<b>out</b>, adding a period before any period - * that that appears at the start of a line, and adding a period-CRLF line at + * that appears at the start of a line, and adding a period-CRLF line at * the end. Replace all LF characters sequences with CRLF. Return the number * of bytes in *<b>out</b>. */ @@ -542,28 +530,15 @@ send_control_event_string(uint16_t event, event_format_t which, const char *msg) { smartlist_t *conns = get_connection_array(); + (void)which; tor_assert(event >= _EVENT_MIN && event <= _EVENT_MAX); - SMARTLIST_FOREACH(conns, connection_t *, conn, - { + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->type == CONN_TYPE_CONTROL && !conn->marked_for_close && conn->state == CONTROL_CONN_STATE_OPEN) { control_connection_t *control_conn = TO_CONTROL_CONN(conn); - if (control_conn->use_long_names) { - if (!(which & LONG_NAMES)) - continue; - } else { - if (!(which & SHORT_NAMES)) - continue; - } - if (control_conn->use_extended_events) { - if (!(which & EXTENDED_FORMAT)) - continue; - } else { - if (!(which & NONEXTENDED_FORMAT)) - continue; - } + if (control_conn->event_mask & (1<<event)) { int is_err = 0; connection_write_to_buf(msg, strlen(msg), TO_CONN(control_conn)); @@ -579,7 +554,7 @@ send_control_event_string(uint16_t event, event_format_t which, connection_handle_write(TO_CONN(control_conn), 1); } } - }); + } SMARTLIST_FOREACH_END(conn); } /** Helper for send_control1_event and send_control1_event_extended: @@ -587,22 +562,17 @@ send_control_event_string(uint16_t event, event_format_t which, * <b>event</b>. The event's body is created by the printf-style format in * <b>format</b>, and other arguments as provided. * - * If <b>extended</b> is true, and the format contains a single '@' character, - * it will be replaced with a space and all text after that character will be - * sent only to controllers that have enabled extended events. - * * Currently the length of the message is limited to 1024 (including the * ending \\r\\n\\0). */ static void -send_control_event_impl(uint16_t event, event_format_t which, int extended, - const char *format, va_list ap) +send_control_event_impl(uint16_t event, event_format_t which, + const char *format, va_list ap) { /* This is just a little longer than the longest allowed log message */ #define SEND_CONTROL1_EVENT_BUFFERSIZE 10064 int r; char buf[SEND_CONTROL1_EVENT_BUFFERSIZE]; size_t len; - char *cp; r = tor_vsnprintf(buf, sizeof(buf), format, ap); if (r<0) { @@ -618,15 +588,7 @@ send_control_event_impl(uint16_t event, event_format_t which, int extended, buf[SEND_CONTROL1_EVENT_BUFFERSIZE-3] = '\r'; } - if (extended && (cp = strchr(buf, '@'))) { - which &= ~ALL_FORMATS; - *cp = ' '; - send_control_event_string(event, which|EXTENDED_FORMAT, buf); - memcpy(cp, "\r\n\0", 3); - send_control_event_string(event, which|NONEXTENDED_FORMAT, buf); - } else { - send_control_event_string(event, which|ALL_FORMATS, buf); - } + send_control_event_string(event, which|ALL_FORMATS, buf); } /** Send an event to all v1 controllers that are listening for code @@ -641,27 +603,7 @@ send_control_event(uint16_t event, event_format_t which, { va_list ap; va_start(ap, format); - send_control_event_impl(event, which, 0, format, ap); - va_end(ap); -} - -/** Send an event to all v1 controllers that are listening for code - * <b>event</b>. The event's body is created by the printf-style format in - * <b>format</b>, and other arguments as provided. - * - * If the format contains a single '@' character, it will be replaced with a - * space and all text after that character will be sent only to controllers - * that have enabled extended events. - * - * Currently the length of the message is limited to 1024 (including the - * ending \\n\\r\\0. */ -static void -send_control_event_extended(uint16_t event, event_format_t which, - const char *format, ...) -{ - va_list ap; - va_start(ap, format); - send_control_event_impl(event, which, 1, format, ap); + send_control_event_impl(event, which, format, ap); va_end(ap); } @@ -907,36 +849,37 @@ handle_control_loadconf(control_connection_t *conn, uint32_t len, retval = options_init_from_string(body, CMD_RUN_TOR, NULL, &errstring); - if (retval != SETOPT_OK) { + if (retval != SETOPT_OK) log_warn(LD_CONTROL, "Controller gave us config file that didn't validate: %s", errstring); - switch (retval) { - case SETOPT_ERR_PARSE: - msg = "552 Invalid config file"; - break; - case SETOPT_ERR_TRANSITION: - msg = "553 Transition not allowed"; - break; - case SETOPT_ERR_SETTING: - msg = "553 Unable to set option"; - break; - case SETOPT_ERR_MISC: - default: - msg = "550 Unable to load config"; - break; - case SETOPT_OK: - tor_fragile_assert(); - break; - } + + switch (retval) { + case SETOPT_ERR_PARSE: + msg = "552 Invalid config file"; + break; + case SETOPT_ERR_TRANSITION: + msg = "553 Transition not allowed"; + break; + case SETOPT_ERR_SETTING: + msg = "553 Unable to set option"; + break; + case SETOPT_ERR_MISC: + default: + msg = "550 Unable to load config"; + break; + case SETOPT_OK: + break; + } + if (msg) { if (errstring) connection_printf_to_buf(conn, "%s: %s\r\n", msg, errstring); else connection_printf_to_buf(conn, "%s\r\n", msg); - tor_free(errstring); - return 0; + } else { + send_control_done(conn); } - send_control_done(conn); + tor_free(errstring); return 0; } @@ -948,7 +891,6 @@ handle_control_setevents(control_connection_t *conn, uint32_t len, { uint16_t event_code; uint32_t event_mask = 0; - unsigned int extended = 0; smartlist_t *events = smartlist_create(); (void) len; @@ -958,7 +900,6 @@ handle_control_setevents(control_connection_t *conn, uint32_t len, SMARTLIST_FOREACH_BEGIN(events, const char *, ev) { if (!strcasecmp(ev, "EXTENDED")) { - extended = 1; continue; } else if (!strcasecmp(ev, "CIRC")) event_code = EVENT_CIRCUIT_STATUS; @@ -1002,6 +943,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len, 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); @@ -1016,8 +959,6 @@ handle_control_setevents(control_connection_t *conn, uint32_t len, smartlist_free(events); conn->event_mask = event_mask; - if (extended) - conn->use_extended_events = 1; control_update_global_event_mask(); send_control_done(conn); @@ -1328,7 +1269,7 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len, smartlist_add(reply, ans); log_warn(LD_CONTROL, "Unable to allocate address for '%s' in MapAddress msg", - safe_str(line)); + safe_str_client(line)); } else { tor_snprintf(ans, anslen, "250-%s=%s", address, to); smartlist_add(reply, ans); @@ -1345,7 +1286,8 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len, "not of expected form 'foo=bar'.", line); smartlist_add(reply, ans); log_info(LD_CONTROL, "Skipping MapAddress '%s': wrong " - "number of items.", safe_str(line)); + "number of items.", + safe_str_client(line)); } SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); smartlist_clear(elts); @@ -1374,13 +1316,15 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len, * trivial-to-implement questions. */ static int getinfo_helper_misc(control_connection_t *conn, const char *question, - char **answer) + char **answer, const char **errmsg) { (void) conn; if (!strcmp(question, "version")) { *answer = tor_strdup(get_version()); } else if (!strcmp(question, "config-file")) { *answer = tor_strdup(get_torrc_fname()); + } 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")) { @@ -1392,15 +1336,19 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, *answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS"); } else if (!strcmp(question, "address")) { uint32_t addr; - if (router_pick_published_address(get_options(), &addr) < 0) + if (router_pick_published_address(get_options(), &addr) < 0) { + *errmsg = "Address unknown"; return -1; + } *answer = tor_dup_ip(addr); } else if (!strcmp(question, "dir-usage")) { *answer = directory_dump_request_log(); } else if (!strcmp(question, "fingerprint")) { routerinfo_t *me = router_get_my_routerinfo(); - if (!me) + if (!me) { + *errmsg = "No routerdesc known; am I really a server?"; return -1; + } *answer = tor_malloc(HEX_DIGEST_LEN+1); base16_encode(*answer, HEX_DIGEST_LEN+1, me->cache_info.identity_digest, DIGEST_LEN); @@ -1461,8 +1409,10 @@ munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri, * directory information. */ static int getinfo_helper_dir(control_connection_t *control_conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { + (void) control_conn; if (!strcmpstart(question, "desc/id/")) { routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/")); if (ri) { @@ -1537,6 +1487,7 @@ getinfo_helper_dir(control_connection_t *control_conn, log_warn(LD_CONTROL, "getinfo '%s': %s", question, msg); smartlist_free(descs); tor_free(url); + *errmsg = msg; return -1; } SMARTLIST_FOREACH(descs, signed_descriptor_t *, sd, @@ -1587,7 +1538,7 @@ getinfo_helper_dir(control_connection_t *control_conn, } } else if (!strcmp(question, "dir/status-vote/current/consensus")) { /* v3 */ if (directory_caches_dir_info(get_options())) { - const cached_dir_t *consensus = dirserv_get_consensus(); + const cached_dir_t *consensus = dirserv_get_consensus("ns"); if (consensus) *answer = tor_strdup(consensus->dir); } @@ -1598,10 +1549,8 @@ getinfo_helper_dir(control_connection_t *control_conn, } } else if (!strcmp(question, "network-status")) { /* v1 */ routerlist_t *routerlist = router_get_routerlist(); - int verbose = control_conn->use_long_names; if (!routerlist || !routerlist->routers || - list_server_status_v1(routerlist->routers, answer, - verbose ? 2 : 1) < 0) { + list_server_status_v1(routerlist->routers, answer, 1) < 0) { return -1; } } else if (!strcmpstart(question, "extra-info/digest/")) { @@ -1635,8 +1584,10 @@ getinfo_helper_dir(control_connection_t *control_conn, * current states of things we send events about. */ static int getinfo_helper_events(control_connection_t *control_conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { + (void) control_conn; if (!strcmp(question, "circuit-status")) { circuit_t *circ; smartlist_t *status = smartlist_create(); @@ -1647,10 +1598,9 @@ getinfo_helper_events(control_connection_t *control_conn, const char *purpose; if (! CIRCUIT_IS_ORIGIN(circ) || circ->marked_for_close) continue; - if (control_conn->use_long_names) - path = circuit_list_path_for_controller(TO_ORIGIN_CIRCUIT(circ)); - else - path = circuit_list_path(TO_ORIGIN_CIRCUIT(circ),0); + + path = circuit_list_path_for_controller(TO_ORIGIN_CIRCUIT(circ)); + if (circ->state == CIRCUIT_STATE_OPEN) state = "BUILT"; else if (strlen(path)) @@ -1728,8 +1678,7 @@ getinfo_helper_events(control_connection_t *control_conn, } else if (!strcmp(question, "orconn-status")) { smartlist_t *conns = get_connection_array(); smartlist_t *status = smartlist_create(); - SMARTLIST_FOREACH(conns, connection_t *, base_conn, - { + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { const char *state; char *s; char name[128]; @@ -1744,29 +1693,19 @@ getinfo_helper_events(control_connection_t *control_conn, state = "LAUNCHED"; else state = "NEW"; - orconn_target_get_name(control_conn->use_long_names, name, sizeof(name), - conn); + orconn_target_get_name(name, sizeof(name), conn); slen = strlen(name)+strlen(state)+2; s = tor_malloc(slen+1); tor_snprintf(s, slen, "%s %s", name, state); smartlist_add(status, s); - }); + } SMARTLIST_FOREACH_END(base_conn); *answer = smartlist_join_strings(status, "\r\n", 0, NULL); SMARTLIST_FOREACH(status, char *, cp, tor_free(cp)); smartlist_free(status); - } else if (!strcmpstart(question, "addr-mappings/") || - !strcmpstart(question, "address-mappings/")) { + } else if (!strcmpstart(question, "address-mappings/")) { time_t min_e, max_e; smartlist_t *mappings; - int want_expiry = !strcmpstart(question, "address-mappings/"); - if (!strcmpstart(question, "addr-mappings/")) { - /* XXXX022 This has been deprecated since 0.2.0.3-alpha, and has - generated a warning since 0.2.1.10-alpha; remove late in 0.2.2.x. */ - log_warn(LD_CONTROL, "Controller used obsolete addr-mappings/ GETINFO " - "key; use address-mappings/ instead."); - } - question += strlen(want_expiry ? "address-mappings/" - : "addr-mappings/"); + question += strlen("address-mappings/"); if (!strcmp(question, "all")) { min_e = 0; max_e = TIME_MAX; } else if (!strcmp(question, "cache")) { @@ -1779,7 +1718,7 @@ getinfo_helper_events(control_connection_t *control_conn, return 0; } mappings = smartlist_create(); - addressmap_get_mappings(mappings, min_e, max_e, want_expiry); + addressmap_get_mappings(mappings, min_e, max_e, 1); *answer = smartlist_join_strings(mappings, "\r\n", 0, NULL); SMARTLIST_FOREACH(mappings, char *, cp, tor_free(cp)); smartlist_free(mappings); @@ -1787,7 +1726,7 @@ getinfo_helper_events(control_connection_t *control_conn, /* Note that status/ is not a catch-all for events; there's only supposed * to be a status GETINFO if there's a corresponding STATUS event. */ if (!strcmp(question, "status/circuit-established")) { - *answer = tor_strdup(has_completed_circuit ? "1" : "0"); + *answer = tor_strdup(can_complete_circuit ? "1" : "0"); } else if (!strcmp(question, "status/enough-dir-info")) { *answer = tor_strdup(router_have_minimum_dir_info() ? "1" : "0"); } else if (!strcmp(question, "status/good-server-descriptor") || @@ -1846,21 +1785,12 @@ getinfo_helper_events(control_connection_t *control_conn, "information", question); } } else if (!strcmp(question, "status/clients-seen")) { - char geoip_start[ISO_TIME_LEN+1]; - size_t answer_len; - char *geoip_summary = extrainfo_get_client_geoip_summary(time(NULL)); - - if (!geoip_summary) + const char *bridge_stats = geoip_get_bridge_stats_controller(time(NULL)); + if (!bridge_stats) { + *errmsg = "No bridge-client stats available"; return -1; - - answer_len = strlen("TimeStarted=\"\" CountrySummary=") + - ISO_TIME_LEN + strlen(geoip_summary) + 1; - *answer = tor_malloc(answer_len); - format_iso_time(geoip_start, geoip_get_history_start()); - tor_snprintf(*answer, answer_len, - "TimeStarted=\"%s\" CountrySummary=%s", - geoip_start, geoip_summary); - tor_free(geoip_summary); + } + *answer = tor_strdup(bridge_stats); } else { return 0; } @@ -1870,11 +1800,14 @@ getinfo_helper_events(control_connection_t *control_conn, /** Callback function for GETINFO: on a given control connection, try to * answer the question <b>q</b> and store the newly-allocated answer in - * *<b>a</b>. If there's no answer, or an error occurs, just don't set - * <b>a</b>. Return 0. + * *<b>a</b>. If an internal error occurs, return -1 and optionally set + * *<b>error_out</b> to point to an error message to be delivered to the + * controller. On success, _or if the key is not recognized_, return 0. Do not + * set <b>a</b> if the key is not recognized. */ typedef int (*getinfo_helper_t)(control_connection_t *, - const char *q, char **a); + const char *q, char **a, + const char **error_out); /** A single item for the GETINFO question-to-answer-function table. */ typedef struct getinfo_item_t { @@ -1894,6 +1827,8 @@ 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-text", misc, + "Return the string that would be written by a saveconf command."), ITEM("accounting/bytes", accounting, "Number of bytes read/written so far in the accounting interval."), ITEM("accounting/bytes-left", accounting, @@ -1933,7 +1868,6 @@ static const getinfo_item_t getinfo_items[] = { PREFIX("ns/purpose/", networkstatus, "Brief summary of router status by purpose (v2 directory format)."), - PREFIX("unregistered-servers-", dirserv_unregistered, NULL), ITEM("network-status", dir, "Brief summary of router status (v1 directory format)"), ITEM("circuit-status", events, "List of current circuits originating here."), @@ -1945,14 +1879,6 @@ static const getinfo_item_t getinfo_items[] = { DOC("address-mappings/config", "Current address mappings from configuration."), DOC("address-mappings/control", "Current address mappings from controller."), - PREFIX("addr-mappings/", events, NULL), - DOC("addr-mappings/all", "Current address mappings without expiry times."), - DOC("addr-mappings/cache", - "Current cached DNS replies without expiry times."), - DOC("addr-mappings/config", - "Current address mappings from configuration without expiry times."), - DOC("addr-mappings/control", - "Current address mappings from controller without expiry times."), PREFIX("status/", events, NULL), DOC("status/circuit-established", "Whether we think client functionality is working."), @@ -1988,18 +1914,18 @@ static char * list_getinfo_options(void) { int i; - char buf[300]; + char *buf=NULL; smartlist_t *lines = smartlist_create(); char *ans; for (i = 0; getinfo_items[i].varname; ++i) { if (!getinfo_items[i].desc) continue; - tor_snprintf(buf, sizeof(buf), "%s%s -- %s\n", + tor_asprintf(&buf, "%s%s -- %s\n", getinfo_items[i].varname, getinfo_items[i].is_prefix ? "*" : "", getinfo_items[i].desc); - smartlist_add(lines, tor_strdup(buf)); + smartlist_add(lines, buf); } smartlist_sort_strings(lines); @@ -2016,7 +1942,8 @@ list_getinfo_options(void) * internal error. */ static int handle_getinfo_helper(control_connection_t *control_conn, - const char *question, char **answer) + const char *question, char **answer, + const char **err_out) { int i; *answer = NULL; /* unrecognized key by default */ @@ -2029,7 +1956,7 @@ handle_getinfo_helper(control_connection_t *control_conn, match = !strcmp(question, getinfo_items[i].varname); if (match) { tor_assert(getinfo_items[i].fn); - return getinfo_items[i].fn(control_conn, question, answer); + return getinfo_items[i].fn(control_conn, question, answer, err_out); } } @@ -2051,10 +1978,12 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len, smartlist_split_string(questions, body, " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - SMARTLIST_FOREACH(questions, const char *, q, - { - if (handle_getinfo_helper(conn, q, &ans) < 0) { - connection_write_str_to_buf("551 Internal error\r\n", conn); + SMARTLIST_FOREACH_BEGIN(questions, const char *, q) { + const char *errmsg = NULL; + if (handle_getinfo_helper(conn, q, &ans, &errmsg) < 0) { + if (!errmsg) + errmsg = "Internal error"; + connection_printf_to_buf(conn, "551 %s\r\n", errmsg); goto done; } if (!ans) { @@ -2063,7 +1992,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len, smartlist_add(answers, tor_strdup(q)); smartlist_add(answers, ans); } - }); + } SMARTLIST_FOREACH_END(q); if (smartlist_len(unrecognized)) { for (i=0; i < smartlist_len(unrecognized)-1; ++i) connection_printf_to_buf(conn, @@ -2108,12 +2037,12 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len, static uint8_t circuit_purpose_from_string(const char *string) { - if (!strcmpstart(string, "purpose=")) + if (!strcasecmpstart(string, "purpose=")) string += strlen("purpose="); - if (!strcmp(string, "general")) + if (!strcasecmp(string, "general")) return CIRCUIT_PURPOSE_C_GENERAL; - else if (!strcmp(string, "controller")) + else if (!strcasecmp(string, "controller")) return CIRCUIT_PURPOSE_CONTROLLER; else return CIRCUIT_PURPOSE_UNKNOWN; @@ -2145,6 +2074,31 @@ getargs_helper(const char *command, control_connection_t *conn, return NULL; } +/** Helper. Return the first element of <b>sl</b> at index <b>start_at</b> or + * higher that starts with <b>prefix</b>, case-insensitive. Return NULL if no + * such element exists. */ +static const char * +find_element_starting_with(smartlist_t *sl, int start_at, const char *prefix) +{ + int i; + for (i = start_at; i < smartlist_len(sl); ++i) { + const char *elt = smartlist_get(sl, i); + if (!strcasecmpstart(elt, prefix)) + return elt; + } + return NULL; +} + +/** Helper. Return true iff s is an argument that we should treat as a + * key-value pair. */ +static int +is_keyval_pair(const char *s) +{ + /* An argument is a key-value pair if it has an =, and it isn't of the form + * $fingeprint=name */ + return strchr(s, '=') && s[0] != '$'; +} + /** Called when we get an EXTENDCIRCUIT message. Try to extend the listed * circuit, and report success or failure. */ static int @@ -2160,33 +2114,57 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, router_nicknames = smartlist_create(); - args = getargs_helper("EXTENDCIRCUIT", conn, body, 2, -1); + args = getargs_helper("EXTENDCIRCUIT", conn, body, 1, -1); if (!args) goto done; zero_circ = !strcmp("0", (char*)smartlist_get(args,0)); - if (!zero_circ && !(circ = get_circ(smartlist_get(args,0)))) { - connection_printf_to_buf(conn, "552 Unknown circuit \"%s\"\r\n", - (char*)smartlist_get(args, 0)); - } - smartlist_split_string(router_nicknames, smartlist_get(args,1), ",", 0, 0); - if (zero_circ && smartlist_len(args)>2) { - char *purp = smartlist_get(args,2); - intended_purpose = circuit_purpose_from_string(purp); - if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) { - connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp); + if (zero_circ) { + const char *purp = find_element_starting_with(args, 1, "PURPOSE="); + + if (purp) { + intended_purpose = circuit_purpose_from_string(purp); + if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) { + connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp); + SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); + smartlist_free(args); + goto done; + } + } + + 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); + if (!circ) { + connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn); + } else { + connection_printf_to_buf(conn, "250 EXTENDED %lu\r\n", + (unsigned long)circ->global_identifier); + } SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); smartlist_free(args); goto done; } + // "EXTENDCIRCUIT 0 router1,router2" || + // "EXTENDCIRCUIT 0 router1,router2 PURPOSE=foo" } - SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); - smartlist_free(args); - if (!zero_circ && !circ) { + + if (!zero_circ && !(circ = get_circ(smartlist_get(args,0)))) { + connection_printf_to_buf(conn, "552 Unknown circuit \"%s\"\r\n", + (char*)smartlist_get(args, 0)); + SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); + smartlist_free(args); goto done; } + smartlist_split_string(router_nicknames, smartlist_get(args,1), ",", 0, 0); + + SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); + smartlist_free(args); + routers = smartlist_create(); SMARTLIST_FOREACH(router_nicknames, const char *, n, { @@ -2244,8 +2222,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); - if (routers) - smartlist_free(routers); + smartlist_free(routers); return 0; } @@ -2271,7 +2248,7 @@ handle_control_setcircuitpurpose(control_connection_t *conn, } { - char *purp = smartlist_get(args,1); + const char *purp = find_element_starting_with(args,1,"PURPOSE="); new_purpose = circuit_purpose_from_string(purp); if (new_purpose == CIRCUIT_PURPOSE_UNKNOWN) { connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp); @@ -2282,7 +2259,7 @@ handle_control_setcircuitpurpose(control_connection_t *conn, circ->_base.purpose = new_purpose; connection_write_str_to_buf("250 OK\r\n", conn); -done: + done: if (args) { SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); smartlist_free(args); @@ -2316,9 +2293,9 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, } else if (!zero_circ && !(circ = get_circ(smartlist_get(args, 1)))) { connection_printf_to_buf(conn, "552 Unknown circuit \"%s\"\r\n", (char*)smartlist_get(args, 1)); - } else if (circ && smartlist_len(args) > 2) { - char *hopstring = smartlist_get(args, 2); - if (!strcasecmpstart(hopstring, "HOP=")) { + } else if (circ) { + const char *hopstring = find_element_starting_with(args,2,"HOP="); + if (hopstring) { hopstring += strlen("HOP="); hop = (int) tor_parse_ulong(hopstring, 10, 0, INT_MAX, &hop_line_ok, NULL); @@ -2365,7 +2342,7 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, char* exit_digest; if (circ->build_state && circ->build_state->chosen_exit && - circ->build_state->chosen_exit->identity_digest) { + !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); } @@ -2426,9 +2403,9 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len, } } else if (!strcasecmpstart(option, "cache=")) { option += strlen("cache="); - if (!strcmp(option, "no")) + if (!strcasecmp(option, "no")) cache = 0; - else if (!strcmp(option, "yes")) + else if (!strcasecmp(option, "yes")) cache = 1; else { connection_printf_to_buf(conn, "552 Unknown cache request \"%s\"\r\n", @@ -2610,17 +2587,17 @@ handle_control_resolve(control_connection_t *conn, uint32_t len, args = smartlist_create(); smartlist_split_string(args, body, " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - if (smartlist_len(args) && - !strcasecmp(smartlist_get(args, 0), "mode=reverse")) { - char *cp = smartlist_get(args, 0); - smartlist_del_keeporder(args, 0); - tor_free(cp); - is_reverse = 1; + { + const char *modearg = find_element_starting_with(args, 0, "mode="); + if (modearg && !strcasecmp(modearg, "mode=reverse")) + is_reverse = 1; } failed = smartlist_create(); SMARTLIST_FOREACH(args, const char *, arg, { - if (dnsserv_launch_request(arg, is_reverse)<0) - smartlist_add(failed, (char*)arg); + if (!is_keyval_pair(arg)) { + if (dnsserv_launch_request(arg, is_reverse)<0) + smartlist_add(failed, (char*)arg); + } }); send_control_done(conn); @@ -2710,7 +2687,6 @@ handle_control_usefeature(control_connection_t *conn, const char *body) { smartlist_t *args; - int verbose_names = 0, extended_events = 0; int bad = 0; (void) len; /* body is nul-terminated; it's safe to ignore the length */ args = smartlist_create(); @@ -2718,9 +2694,9 @@ handle_control_usefeature(control_connection_t *conn, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); SMARTLIST_FOREACH(args, const char *, arg, { if (!strcasecmp(arg, "VERBOSE_NAMES")) - verbose_names = 1; + ; else if (!strcasecmp(arg, "EXTENDED_EVENTS")) - extended_events = 1; + ; else { connection_printf_to_buf(conn, "552 Unrecognized feature \"%s\"\r\n", arg); @@ -2730,12 +2706,6 @@ handle_control_usefeature(control_connection_t *conn, }); if (!bad) { - if (verbose_names) { - conn->use_long_names = 1; - control_update_global_event_mask(); - } - if (extended_events) - conn->use_extended_events = 1; send_control_done(conn); } @@ -2885,9 +2855,10 @@ connection_control_process_inbuf(control_connection_t *conn) && !TOR_ISSPACE(conn->incoming_cmd[cmd_len])) ++cmd_len; - data_len -= cmd_len; conn->incoming_cmd[cmd_len]='\0'; 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') { ++args; --data_len; @@ -3039,20 +3010,11 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp, tor_free(reason); } - if (EVENT_IS_INTERESTING1S(EVENT_CIRCUIT_STATUS)) { - char *path = circuit_list_path(circ,0); - const char *sp = strlen(path) ? " " : ""; - send_control_event_extended(EVENT_CIRCUIT_STATUS, SHORT_NAMES, - "650 CIRC %lu %s%s%s@%s\r\n", - (unsigned long)circ->global_identifier, - status, sp, path, extended_buf); - tor_free(path); - } - if (EVENT_IS_INTERESTING1L(EVENT_CIRCUIT_STATUS)) { + { char *vpath = circuit_list_path_for_controller(circ); const char *sp = strlen(vpath) ? " " : ""; - send_control_event_extended(EVENT_CIRCUIT_STATUS, LONG_NAMES, - "650 CIRC %lu %s%s%s@%s\r\n", + send_control_event(EVENT_CIRCUIT_STATUS, ALL_FORMATS, + "650 CIRC %lu %s%s%s %s\r\n", (unsigned long)circ->global_identifier, status, sp, vpath, extended_buf); tor_free(vpath); @@ -3131,26 +3093,26 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, char *r = NULL; if (!reason_str) { r = tor_malloc(16); - tor_snprintf(r, 16, "UNKNOWN_%d", reason_code); + tor_snprintf(r, 16, " UNKNOWN_%d", reason_code); reason_str = r; } if (reason_code & END_STREAM_REASON_FLAG_REMOTE) tor_snprintf(reason_buf, sizeof(reason_buf), - "REASON=END REMOTE_REASON=%s", reason_str); + " REASON=END REMOTE_REASON=%s", reason_str); else tor_snprintf(reason_buf, sizeof(reason_buf), - "REASON=%s", reason_str); + " REASON=%s", reason_str); tor_free(r); } else if (reason_code && tp == STREAM_EVENT_REMAP) { switch (reason_code) { case REMAP_STREAM_SOURCE_CACHE: - strlcpy(reason_buf, "SOURCE=CACHE", sizeof(reason_buf)); + strlcpy(reason_buf, " SOURCE=CACHE", sizeof(reason_buf)); break; case REMAP_STREAM_SOURCE_EXIT: - strlcpy(reason_buf, "SOURCE=EXIT", sizeof(reason_buf)); + strlcpy(reason_buf, " SOURCE=EXIT", sizeof(reason_buf)); break; default: - tor_snprintf(reason_buf, sizeof(reason_buf), "REASON=UNKNOWN_%d", + tor_snprintf(reason_buf, sizeof(reason_buf), " REASON=UNKNOWN_%d", reason_code); /* XXX do we want SOURCE=UNKNOWN_%d above instead? -RD */ break; @@ -3158,8 +3120,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), "%sSOURCE_ADDR=%s:%d", - strlen(reason_buf) ? " " : "", + tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d", TO_CONN(conn)->address, TO_CONN(conn)->port ); } else { addrport_buf[0] = '\0'; @@ -3188,8 +3149,8 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, circ = circuit_get_by_edge_conn(conn); if (circ && CIRCUIT_IS_ORIGIN(circ)) origin_circ = TO_ORIGIN_CIRCUIT(circ); - send_control_event_extended(EVENT_STREAM_STATUS, ALL_NAMES, - "650 STREAM "U64_FORMAT" %s %lu %s@%s%s%s\r\n", + 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, origin_circ? (unsigned long)origin_circ->global_identifier : 0ul, @@ -3202,30 +3163,21 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, /** Figure out the best name for the target router of an OR connection * <b>conn</b>, and write it into the <b>len</b>-character buffer - * <b>name</b>. Use verbose names if <b>long_names</b> is set. */ + * <b>name</b>. */ static void -orconn_target_get_name(int long_names, - char *name, size_t len, or_connection_t *conn) -{ - if (! long_names) { - if (conn->nickname) - strlcpy(name, conn->nickname, len); - else - tor_snprintf(name, len, "%s:%d", - conn->_base.address, conn->_base.port); +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) { + tor_assert(len > MAX_VERBOSE_NICKNAME_LEN); + router_get_verbose_nickname(name, ri); + } else if (! tor_digest_is_zero(conn->identity_digest)) { + name[0] = '$'; + base16_encode(name+1, len-1, conn->identity_digest, + DIGEST_LEN); } else { - routerinfo_t *ri = router_get_by_digest(conn->identity_digest); - if (ri) { - tor_assert(len > MAX_VERBOSE_NICKNAME_LEN); - router_get_verbose_nickname(name, ri); - } else if (! tor_digest_is_zero(conn->identity_digest)) { - name[0] = '$'; - base16_encode(name+1, len-1, conn->identity_digest, - DIGEST_LEN); - } else { - tor_snprintf(name, len, "%s:%d", - conn->_base.address, conn->_base.port); - } + tor_snprintf(name, len, "%s:%d", + conn->_base.address, conn->_base.port); } } @@ -3264,24 +3216,13 @@ control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t tp, reason ? " " : "", ncircs); } - if (EVENT_IS_INTERESTING1S(EVENT_OR_CONN_STATUS)) { - orconn_target_get_name(0, name, sizeof(name), conn); - send_control_event_extended(EVENT_OR_CONN_STATUS, SHORT_NAMES, - "650 ORCONN %s %s@%s%s%s\r\n", - name, status, - reason ? "REASON=" : "", - orconn_end_reason_to_control_string(reason), - ncircs_buf); - } - if (EVENT_IS_INTERESTING1L(EVENT_OR_CONN_STATUS)) { - orconn_target_get_name(1, name, sizeof(name), conn); - send_control_event_extended(EVENT_OR_CONN_STATUS, LONG_NAMES, - "650 ORCONN %s %s@%s%s%s\r\n", - name, status, - reason ? "REASON=" : "", - orconn_end_reason_to_control_string(reason), - ncircs_buf); - } + orconn_target_get_name(name, sizeof(name), conn); + send_control_event(EVENT_OR_CONN_STATUS, ALL_FORMATS, + "650 ORCONN %s %s %s%s%s\r\n", + name, status, + reason ? "REASON=" : "", + orconn_end_reason_to_control_string(reason), + ncircs_buf); return 0; } @@ -3296,7 +3237,7 @@ control_event_stream_bandwidth(edge_connection_t *edge_conn) if (!edge_conn->n_read && !edge_conn->n_written) return 0; - send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_NAMES, + send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_FORMATS, "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n", U64_PRINTF_ARG(edge_conn->_base.global_identifier), (unsigned long)edge_conn->n_read, @@ -3325,7 +3266,7 @@ control_event_stream_bandwidth_used(void) if (!edge_conn->n_read && !edge_conn->n_written) continue; - send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_NAMES, + send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_FORMATS, "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n", U64_PRINTF_ARG(edge_conn->_base.global_identifier), (unsigned long)edge_conn->n_read, @@ -3345,7 +3286,7 @@ int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written) { if (EVENT_IS_INTERESTING(EVENT_BANDWIDTH_USED)) { - send_control_event(EVENT_BANDWIDTH_USED, ALL_NAMES, + send_control_event(EVENT_BANDWIDTH_USED, ALL_FORMATS, "650 BW %lu %lu\r\n", (unsigned long)n_read, (unsigned long)n_written); @@ -3415,7 +3356,7 @@ control_event_logmsg(int severity, uint32_t domain, const char *msg) default: s = "UnknownLogSeverity"; break; } ++disable_log_messages; - send_control_event(event, ALL_NAMES, "650 %s %s\r\n", s, b?b:msg); + send_control_event(event, ALL_FORMATS, "650 %s %s\r\n", s, b?b:msg); --disable_log_messages; tor_free(b); } @@ -3428,31 +3369,12 @@ control_event_logmsg(int severity, uint32_t domain, const char *msg) int control_event_descriptors_changed(smartlist_t *routers) { - size_t len; char *msg; - smartlist_t *identities = NULL; - char buf[HEX_DIGEST_LEN+1]; if (!EVENT_IS_INTERESTING(EVENT_NEW_DESC)) return 0; - if (EVENT_IS_INTERESTING1S(EVENT_NEW_DESC)) { - identities = smartlist_create(); - SMARTLIST_FOREACH(routers, routerinfo_t *, r, - { - base16_encode(buf,sizeof(buf),r->cache_info.identity_digest,DIGEST_LEN); - smartlist_add(identities, tor_strdup(buf)); - }); - } - if (EVENT_IS_INTERESTING1S(EVENT_NEW_DESC)) { - char *ids = smartlist_join_strings(identities, " ", 0, &len); - size_t ids_len = strlen(ids)+32; - msg = tor_malloc(ids_len); - tor_snprintf(msg, ids_len, "650 NEWDESC %s\r\n", ids); - send_control_event_string(EVENT_NEW_DESC, SHORT_NAMES|ALL_FORMATS, msg); - tor_free(ids); - tor_free(msg); - } - if (EVENT_IS_INTERESTING1L(EVENT_NEW_DESC)) { + + { smartlist_t *names = smartlist_create(); char *ids; size_t names_len; @@ -3465,16 +3387,12 @@ control_event_descriptors_changed(smartlist_t *routers) names_len = strlen(ids)+32; msg = tor_malloc(names_len); tor_snprintf(msg, names_len, "650 NEWDESC %s\r\n", ids); - send_control_event_string(EVENT_NEW_DESC, LONG_NAMES|ALL_FORMATS, msg); + send_control_event_string(EVENT_NEW_DESC, ALL_FORMATS, msg); tor_free(ids); tor_free(msg); SMARTLIST_FOREACH(names, char *, cp, tor_free(cp)); smartlist_free(names); } - if (identities) { - SMARTLIST_FOREACH(identities, char *, cp, tor_free(cp)); - smartlist_free(identities); - } return 0; } @@ -3491,17 +3409,17 @@ control_event_address_mapped(const char *from, const char *to, time_t expires, return 0; if (expires < 3 || expires == TIME_MAX) - send_control_event_extended(EVENT_ADDRMAP, ALL_NAMES, - "650 ADDRMAP %s %s NEVER@%s\r\n", from, to, + send_control_event(EVENT_ADDRMAP, ALL_FORMATS, + "650 ADDRMAP %s %s NEVER %s\r\n", from, to, error?error:""); else { char buf[ISO_TIME_LEN+1]; char buf2[ISO_TIME_LEN+1]; format_local_iso_time(buf,expires); format_iso_time(buf2,expires); - send_control_event_extended(EVENT_ADDRMAP, ALL_NAMES, + send_control_event(EVENT_ADDRMAP, ALL_FORMATS, "650 ADDRMAP %s %s \"%s\"" - "@%s%sEXPIRES=\"%s\"\r\n", + " %s%sEXPIRES=\"%s\"\r\n", from, to, buf, error?error:"", error?" ":"", buf2); @@ -3541,9 +3459,9 @@ control_event_or_authdir_new_descriptor(const char *action, buf = tor_malloc(totallen); strlcpy(buf, firstline, totallen); strlcpy(buf+strlen(firstline), esc, totallen); - send_control_event_string(EVENT_AUTHDIR_NEWDESCS, ALL_NAMES|ALL_FORMATS, + send_control_event_string(EVENT_AUTHDIR_NEWDESCS, ALL_FORMATS, buf); - send_control_event_string(EVENT_AUTHDIR_NEWDESCS, ALL_NAMES|ALL_FORMATS, + send_control_event_string(EVENT_AUTHDIR_NEWDESCS, ALL_FORMATS, "650 OK\r\n"); tor_free(esc); tor_free(buf); @@ -3581,8 +3499,8 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses, SMARTLIST_FOREACH(strs, char *, cp, tor_free(cp)); smartlist_free(strs); tor_free(s); - send_control_event_string(event, ALL_NAMES|ALL_FORMATS, esc); - send_control_event_string(event, ALL_NAMES|ALL_FORMATS, + send_control_event_string(event, ALL_FORMATS, esc); + send_control_event_string(event, ALL_FORMATS, "650 OK\r\n"); tor_free(esc); @@ -3608,6 +3526,55 @@ control_event_newconsensus(const networkstatus_t *consensus) consensus->routerstatus_list, EVENT_NEWCONSENSUS, "NEWCONSENSUS"); } +/** Called when we compute a new circuitbuildtimeout */ +int +control_event_buildtimeout_set(const circuit_build_times_t *cbt, + buildtimeout_set_event_t type) +{ + const char *type_string = NULL; + double qnt = circuit_build_times_quantile_cutoff(); + + if (!control_event_is_interesting(EVENT_BUILDTIMEOUT_SET)) + return 0; + + switch (type) { + case BUILDTIMEOUT_SET_EVENT_COMPUTED: + type_string = "COMPUTED"; + break; + case BUILDTIMEOUT_SET_EVENT_RESET: + type_string = "RESET"; + qnt = 1.0; + break; + case BUILDTIMEOUT_SET_EVENT_SUSPENDED: + type_string = "SUSPENDED"; + qnt = 1.0; + break; + case BUILDTIMEOUT_SET_EVENT_DISCARD: + type_string = "DISCARD"; + qnt = 1.0; + break; + case BUILDTIMEOUT_SET_EVENT_RESUME: + type_string = "RESUME"; + break; + default: + type_string = "UNKNOWN"; + break; + } + + send_control_event(EVENT_BUILDTIMEOUT_SET, ALL_FORMATS, + "650 BUILDTIMEOUT_SET %s TOTAL_TIMES=%lu " + "TIMEOUT_MS=%lu XM=%lu ALPHA=%lf CUTOFF_QUANTILE=%lf " + "TIMEOUT_RATE=%lf CLOSE_MS=%lu CLOSE_RATE=%lf\r\n", + type_string, (unsigned long)cbt->total_build_times, + (unsigned long)cbt->timeout_ms, + (unsigned long)cbt->Xm, cbt->alpha, qnt, + circuit_build_times_timeout_rate(cbt), + (unsigned long)cbt->close_ms, + circuit_build_times_close_rate(cbt)); + + return 0; +} + /** Called when a single local_routerstatus_t has changed: Sends an NS event * to any controller that cares. */ int @@ -3631,7 +3598,7 @@ control_event_networkstatus_changed_single(routerstatus_t *rs) int control_event_my_descriptor_changed(void) { - send_control_event(EVENT_DESCCHANGED, ALL_NAMES, "650 DESCCHANGED\r\n"); + send_control_event(EVENT_DESCCHANGED, ALL_FORMATS, "650 DESCCHANGED\r\n"); return 0; } @@ -3679,7 +3646,7 @@ control_event_status(int type, int severity, const char *format, va_list args) return -1; } - send_control_event_impl(type, ALL_NAMES|ALL_FORMATS, 0, format_buf, args); + send_control_event_impl(type, ALL_FORMATS, format_buf, args); return 0; } @@ -3743,7 +3710,7 @@ control_event_guard(const char *nickname, const char *digest, if (!EVENT_IS_INTERESTING(EVENT_GUARD)) return 0; - if (EVENT_IS_INTERESTING1L(EVENT_GUARD)) { + { char buf[MAX_VERBOSE_NICKNAME_LEN+1]; routerinfo_t *ri = router_get_by_digest(digest); if (ri) { @@ -3751,13 +3718,9 @@ control_event_guard(const char *nickname, const char *digest, } else { tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname); } - send_control_event(EVENT_GUARD, LONG_NAMES, + send_control_event(EVENT_GUARD, ALL_FORMATS, "650 GUARD ENTRY %s %s\r\n", buf, status); } - if (EVENT_IS_INTERESTING1S(EVENT_GUARD)) { - send_control_event(EVENT_GUARD, SHORT_NAMES, - "650 GUARD ENTRY $%s %s\r\n", hbuf, status); - } return 0; } @@ -4008,10 +3971,9 @@ control_event_bootstrap_problem(const char *warn, int reason) * from recently. Send a copy to the controller in case it wants to * display it for the user. */ void -control_event_clients_seen(const char *timestarted, const char *countries) +control_event_clients_seen(const char *controller_str) { send_control_event(EVENT_CLIENTS_SEEN, 0, - "650 CLIENTS_SEEN TimeStarted=\"%s\" CountrySummary=%s\r\n", - timestarted, countries); + "650 CLIENTS_SEEN %s\r\n", controller_str); } diff --git a/src/or/control.h b/src/or/control.h new file mode 100644 index 0000000000..27ef5c37f7 --- /dev/null +++ b/src/or/control.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file control.h + * \brief Header file for control.c. + **/ + +#ifndef _TOR_CONTROL_H +#define _TOR_CONTROL_H + +void control_update_global_event_mask(void); +void control_adjust_event_log_severity(void); + +/** Log information about the connection <b>conn</b>, protecting it as with + * CONN_LOG_PROTECT. Example: + * + * LOG_FN_CONN(conn, (LOG_DEBUG, "Socket %d wants to write", conn->s)); + **/ +#define LOG_FN_CONN(conn, args) \ + CONN_LOG_PROTECT(conn, log_fn args) + +int connection_control_finished_flushing(control_connection_t *conn); +int connection_control_reached_eof(control_connection_t *conn); +int connection_control_process_inbuf(control_connection_t *conn); + +#define EVENT_AUTHDIR_NEWDESCS 0x000D +#define EVENT_NS 0x000F +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, + stream_status_event_t e, + int reason); +int control_event_or_conn_status(or_connection_t *conn, + or_conn_status_event_t e, int reason); +int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written); +int control_event_stream_bandwidth(edge_connection_t *edge_conn); +int control_event_stream_bandwidth_used(void); +void control_event_logmsg(int severity, unsigned int domain, const char *msg); +int control_event_descriptors_changed(smartlist_t *routers); +int control_event_address_mapped(const char *from, const char *to, + time_t expires, const char *error); +int control_event_or_authdir_new_descriptor(const char *action, + const char *desc, + size_t desclen, + const char *msg); +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_general_status(int severity, const char *format, ...) + CHECK_PRINTF(2,3); +int control_event_client_status(int severity, const char *format, ...) + CHECK_PRINTF(2,3); +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_buildtimeout_set(const circuit_build_times_t *cbt, + buildtimeout_set_event_t type); + +int init_cookie_authentication(int enabled); +smartlist_t *decode_hashed_passwords(config_line_t *passwords); +void disable_control_logging(void); +void enable_control_logging(void); + +void control_event_bootstrap(bootstrap_status_t status, int progress); +void control_event_bootstrap_problem(const char *warn, int reason); + +void control_event_clients_seen(const char *controller_str); + +#ifdef CONTROL_PRIVATE +/* Used only by control.c and test.c */ +size_t write_escaped_data(const char *data, size_t len, char **out); +size_t read_escaped_data(const char *data, size_t len, char **out); +#endif + +#endif + diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index fde149978c..ae8d69f6ec 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -13,6 +13,15 @@ **/ #include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "config.h" +#include "connection.h" +#include "cpuworker.h" +#include "main.h" +#include "onion.h" +#include "router.h" /** The maximum number of cpuworker processes we will keep around. */ #define MAX_CPUWORKERS 16 @@ -183,7 +192,7 @@ connection_cpu_process_inbuf(connection_t *conn) tor_assert(0); /* don't ask me to do handshakes yet */ } -done_processing: + done_processing: conn->state = CPUWORKER_STATE_IDLE; num_cpuworkers_busy--; if (conn->timestamp_created < last_rotation_time) { @@ -358,7 +367,7 @@ spawn_cpuworker(void) static void spawn_enough_cpuworkers(void) { - int num_cpuworkers_needed = get_options()->NumCpus; + int num_cpuworkers_needed = get_options()->NumCPUs; if (num_cpuworkers_needed < MIN_CPUWORKERS) num_cpuworkers_needed = MIN_CPUWORKERS; diff --git a/src/or/cpuworker.h b/src/or/cpuworker.h new file mode 100644 index 0000000000..e09703f217 --- /dev/null +++ b/src/or/cpuworker.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file cpuworker.h + * \brief Header file for cpuworker.c. + **/ + +#ifndef _TOR_CPUWORKER_H +#define _TOR_CPUWORKER_H + +void cpu_init(void); +void cpuworkers_rotate(void); +int connection_cpu_finished_flushing(connection_t *conn); +int connection_cpu_reached_eof(connection_t *conn); +int connection_cpu_process_inbuf(connection_t *conn); +int assign_onionskin_to_cpuworker(connection_t *cpuworker, + or_circuit_t *circ, + char *onionskin); + +#endif + diff --git a/src/or/directory.c b/src/or/directory.c index 7ec97d48e0..fbdd496c12 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -4,6 +4,26 @@ /* See LICENSE for licensing information */ #include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "control.h" +#include "directory.h" +#include "dirserv.h" +#include "dirvote.h" +#include "geoip.h" +#include "main.h" +#include "networkstatus.h" +#include "policies.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" + #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) #ifndef OPENBSD #include <malloc.h> @@ -47,8 +67,10 @@ static void http_set_address_origin(const char *headers, connection_t *conn); static void connection_dir_download_networkstatus_failed( dir_connection_t *conn, int status_code); static void connection_dir_download_routerdesc_failed(dir_connection_t *conn); +static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn); static void connection_dir_download_cert_failed( dir_connection_t *conn, int status_code); +static void connection_dir_retry_bridges(smartlist_t *descs); static void dir_networkstatus_download_failed(smartlist_t *failed, int status_code); static void dir_routerdesc_download_failed(smartlist_t *failed, @@ -92,17 +114,19 @@ static void directory_initiate_command_rend(const char *address, #define ROUTERDESC_CACHE_LIFETIME (30*60) #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60) #define ROBOTS_CACHE_LIFETIME (24*60*60) +#define MICRODESC_CACHE_LIFETIME (48*60*60) /********* END VARIABLES ************/ -/** Return true iff the directory purpose 'purpose' must use an - * anonymous connection to a directory. */ +/** Return true iff the directory purpose <b>dir_purpose</b> (and if it's + * fetching descriptors, it's fetching them for <b>router_purpose</b>) + * must use an anonymous connection to a directory. */ static int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose) { if (get_options()->AllDirActionsPrivate) return 1; - if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit) + if (router_purpose == ROUTER_PURPOSE_BRIDGE && can_complete_circuit) return 1; /* if no circuits yet, we may need this info to bootstrap. */ if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR || dir_purpose == DIR_PURPOSE_UPLOAD_VOTE || @@ -230,7 +254,7 @@ directories_have_accepted_server_descriptor(void) /** Start a connection to every suitable directory authority, using * connection purpose 'purpose' and uploading the payload 'payload' - * (length 'payload_len'). The purpose should be one of + * (length 'payload_len'). dir_purpose should be one of * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'. * * <b>type</b> specifies what sort of dir authorities (V1, V2, @@ -560,7 +584,7 @@ connection_dir_request_failed(dir_connection_t *conn) if (directory_conn_is_self_reachability_test(conn)) { return; /* this was a test fetch. don't retry. */ } - if (entry_list_can_grow(get_options())) + if (!entry_list_is_constrained(get_options())) router_set_status(conn->identity_digest, 0); /* don't try him again */ if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) { log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", @@ -570,6 +594,8 @@ connection_dir_request_failed(dir_connection_t *conn) conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { log_info(LD_DIR, "Giving up on 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); @@ -614,7 +640,7 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn, * failed, and possibly retry them later.*/ smartlist_t *failed = smartlist_create(); dir_split_resource_into_fingerprints(conn->requested_resource+3, - failed, NULL, 0, 0); + failed, NULL, 0); if (smartlist_len(failed)) { dir_networkstatus_download_failed(failed, status_code); SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp)); @@ -623,6 +649,24 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn, } } +/** Helper: Attempt to fetch directly the descriptors of each bridge + * listed in <b>failed</b>. + */ +static void +connection_dir_retry_bridges(smartlist_t *descs) +{ + char digest[DIGEST_LEN]; + SMARTLIST_FOREACH(descs, const char *, cp, + { + if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) { + log_warn(LD_BUG, "Malformed fingerprint in list: %s", + escaped(cp)); + continue; + } + retry_bridge_descriptor_fetch_directly(digest); + }); +} + /** Called when an attempt to download one or more router descriptors * or extra-info documents on connection <b>conn</b> failed. */ @@ -640,6 +684,33 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn) (void) conn; } +/** Called when an attempt to download a bridge's routerdesc from + * one of the authorities failed due to a network error. If + * possible attempt to download descriptors from the bridge directly. + */ +static void +connection_dir_bridge_routerdesc_failed(dir_connection_t *conn) +{ + smartlist_t *which = NULL; + + /* Requests for bridge descriptors are in the form 'fp/', so ignore + anything else. */ + if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/")) + return; + + which = smartlist_create(); + dir_split_resource_into_fingerprints(conn->requested_resource + + strlen("fp/"), + which, NULL, 0); + + tor_assert(conn->_base.purpose != DIR_PURPOSE_FETCH_EXTRAINFO); + if (smartlist_len(which)) { + connection_dir_retry_bridges(which); + SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); + } + smartlist_free(which); +} + /** Called when an attempt to fetch a certificate fails. */ static void connection_dir_download_cert_failed(dir_connection_t *conn, int status) @@ -651,7 +722,7 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status) return; failed = smartlist_create(); dir_split_resource_into_fingerprints(conn->requested_resource+3, - failed, NULL, 1, 0); + failed, NULL, DSR_HEX); SMARTLIST_FOREACH(failed, char *, cp, { authority_cert_dl_failed(cp, status); @@ -667,7 +738,7 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status) * 1) If or_port is 0, or it's a direct conn and or_port is firewalled * or we're a dir mirror, no. * 2) If we prefer to avoid begindir conns, and we're not fetching or - * publishing a bridge relay descriptor, no. + * publishing a bridge relay descriptor, no. * 3) Else yes. */ static int @@ -746,6 +817,15 @@ 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)); + /* ensure that we don't make direct connections when a SOCKS server is + * configured. */ + if (!anonymized_connection && !use_begindir && !options->HTTPProxy && + (options->Socks4Proxy || options->Socks5Proxy)) { + log_warn(LD_DIR, "Cannot connect to a directory server through a " + "SOCKS proxy!"); + return; + } + conn = dir_connection_new(AF_INET); /* set up conn so it's got all the data we need to remember */ @@ -770,9 +850,9 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, if (!anonymized_connection && !use_begindir) { /* then we want to connect to dirport directly */ - if (options->HttpProxy) { - tor_addr_from_ipv4h(&addr, options->HttpProxyAddr); - dir_port = options->HttpProxyPort; + if (options->HTTPProxy) { + tor_addr_copy(&addr, &options->HTTPProxyAddr); + dir_port = options->HTTPProxyPort; } switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr, @@ -793,7 +873,7 @@ 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), EV_READ | EV_WRITE); + connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT); /* writable indicates finish, readable indicates broken link, error indicates broken link in windowsland. */ } @@ -832,7 +912,7 @@ 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), EV_READ | EV_WRITE); + connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT); connection_start_reading(TO_CONN(linked_conn)); } } @@ -880,7 +960,7 @@ directory_get_consensus_url(int supports_conditional_consensus) if (supports_conditional_consensus) { char *authority_id_list; - smartlist_t *authority_digets = smartlist_create(); + smartlist_t *authority_digests = smartlist_create(); SMARTLIST_FOREACH(router_get_trusted_dir_servers(), trusted_dir_server_t *, ds, @@ -892,10 +972,10 @@ directory_get_consensus_url(int supports_conditional_consensus) hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1); base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1, ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN); - smartlist_add(authority_digets, hex); + smartlist_add(authority_digests, hex); }); - smartlist_sort(authority_digets, _compare_strs); - authority_id_list = smartlist_join_strings(authority_digets, + smartlist_sort(authority_digests, _compare_strs); + authority_id_list = smartlist_join_strings(authority_digests, "+", 0, NULL); len = strlen(authority_id_list)+64; @@ -903,8 +983,8 @@ directory_get_consensus_url(int supports_conditional_consensus) tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z", authority_id_list); - SMARTLIST_FOREACH(authority_digets, char *, cp, tor_free(cp)); - smartlist_free(authority_digets); + 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"); @@ -913,7 +993,7 @@ directory_get_consensus_url(int supports_conditional_consensus) } /** Queue an appropriate HTTP command on conn-\>outbuf. The other args - * are as in directory_initiate_command. + * are as in directory_initiate_command(). */ static void directory_send_command(dir_connection_t *conn, @@ -956,9 +1036,9 @@ directory_send_command(dir_connection_t *conn, } /* come up with some proxy lines, if we're using one. */ - if (direct && get_options()->HttpProxy) { + if (direct && get_options()->HTTPProxy) { char *base64_authenticator=NULL; - const char *authenticator = get_options()->HttpProxyAuthenticator; + const char *authenticator = get_options()->HTTPProxyAuthenticator; tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring); if (authenticator) { @@ -1049,31 +1129,10 @@ directory_send_command(dir_connection_t *conn, httpcommand = "POST"; url = tor_strdup("/tor/post/consensus-signature"); break; - case DIR_PURPOSE_FETCH_RENDDESC: - tor_assert(resource); - tor_assert(!payload); - - /* this must be true or we wouldn't be doing the lookup */ - tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN_BASE32); - /* This breaks the function abstraction. */ - conn->rend_data = tor_malloc_zero(sizeof(rend_data_t)); - strlcpy(conn->rend_data->onion_address, resource, - sizeof(conn->rend_data->onion_address)); - conn->rend_data->rend_desc_version = 0; - - httpcommand = "GET"; - /* Request the most recent versioned descriptor. */ - // (XXXX We were going to switch this to fetch rendezvous1 descriptors, - // but that never got testing, and it wasn't a good design.) - len = strlen(resource)+32; - url = tor_malloc(len); - tor_snprintf(url, len, "/tor/rendezvous/%s", resource); - break; case DIR_PURPOSE_FETCH_RENDDESC_V2: tor_assert(resource); tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32); tor_assert(!payload); - conn->rend_data->rend_desc_version = 2; httpcommand = "GET"; len = strlen(resource) + 32; url = tor_malloc(len); @@ -1162,7 +1221,7 @@ parse_http_url(const char *headers, char **url) if (s-tmp >= 3 && !strcmpstart(tmp,"://")) { tmp = strchr(tmp+3, '/'); if (tmp && tmp < s) { - log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string"); + log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string"); start = tmp; } } @@ -1478,21 +1537,22 @@ connection_dir_client_reached_eof(dir_connection_t *conn) } (void) skewed; /* skewed isn't used yet. */ - if (status_code == 503 && body_len < 16) { - routerstatus_t *rs; - trusted_dir_server_t *ds; - 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))) - rs->last_dir_503_at = now; - if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest))) - ds->fake_status.last_dir_503_at = now; + if (status_code == 503) { + if (body_len < 16) { + routerstatus_t *rs; + trusted_dir_server_t *ds; + 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))) + rs->last_dir_503_at = now; + if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest))) + ds->fake_status.last_dir_503_at = now; - tor_free(body); tor_free(headers); tor_free(reason); - return -1; - } else if (status_code == 503) { + tor_free(body); tor_free(headers); tor_free(reason); + return -1; + } /* XXXX022 Remove this once every server with bug 539 is obsolete. */ log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included " "a body anyway. We'll pretend it gave us a 200.", @@ -1564,7 +1624,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) v2_networkstatus_source_t source; char *cp; log_info(LD_DIR,"Received networkstatus objects (size %d) from server " - "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port); + "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port); if (status_code != 200) { log_warn(LD_DIR, "Received http status code %d (%s) from server " @@ -1580,7 +1640,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) source = NS_FROM_DIR_BY_FP; which = smartlist_create(); dir_split_resource_into_fingerprints(conn->requested_resource+3, - which, NULL, 0, 0); + which, NULL, 0); } else if (conn->requested_resource && !strcmpstart(conn->requested_resource, "all")) { source = NS_FROM_DIR_ALL; @@ -1638,8 +1698,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) 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, 0))<0) { + "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port); + if ((r=networkstatus_set_current_consensus(body, "ns", 0))<0) { log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR, "Unable to load consensus directory downloaded from " "server '%s:%d'. I'll try again soon.", @@ -1666,9 +1726,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn) return -1; } log_info(LD_DIR,"Received authority certificates (size %d) from server " - "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port); + "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port); if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) { log_warn(LD_DIR, "Unable to parse fetched certificates"); + /* if we fetched more than one and only some failed, the successful + * ones got flushed to disk so it's safe to call this on them */ connection_dir_download_cert_failed(conn, status_code); } else { directory_info_has_arrived(now, 0); @@ -1679,7 +1741,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) const char *msg; int st; log_info(LD_DIR,"Got votes (size %d) from server %s:%d", - (int) body_len, conn->_base.address, conn->_base.port); + (int)body_len, conn->_base.address, conn->_base.port); if (status_code != 200) { log_warn(LD_DIR, "Received http status code %d (%s) from server " @@ -1699,11 +1761,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) { const char *msg = NULL; log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d", - (int) body_len, conn->_base.address, conn->_base.port); + (int)body_len, conn->_base.address, conn->_base.port); if (status_code != 200) { log_warn(LD_DIR, - "Received http status code %d (%s) from server " - "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".", + "Received http status code %d (%s) from server '%s:%d' while fetching " + "\"/tor/status-vote/next/consensus-signatures.z\".", status_code, escaped(reason), conn->_base.address, conn->_base.port); tor_free(body); tor_free(headers); tor_free(reason); @@ -1731,7 +1793,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) which = smartlist_create(); dir_split_resource_into_fingerprints(conn->requested_resource + (descriptor_digests ? 2 : 3), - which, NULL, 0, 0); + which, NULL, 0); n_asked_for = smartlist_len(which); } if (status_code != 200) { @@ -1919,7 +1981,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) /* Success, or at least there's a v2 descriptor already * present. Notify pending connections about this. */ conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; - rend_client_desc_trynow(conn->rend_data->onion_address, -1); + rend_client_desc_trynow(conn->rend_data->onion_address); } break; case 404: @@ -1966,7 +2028,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_REND, "Successfully fetched v2 rendezvous " "descriptor."); conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; - rend_client_desc_trynow(conn->rend_data->onion_address, -1); + rend_client_desc_trynow(conn->rend_data->onion_address); break; } break; @@ -2009,12 +2071,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "'%s:%d'. Malformed rendezvous descriptor?", escaped(reason), conn->_base.address, conn->_base.port); break; - case 503: - log_info(LD_REND,"http status 503 (%s) response from dirserver " - "'%s:%d'. Node is (currently) not acting as v2 hidden " - "service directory.", - escaped(reason), conn->_base.address, conn->_base.port); - break; default: log_warn(LD_REND,"http status %d (%s) response unexpected (server " "'%s:%d').", @@ -2321,7 +2377,7 @@ directory_dump_request_log(void) } #endif -/** Decide whether a client would accept the consensus we have +/** Decide whether a client would accept the consensus we have. * * Clients can say they only want a consensus if it's signed by more * than half the authorities in a list. They pass this list in @@ -2342,31 +2398,32 @@ client_likes_consensus(networkstatus_t *v, const char *want_url) int need_at_least; int have = 0; - dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0, 0); + dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0); need_at_least = smartlist_len(want_authorities)/2+1; - SMARTLIST_FOREACH(want_authorities, const char *, d, { + SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) { char want_digest[DIGEST_LEN]; size_t want_len = strlen(d)/2; if (want_len > DIGEST_LEN) want_len = DIGEST_LEN; if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) { - log_warn(LD_DIR,"Failed to decode requested authority digest %s.", d); + log_fn(LOG_PROTOCOL_WARN, LD_DIR, + "Failed to decode requested authority digest %s.", d); continue; }; - SMARTLIST_FOREACH(v->voters, networkstatus_voter_info_t *, vi, { - if (vi->signature && + SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) { + if (smartlist_len(vi->sigs) && !memcmp(vi->identity_digest, want_digest, want_len)) { have++; break; }; - }); + } SMARTLIST_FOREACH_END(vi); /* early exit, if we already have enough */ if (have >= need_at_least) break; - }); + } SMARTLIST_FOREACH_END(d); SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d)); smartlist_free(want_authorities); @@ -2513,9 +2570,12 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, /* v2 or v3 network status fetch. */ smartlist_t *dir_fps = smartlist_create(); int is_v3 = !strcmpstart(url, "/tor/status-vote"); + geoip_client_action_t act = + is_v3 ? GEOIP_CLIENT_NETWORKSTATUS : GEOIP_CLIENT_NETWORKSTATUS_V2; const char *request_type = NULL; const char *key = url + strlen("/tor/status/"); long lifetime = NETWORKSTATUS_CACHE_LIFETIME; + if (!is_v3) { dirserv_get_networkstatus_v2_fingerprints(dir_fps, key); if (!strcmpstart(key, "fp/")) @@ -2530,18 +2590,44 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, } else { networkstatus_t *v = networkstatus_get_latest_consensus(); time_t now = time(NULL); + const char *want_fps = NULL; + char *flavor = NULL; #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/" - if (v && - !strcmpstart(url, CONSENSUS_URL_PREFIX) && - !client_likes_consensus(v, url + strlen(CONSENSUS_URL_PREFIX))) { + #define CONSENSUS_FLAVORED_PREFIX "/tor/status-vote/current/consensus-" + /* figure out the flavor if any, and who we wanted to sign the thing */ + if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) { + const char *f, *cp; + f = url + strlen(CONSENSUS_FLAVORED_PREFIX); + cp = strchr(f, '/'); + if (cp) { + want_fps = cp+1; + flavor = tor_strndup(f, cp-f); + } else { + flavor = tor_strdup(f); + } + } else { + if (!strcmpstart(url, CONSENSUS_URL_PREFIX)) + want_fps = url+strlen(CONSENSUS_URL_PREFIX); + } + + /* XXXX MICRODESC NM NM should check document of correct flavor */ + if (v && want_fps && + !client_likes_consensus(v, want_fps)) { write_http_status_line(conn, 404, "Consensus not signed by sufficient " "number of requested authorities"); smartlist_free(dir_fps); + geoip_note_ns_response(act, GEOIP_REJECT_NOT_ENOUGH_SIGS); + tor_free(flavor); goto done; } - smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0", 20)); + { + char *fp = tor_malloc_zero(DIGEST_LEN); + if (flavor) + strlcpy(fp, flavor, DIGEST_LEN); + tor_free(flavor); + smartlist_add(dir_fps, fp); + } request_type = compressed?"v3.z":"v3"; lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0; } @@ -2549,6 +2635,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */ write_http_status_line(conn, 503, "Network status object unavailable"); smartlist_free(dir_fps); + geoip_note_ns_response(act, GEOIP_REJECT_UNAVAILABLE); goto done; } @@ -2556,11 +2643,13 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, write_http_status_line(conn, 404, "Not found"); SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp)); smartlist_free(dir_fps); + geoip_note_ns_response(act, GEOIP_REJECT_NOT_FOUND); goto done; } else if (!smartlist_len(dir_fps)) { write_http_status_line(conn, 304, "Not modified"); SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp)); smartlist_free(dir_fps); + geoip_note_ns_response(act, GEOIP_REJECT_NOT_MODIFIED); goto done; } @@ -2572,18 +2661,25 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, write_http_status_line(conn, 503, "Directory busy, try again later"); SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp)); smartlist_free(dir_fps); + geoip_note_ns_response(act, GEOIP_REJECT_BUSY); goto done; } -#ifdef ENABLE_GEOIP_STATS { - geoip_client_action_t act = - is_v3 ? GEOIP_CLIENT_NETWORKSTATUS : GEOIP_CLIENT_NETWORKSTATUS_V2; struct in_addr in; - if (tor_inet_aton((TO_CONN(conn))->address, &in)) + if (tor_inet_aton((TO_CONN(conn))->address, &in)) { geoip_note_client_seen(act, ntohl(in.s_addr), time(NULL)); + geoip_note_ns_response(act, GEOIP_SUCCESS); + /* Note that a request for a network status has started, so that we + * can measure the download time later on. */ + if (TO_CONN(conn)->dirreq_id) + geoip_start_dirreq(TO_CONN(conn)->dirreq_id, dlen, act, + DIRREQ_TUNNELED); + else + geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen, act, + DIRREQ_DIRECT); + } } -#endif // note_request(request_type,dlen); (void) request_type; @@ -2619,7 +2715,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, const char *item; tor_assert(!current); /* we handle current consensus specially above, * since it wants to be spooled. */ - if ((item = dirvote_get_pending_consensus())) + if ((item = dirvote_get_pending_consensus(FLAV_NS))) smartlist_add(items, (char*)item); } else if (!current && !strcmp(url, "consensus-signatures")) { /* XXXX the spec says that we should implement @@ -2645,7 +2741,8 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, flags = DGV_BY_ID | (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING); } - dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1); + dir_split_resource_into_fingerprints(url, fps, NULL, + DSR_HEX|DSR_SORT_UNIQ); SMARTLIST_FOREACH(fps, char *, fp, { if ((d = dirvote_get_vote(fp, flags))) smartlist_add(dir_items, (cached_dir_t*)d); @@ -2698,6 +2795,41 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, goto done; } + if (!strcmpstart(url, "/tor/micro/d/")) { + smartlist_t *fps = smartlist_create(); + + dir_split_resource_into_fingerprints(url+strlen("/tor/micro/d/"), + fps, NULL, + DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ); + + if (!dirserv_have_any_microdesc(fps)) { + write_http_status_line(conn, 404, "Not found"); + SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp)); + smartlist_free(fps); + goto done; + } + dlen = dirserv_estimate_microdesc_size(fps, compressed); + if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) { + log_info(LD_DIRSERV, + "Client asked for server descriptors, but we've been " + "writing too many bytes lately. Sending 503 Dir busy."); + write_http_status_line(conn, 503, "Directory busy, try again later"); + SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp)); + smartlist_free(fps); + goto done; + } + + write_http_response_header(conn, -1, compressed, MICRODESC_CACHE_LIFETIME); + conn->dir_spool_src = DIR_SPOOL_MICRODESC; + conn->fingerprint_stack = fps; + + if (compressed) + conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD); + + connection_dirserv_flushed_some(conn); + goto done; + } + if (!strcmpstart(url,"/tor/server/") || (!options->BridgeAuthoritativeDir && !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) { @@ -2779,7 +2911,8 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, } else if (!strcmpstart(url, "/tor/keys/fp/")) { smartlist_t *fps = smartlist_create(); dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"), - fps, NULL, 1, 1); + fps, NULL, + DSR_HEX|DSR_SORT_UNIQ); SMARTLIST_FOREACH(fps, char *, d, { authority_cert_t *c = authority_cert_get_newest_by_id(d); if (c) smartlist_add(certs, c); @@ -2789,7 +2922,8 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, } else if (!strcmpstart(url, "/tor/keys/sk/")) { smartlist_t *fps = smartlist_create(); dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"), - fps, NULL, 1, 1); + fps, NULL, + DSR_HEX|DSR_SORT_UNIQ); SMARTLIST_FOREACH(fps, char *, d, { authority_cert_t *c = authority_cert_get_by_sk_digest(d); if (c) smartlist_add(certs, c); @@ -2891,18 +3025,9 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, note_request("/tor/rendezvous?/", desc_len); /* need to send descp separately, because it may include NULs */ connection_write_to_buf(descp, desc_len, TO_CONN(conn)); - /* report successful fetch to statistic */ - if (options->HSAuthorityRecordStats) { - hs_usage_note_fetch_total(query, time(NULL)); - hs_usage_note_fetch_successful(query, time(NULL)); - } break; case 0: /* well-formed but not present */ write_http_status_line(conn, 404, "Not found"); - /* report (unsuccessful) fetch to statistic */ - if (options->HSAuthorityRecordStats) { - hs_usage_note_fetch_total(query, time(NULL)); - } break; case -1: /* not well-formed */ write_http_status_line(conn, 400, "Bad request"); @@ -3179,8 +3304,8 @@ directory_handle_command(dir_connection_t *conn) &body, &body_len, MAX_DIR_UL_SIZE, 0)) { case -1: /* overflow */ log_warn(LD_DIRSERV, - "Invalid input from address '%s'. Closing.", - conn->_base.address); + "Request too large from address '%s' to DirPort. Closing.", + safe_str(conn->_base.address)); return -1; case 0: log_debug(LD_DIRSERV,"command not all here yet."); @@ -3216,6 +3341,16 @@ connection_dir_finished_flushing(dir_connection_t *conn) tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_DIR); + /* Note that we have finished writing the directory response. For direct + * connections this means we're done, for tunneled connections its only + * an intermediate step. */ + if (TO_CONN(conn)->dirreq_id) + geoip_change_dirreq_state(TO_CONN(conn)->dirreq_id, DIRREQ_TUNNELED, + DIRREQ_FLUSHING_DIR_CONN_FINISHED); + else + geoip_change_dirreq_state(TO_CONN(conn)->global_identifier, + DIRREQ_DIRECT, + DIRREQ_FLUSHING_DIR_CONN_FINISHED); switch (conn->_base.state) { case DIR_CONN_STATE_CLIENT_SENDING: log_debug(LD_DIR,"client finished sending command."); @@ -3398,6 +3533,14 @@ download_status_reset(download_status_t *dls) dls->next_attempt_at = time(NULL) + schedule[0]; } +/** Return the number of failures on <b>dls</b> since the last success (if + * any). */ +int +download_status_get_n_failures(const download_status_t *dls) +{ + return dls->n_download_failures; +} + /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>) * fetches have failed (with uppercase fingerprints listed in <b>failed</b>, * either as descriptor digests or as identity digests based on @@ -3413,16 +3556,8 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code, int server = directory_fetches_from_authorities(get_options()); if (!was_descriptor_digests) { if (router_purpose == ROUTER_PURPOSE_BRIDGE) { - tor_assert(!was_extrainfo); /* not supported yet */ - SMARTLIST_FOREACH(failed, const char *, cp, - { - if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) { - log_warn(LD_BUG, "Malformed fingerprint in list: %s", - escaped(cp)); - continue; - } - retry_bridge_descriptor_fetch_directly(digest); - }); + tor_assert(!was_extrainfo); + connection_dir_retry_bridges(failed); } return; /* FFFF should implement for other-than-router-purpose someday */ } @@ -3515,19 +3650,37 @@ dir_split_resource_into_fingerprint_pairs(const char *res, /** Given a directory <b>resource</b> request, containing zero * or more strings separated by plus signs, followed optionally by ".z", store * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is - * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If - * decode_hex is true, then delete all elements that aren't hex digests, and - * decode the rest. If sort_uniq is true, then sort the list and remove - * all duplicates. + * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. + * + * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and + * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as + * a separator, delete all the elements that aren't base64-encoded digests, + * and decode the rest. If (flags & DSR_DIGEST256), these digests should be + * 256 bits long; else they should be 160. + * + * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates. */ int dir_split_resource_into_fingerprints(const char *resource, smartlist_t *fp_out, int *compressed_out, - int decode_hex, int sort_uniq) + int flags) { + const int decode_hex = flags & DSR_HEX; + const int decode_base64 = flags & DSR_BASE64; + const int digests_are_256 = flags & DSR_DIGEST256; + const int sort_uniq = flags & DSR_SORT_UNIQ; + + const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN; + const int hex_digest_len = digests_are_256 ? + HEX_DIGEST256_LEN : HEX_DIGEST_LEN; + const int base64_digest_len = digests_are_256 ? + BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN; smartlist_t *fp_tmp = smartlist_create(); + + tor_assert(!(decode_hex && decode_base64)); tor_assert(fp_out); - smartlist_split_string(fp_tmp, resource, "+", 0, 0); + + smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0); if (compressed_out) *compressed_out = 0; if (smartlist_len(fp_tmp)) { @@ -3539,22 +3692,25 @@ dir_split_resource_into_fingerprints(const char *resource, *compressed_out = 1; } } - if (decode_hex) { + if (decode_hex || decode_base64) { + const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len; int i; char *cp, *d = NULL; for (i = 0; i < smartlist_len(fp_tmp); ++i) { cp = smartlist_get(fp_tmp, i); - if (strlen(cp) != HEX_DIGEST_LEN) { + if (strlen(cp) != encoded_len) { log_info(LD_DIR, "Skipping digest %s with non-standard length.", escaped(cp)); smartlist_del_keeporder(fp_tmp, i--); goto again; } - d = tor_malloc_zero(DIGEST_LEN); - if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) { - log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp)); - smartlist_del_keeporder(fp_tmp, i--); - goto again; + d = tor_malloc_zero(digest_len); + if (decode_hex ? + (base16_decode(d, digest_len, cp, hex_digest_len)<0) : + (base64_decode(d, digest_len, cp, base64_digest_len)<0)) { + log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp)); + smartlist_del_keeporder(fp_tmp, i--); + goto again; } smartlist_set(fp_tmp, i, d); d = NULL; @@ -3564,26 +3720,18 @@ dir_split_resource_into_fingerprints(const char *resource, } } if (sort_uniq) { - smartlist_t *fp_tmp2 = smartlist_create(); - int i; - if (decode_hex) - smartlist_sort_digests(fp_tmp); - else + if (decode_hex || decode_base64) { + if (digests_are_256) { + smartlist_sort_digests256(fp_tmp); + smartlist_uniq_digests256(fp_tmp); + } else { + smartlist_sort_digests(fp_tmp); + smartlist_uniq_digests(fp_tmp); + } + } else { smartlist_sort_strings(fp_tmp); - if (smartlist_len(fp_tmp)) - smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0)); - for (i = 1; i < smartlist_len(fp_tmp); ++i) { - char *cp = smartlist_get(fp_tmp, i); - char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1); - - if ((decode_hex && memcmp(cp, last, DIGEST_LEN)) - || (!decode_hex && strcasecmp(cp, last))) - smartlist_add(fp_tmp2, cp); - else - tor_free(cp); + smartlist_uniq_strings(fp_tmp); } - smartlist_free(fp_tmp); - fp_tmp = fp_tmp2; } smartlist_add_all(fp_out, fp_tmp); smartlist_free(fp_tmp); diff --git a/src/or/directory.h b/src/or/directory.h new file mode 100644 index 0000000000..6fd2c0beff --- /dev/null +++ b/src/or/directory.h @@ -0,0 +1,110 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file directory.h + * \brief Header file for directory.c. + **/ + +#ifndef _TOR_DIRECTORY_H +#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, + size_t payload_len, size_t extrainfo_len); +void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, + const char *resource, + int pds_flags); +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, + uint8_t dir_purpose, + uint8_t router_purpose, + int anonymized_connection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since); +void directory_initiate_command_routerstatus_rend(routerstatus_t *status, + uint8_t dir_purpose, + uint8_t router_purpose, + int anonymized_connection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since, + const rend_data_t *rend_query); + +int parse_http_response(const char *headers, int *code, time_t *date, + compress_method_t *compression, char **response); + +int connection_dir_is_encrypted(dir_connection_t *conn); +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 directory_initiate_command(const char *address, const tor_addr_t *addr, + uint16_t or_port, uint16_t dir_port, + int supports_conditional_consensus, + int supports_begindir, const char *digest, + uint8_t dir_purpose, uint8_t router_purpose, + int anonymized_connection, + const char *resource, + const char *payload, size_t payload_len, + time_t if_modified_since); + +#define DSR_HEX (1<<0) +#define DSR_BASE64 (1<<1) +#define DSR_DIGEST256 (1<<2) +#define DSR_SORT_UNIQ (1<<3) +int dir_split_resource_into_fingerprints(const char *resource, + smartlist_t *fp_out, int *compressed_out, + int flags); + +int dir_split_resource_into_fingerprint_pairs(const char *res, + smartlist_t *pairs_out); +char *directory_dump_request_log(void); +void note_request(const char *key, size_t bytes); +int router_supports_extrainfo(const char *identity_digest, int is_authority); + +time_t download_status_increment_failure(download_status_t *dls, + int status_code, const char *item, + int server, time_t now); +/** Increment the failure count of the download_status_t <b>dls</b>, with + * the optional status code <b>sc</b>. */ +#define download_status_failed(dls, sc) \ + download_status_increment_failure((dls), (sc), NULL, \ + get_options()->DirPort, time(NULL)) + +void download_status_reset(download_status_t *dls); +static int download_status_is_ready(download_status_t *dls, time_t now, + int max_failures); +/** Return true iff, as of <b>now</b>, the resource tracked by <b>dls</b> is + * ready to get its download reattempted. */ +static INLINE int +download_status_is_ready(download_status_t *dls, time_t now, + int max_failures) +{ + return (dls->n_download_failures <= max_failures + && dls->next_attempt_at <= now); +} + +static void download_status_mark_impossible(download_status_t *dl); +/** Mark <b>dl</b> as never downloadable. */ +static INLINE void +download_status_mark_impossible(download_status_t *dl) +{ + dl->n_download_failures = IMPOSSIBLE_TO_DOWNLOAD; +} + +int download_status_get_n_failures(const download_status_t *dls); + +#endif + diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 851fc5cbdd..841c86624b 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -5,6 +5,22 @@ #define DIRSERV_PRIVATE #include "or.h" +#include "buffers.h" +#include "config.h" +#include "connection.h" +#include "connection_or.h" +#include "control.h" +#include "directory.h" +#include "dirserv.h" +#include "dirvote.h" +#include "hibernate.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "policies.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" /** * \file dirserv.c @@ -41,7 +57,7 @@ static time_t the_v2_networkstatus_is_dirty = 1; static cached_dir_t *the_directory = NULL; /** For authoritative directories: the current (v1) network status. */ -static cached_dir_t the_runningrouters = { NULL, NULL, 0, 0, 0, -1 }; +static cached_dir_t the_runningrouters; static void directory_remove_invalid(void); static cached_dir_t *dirserv_regenerate_directory(void); @@ -63,13 +79,16 @@ static signed_descriptor_t *get_signed_descriptor_by_fp(const char *fp, time_t publish_cutoff); static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg); +/************** Measured Bandwidth parsing code ******/ +#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */ + /************** Fingerprint handling code ************/ #define FP_NAMED 1 /**< Listed in fingerprint file. */ #define FP_INVALID 2 /**< Believed invalid. */ #define FP_REJECT 4 /**< We will not publish this router. */ #define FP_BADDIR 8 /**< We'll tell clients to avoid using this as a dir. */ -#define FP_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */ +#define FP_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */ #define FP_UNNAMED 32 /**< Another router has this name in fingerprint file. */ /** Encapsulate a nickname and an FP_* status; target of status_by_digest @@ -99,7 +118,7 @@ authdir_config_new(void) return list; } -/** Add the fingerprint <b>fp</b> for the nickname <b>nickname</b> to +/** Add the fingerprint <b>fp</b> for <b>nickname</b> to * the smartlist of fingerprint_entry_t's <b>list</b>. Return 0 if it's * new, or 1 if we replaced the old value. */ @@ -181,8 +200,7 @@ dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk) * file. The file format is line-based, with each non-blank holding one * nickname, some space, and a fingerprint for that nickname. On success, * replace the current fingerprint list with the new list and return 0. On - * failure, leave the current fingerprint list untouched, and - * return -1. */ + * failure, leave the current fingerprint list untouched, and return -1. */ int dirserv_load_fingerprint_file(void) { @@ -368,13 +386,19 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, strmap_size(fingerprint_list->fp_by_name), digestmap_size(fingerprint_list->status_by_digest)); - /* 0.1.1.17-rc was the first version that claimed to be stable, doesn't - * crash and drop circuits all the time, and is even vaguely compatible with - * the current network */ - if (platform && !tor_version_as_new_as(platform,"0.1.1.17-rc")) { + /* Tor 0.2.0.26-rc is the oldest version that currently caches the right + * directory information. Once more of them die off, we should raise this + * minimum. */ + if (platform && !tor_version_as_new_as(platform,"0.2.0.26-rc")) { if (msg) *msg = "Tor version is far too old to work."; return FP_REJECT; + } else if (platform && tor_version_as_new_as(platform,"0.2.1.3-alpha") + && !tor_version_as_new_as(platform, "0.2.1.19")) { + /* These versions mishandled RELAY_EARLY cells on rend circuits. */ + if (msg) + *msg = "Tor version is too buggy to work."; + return FP_REJECT; } result = dirserv_get_name_status(id_digest, nickname); @@ -520,7 +544,7 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, /* Okay. Now check whether the fingerprint is recognized. */ uint32_t status = dirserv_router_get_status(ri, msg); time_t now; - int severity = complain ? LOG_NOTICE : LOG_INFO; + int severity = (complain && ri->contact_info) ? LOG_NOTICE : LOG_INFO; tor_assert(msg); if (status & FP_REJECT) return -1; /* msg is already set. */ @@ -712,6 +736,10 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) desc = tor_strndup(ri->cache_info.signed_descriptor_body, desclen); nickname = tor_strdup(ri->nickname); + /* Tell if we're about to need to launch a test if we add this. */ + ri->needs_retest_if_added = + dirserv_should_launch_reachability_test(ri, ri_old); + r = router_add_to_routerlist(ri, msg, 0, 0); if (!WRA_WAS_ADDED(r)) { /* unless the routerinfo was fine, just out-of-date */ @@ -726,7 +754,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) changed = smartlist_create(); smartlist_add(changed, ri); - control_event_descriptors_changed(changed); + routerlist_descriptors_added(changed, 0); smartlist_free(changed); if (!*msg) { *msg = ri->is_valid ? "Descriptor for valid server accepted" : @@ -835,46 +863,6 @@ directory_remove_invalid(void) routerlist_assert_ok(rl); } -/** Write a list of unregistered descriptors into a newly allocated - * string and return it. Used by dirserv operators to keep track of - * fast nodes that haven't registered. - */ -int -getinfo_helper_dirserv_unregistered(control_connection_t *control_conn, - const char *question, char **answer_out) -{ - smartlist_t *answerlist; - char buf[1024]; - char *answer; - int min_bw = atoi(question); - routerlist_t *rl = router_get_routerlist(); - - (void) control_conn; - - if (strcmpstart(question, "unregistered-servers-")) - return 0; - question += strlen("unregistered-servers-"); - - answerlist = smartlist_create(); - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ent, { - uint32_t r = dirserv_router_get_status(ent, NULL); - if (router_get_advertised_bandwidth(ent) >= (size_t)min_bw && - !(r & FP_NAMED)) { - /* then log this one */ - tor_snprintf(buf, sizeof(buf), - "%s: BW %d on '%s'.", - ent->nickname, router_get_advertised_bandwidth(ent), - ent->platform ? ent->platform : ""); - smartlist_add(answerlist, tor_strdup(buf)); - } - }); - answer = smartlist_join_strings(answerlist, "\r\n", 0, NULL); - SMARTLIST_FOREACH(answerlist, char *, cp, tor_free(cp)); - smartlist_free(answerlist); - *answer_out = answer; - return 0; -} - /** Mark the directory as <b>dirty</b> -- when we're next asked for a * directory, we will rebuild it instead of reusing the most recently * generated one. @@ -933,26 +921,54 @@ list_single_server_status(routerinfo_t *desc, int is_live) return tor_strdup(buf); } +static INLINE int +running_long_enough_to_decide_unreachable(void) +{ + return time_of_process_start + + get_options()->TestingAuthDirTimeToLearnReachability < approx_time(); +} + /** Each server needs to have passed a reachability test no more * than this number of seconds ago, or he is listed as down in * the directory. */ #define REACHABLE_TIMEOUT (45*60) +/** If we tested a router and found it reachable _at least this long_ after it + * declared itself hibernating, it is probably done hibernating and we just + * missed a descriptor from it. */ +#define HIBERNATION_PUBLICATION_SKEW (60*60) + /** Treat a router as alive if * - It's me, and I'm not hibernating. * or - We've found it reachable recently. */ void dirserv_set_router_is_running(routerinfo_t *router, time_t now) { + /*XXXX022 This function is a mess. Separate out the part that calculates + whether it's reachable and the part that tells rephist that the router was + unreachable. + */ int answer; - if (router_is_me(router) && !we_are_hibernating()) + if (router_is_me(router)) { + /* We always know if we are down ourselves. */ + answer = ! we_are_hibernating(); + } else if (router->is_hibernating && + (router->cache_info.published_on + + HIBERNATION_PUBLICATION_SKEW) > router->last_reachable) { + /* A hibernating router is down unless we (somehow) had contact with it + * since it declared itself to be hibernating. */ + answer = 0; + } else if (get_options()->AssumeReachable) { + /* If AssumeReachable, everybody is up unless they say they are down! */ answer = 1; - else - answer = get_options()->AssumeReachable || - now < router->last_reachable + REACHABLE_TIMEOUT; + } else { + /* Otherwise, a router counts as up if we found it reachable in the last + REACHABLE_TIMEOUT seconds. */ + answer = (now < router->last_reachable + REACHABLE_TIMEOUT); + } - if (!answer) { + if (!answer && running_long_enough_to_decide_unreachable()) { /* not considered reachable. tell rephist. */ rep_hist_note_router_unreachable(router->cache_info.identity_digest, now); } @@ -965,7 +981,6 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) * *<b>router_status_out</b>. Return 0 on success, -1 on failure. * * If for_controller is true, include the routers with very old descriptors. - * If for_controller is >1, use the verbose nickname format. */ int list_server_status_v1(smartlist_t *routers, char **router_status_out, @@ -985,23 +1000,22 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out, rs_entries = smartlist_create(); - SMARTLIST_FOREACH(routers, routerinfo_t *, ri, - { + SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) { if (authdir) { /* Update router status in routerinfo_t. */ dirserv_set_router_is_running(ri, now); } - if (for_controller == 1 || ri->cache_info.published_on >= cutoff) - smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running)); - else if (for_controller > 2) { + if (for_controller) { char name_buf[MAX_VERBOSE_NICKNAME_LEN+2]; char *cp = name_buf; if (!ri->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_FOREACH_END(ri); *router_status_out = smartlist_join_strings(rs_entries, " ", 0, NULL); @@ -1119,7 +1133,8 @@ dirserv_dump_directory_to_string(char **dir_out, return -1; } note_crypto_pk_op(SIGN_DIR); - if (router_append_dirobj_signature(buf,buf_len,digest,private_key)<0) { + if (router_append_dirobj_signature(buf,buf_len,digest,DIGEST_LEN, + private_key)<0) { tor_free(buf); return -1; } @@ -1144,18 +1159,21 @@ directory_fetches_from_authorities(or_options_t *options) { routerinfo_t *me; uint32_t addr; + int refuseunknown; if (options->FetchDirInfoEarly) return 1; if (options->BridgeRelay == 1) return 0; if (server_mode(options) && router_pick_published_address(options, &addr)<0) return 1; /* we don't know our IP address; ask an authority. */ - if (options->DirPort == 0) + refuseunknown = ! router_my_exit_policy_is_reject_star() && + should_refuse_unknown_exits(options); + if (options->DirPort == 0 && !refuseunknown) return 0; if (!server_mode(options) || !advertised_server_mode()) return 0; me = router_get_my_routerinfo(); - if (!me || !me->dir_port) + if (!me || (!me->dir_port && !refuseunknown)) return 0; /* if dirport not advertised, return 0 too */ return 1; } @@ -1195,7 +1213,14 @@ directory_caches_v2_dir_info(or_options_t *options) int directory_caches_dir_info(or_options_t *options) { - return options->BridgeRelay != 0 || options->DirPort != 0; + if (options->BridgeRelay || options->DirPort) + return 1; + if (!server_mode(options) || !advertised_server_mode()) + return 0; + /* We need an up-to-date view of network info if we're going to try to + * block exit attempts from unknown relays. */ + return ! router_my_exit_policy_is_reject_star() && + should_refuse_unknown_exits(options); } /** Return 1 if we want to allow remote people to ask us directory @@ -1238,14 +1263,14 @@ directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now) static cached_dir_t *cached_directory = NULL; /** The v1 runningrouters document we'll serve (as a cache or as an authority) * if requested. */ -static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0, -1 }; +static cached_dir_t cached_runningrouters; /** Used for other dirservers' v2 network statuses. Map from hexdigest to * cached_dir_t. */ static digestmap_t *cached_v2_networkstatus = NULL; -/** The v3 consensus network status that we're currently serving. */ -static cached_dir_t *cached_v3_networkstatus = NULL; +/** Map from flavor name to 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 * <b>directory</b> published on <b>when</b>, unless <b>when</b> is older than @@ -1319,7 +1344,11 @@ clear_cached_dir(cached_dir_t *d) static void _free_cached_dir(void *_d) { - cached_dir_t *d = (cached_dir_t *)_d; + cached_dir_t *d; + if (!_d) + return; + + d = (cached_dir_t *)_d; cached_dir_decref(d); } @@ -1413,17 +1442,26 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus, } } -/** Replace the v3 consensus networkstatus that we're serving with - * <b>networkstatus</b>, published at <b>published</b>. No validation is - * performed. */ +/** Replace the v3 consensus networkstatus of type <b>flavor_name</b> that + * we're serving with <b>networkstatus</b>, published at <b>published</b>. No + * validation is performed. */ void -dirserv_set_cached_networkstatus_v3(const char *networkstatus, - time_t published) +dirserv_set_cached_consensus_networkstatus(const char *networkstatus, + const char *flavor_name, + const digests_t *digests, + time_t published) { - if (cached_v3_networkstatus) - cached_dir_decref(cached_v3_networkstatus); - cached_v3_networkstatus = new_cached_dir( - tor_strdup(networkstatus), published); + cached_dir_t *new_networkstatus; + cached_dir_t *old_networkstatus; + if (!cached_consensuses) + cached_consensuses = strmap_new(); + + new_networkstatus = new_cached_dir(tor_strdup(networkstatus), published); + memcpy(&new_networkstatus->digests, digests, sizeof(digests_t)); + old_networkstatus = strmap_set(cached_consensuses, flavor_name, + new_networkstatus); + if (old_networkstatus) + cached_dir_decref(old_networkstatus); } /** Remove any v2 networkstatus from the directory cache that was published @@ -1520,7 +1558,8 @@ dirserv_regenerate_directory(void) { char *new_directory=NULL; - if (dirserv_dump_directory_to_string(&new_directory, get_identity_key())) { + if (dirserv_dump_directory_to_string(&new_directory, + get_server_identity_key())) { log_warn(LD_BUG, "Error creating directory."); tor_free(new_directory); return NULL; @@ -1550,7 +1589,7 @@ generate_runningrouters(void) char digest[DIGEST_LEN]; char published[ISO_TIME_LEN+1]; size_t len; - crypto_pk_env_t *private_key = get_identity_key(); + crypto_pk_env_t *private_key = get_server_identity_key(); char *identity_pkey; /* Identity key, DER64-encoded. */ size_t identity_pkey_len; @@ -1577,7 +1616,8 @@ generate_runningrouters(void) goto err; } note_crypto_pk_op(SIGN_DIR); - if (router_append_dirobj_signature(s, len, digest, private_key)<0) + if (router_append_dirobj_signature(s, len, digest, DIGEST_LEN, + private_key)<0) goto err; set_cached_dir(&the_runningrouters, s, time(NULL)); @@ -1605,9 +1645,11 @@ dirserv_get_runningrouters(void) /** Return the latest downloaded consensus networkstatus in encoded, signed, * optionally compressed format, suitable for sending to clients. */ cached_dir_t * -dirserv_get_consensus(void) +dirserv_get_consensus(const char *flavor_name) { - return cached_v3_networkstatus; + if (!cached_consensuses) + return NULL; + return strmap_get(cached_consensuses, flavor_name); } /** For authoritative directories: the current (v2) network status. */ @@ -1645,7 +1687,7 @@ should_generate_v2_networkstatus(void) #define TIME_KNOWN_TO_GUARANTEE_FAMILIAR (8*24*60*60) /** Similarly, every node with sufficient WFU is around enough to be a guard. */ -#define WFU_TO_GUARANTEE_GUARD (0.995) +#define WFU_TO_GUARANTEE_GUARD (0.98) /* Thresholds for server performance: set by * dirserv_compute_performance_thresholds, and used by @@ -1725,7 +1767,7 @@ dirserv_thinks_router_is_unreliable(time_t now, /** Return true iff <b>router</b> should be assigned the "HSDir" flag. * Right now this means it advertises support for it, it has a high - * uptime, and it's currently considered Running. + * uptime, it has a DirPort open, and it's currently considered Running. * * This function needs to be called after router-\>is_running has * been set. @@ -1735,7 +1777,11 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now) { long uptime = real_uptime(router, now); - return (router->wants_to_be_hs_dir && + /* XXX We shouldn't need to check dir_port, but we do because of + * bug 1693. In the future, once relays set wants_to_be_hs_dir + * correctly, we can revert to only checking dir_port if router's + * version is too old. */ + return (router->wants_to_be_hs_dir && router->dir_port && uptime > get_options()->MinUptimeHidServDirectoryV2 && router->is_running); } @@ -1790,7 +1836,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) if (router_is_active(ri, now)) { const char *id = ri->cache_info.identity_digest; uint32_t bw; - ri->is_exit = exit_policy_is_general_exit(ri->exit_policy); + ri->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); @@ -1897,16 +1944,20 @@ version_from_platform(const char *platform) * which has at least <b>buf_len</b> free characters. Do NUL-termination. * Use the same format as in network-status documents. If <b>version</b> is * non-NULL, add a "v" line for the platform. Return 0 on success, -1 on - * failure. If <b>first_line_only</b> is true, don't include any flags - * or version line. + * failure. + * + * The format argument has three possible values: + * NS_V2 - Output an entry suitable for a V2 NS opinion document + * NS_V3_CONSENSUS - Output the first portion of a V3 NS consensus entry + * NS_V3_CONSENSUS_MICRODESC - Output the first portion of a V3 microdesc + * consensus entry. + * NS_V3_VOTE - Output a complete V3 NS vote + * NS_CONTROL_PORT - Output a NS document for the control port */ int routerstatus_format_entry(char *buf, size_t buf_len, routerstatus_t *rs, const char *version, - int first_line_only, int v2_format) -/* XXX: first_line_only and v2_format should probably be be both - * replaced by a single purpose parameter. - */ + routerstatus_format_type_t format) { int r; struct in_addr in; @@ -1925,10 +1976,11 @@ routerstatus_format_entry(char *buf, size_t buf_len, tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr)); r = tor_snprintf(buf, buf_len, - "r %s %s %s %s %s %d %d\n", + "r %s %s %s%s%s %s %d %d\n", rs->nickname, identity64, - digest64, + (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64, + (format==NS_V3_CONSENSUS_MICRODESC)?"":" ", published, ipaddr, (int)rs->or_port, @@ -1937,7 +1989,12 @@ routerstatus_format_entry(char *buf, size_t buf_len, log_warn(LD_BUG, "Not enough space in buffer."); return -1; } - if (first_line_only) + + /* TODO: Maybe we want to pass in what we need to build the rest of + * this here, instead of in the caller. Then we could use the + * networkstatus_type_t values, with an additional control port value + * added -MP */ + if (format == NS_V3_CONSENSUS || format == NS_V3_CONSENSUS_MICRODESC) return 0; cp = buf + strlen(buf); @@ -1974,62 +2031,87 @@ routerstatus_format_entry(char *buf, size_t buf_len, cp += strlen(cp); } - if (!v2_format) { + if (format != NS_V2) { routerinfo_t* desc = router_get_by_digest(rs->identity_digest); + uint32_t bw; + + if (format != NS_CONTROL_PORT) { + /* Blow up more or less nicely if we didn't get anything or not the + * thing we expected. + */ + if (!desc) { + char id[HEX_DIGEST_LEN+1]; + char dd[HEX_DIGEST_LEN+1]; + + base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); + base16_encode(dd, sizeof(dd), rs->descriptor_digest, DIGEST_LEN); + log_warn(LD_BUG, "Cannot get any descriptor for %s " + "(wanted descriptor %s).", + id, dd); + return -1; + }; + + /* This assert can fire for the control port, because + * it can request NS documents before all descriptors + * have been fetched. */ + if (memcmp(desc->cache_info.signed_descriptor_digest, + rs->descriptor_digest, + DIGEST_LEN)) { + char rl_d[HEX_DIGEST_LEN+1]; + char rs_d[HEX_DIGEST_LEN+1]; + char id[HEX_DIGEST_LEN+1]; + + base16_encode(rl_d, sizeof(rl_d), + desc->cache_info.signed_descriptor_digest, DIGEST_LEN); + base16_encode(rs_d, sizeof(rs_d), rs->descriptor_digest, DIGEST_LEN); + base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); + log_err(LD_BUG, "descriptor digest in routerlist does not match " + "the one in routerstatus: %s vs %s " + "(router %s)\n", + rl_d, rs_d, id); + + tor_assert(!memcmp(desc->cache_info.signed_descriptor_digest, + rs->descriptor_digest, + DIGEST_LEN)); + }; + } - /* Blow up more or less nicely if we didn't get anything or not the - * thing we expected. - */ - if (!desc) { - char id[HEX_DIGEST_LEN+1]; - char dd[HEX_DIGEST_LEN+1]; - - base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); - base16_encode(dd, sizeof(dd), rs->descriptor_digest, DIGEST_LEN); - log_warn(LD_BUG, "Cannot get any descriptor for %s " - "(wanted descriptor %s).", - id, dd); - return -1; - }; - if (memcmp(desc->cache_info.signed_descriptor_digest, - rs->descriptor_digest, - DIGEST_LEN)) { - char rl_d[HEX_DIGEST_LEN+1]; - char rs_d[HEX_DIGEST_LEN+1]; - char id[HEX_DIGEST_LEN+1]; - - base16_encode(rl_d, sizeof(rl_d), - desc->cache_info.signed_descriptor_digest, DIGEST_LEN); - base16_encode(rs_d, sizeof(rs_d), rs->descriptor_digest, DIGEST_LEN); - base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); - log_err(LD_BUG, "descriptor digest in routerlist does not match " - "the one in routerstatus: %s vs %s " - "(router %s)\n", - rl_d, rs_d, id); - - tor_assert(!memcmp(desc->cache_info.signed_descriptor_digest, - rs->descriptor_digest, - DIGEST_LEN)); - }; - + if (format == NS_CONTROL_PORT && rs->has_bandwidth) { + bw = rs->bandwidth; + } else { + tor_assert(desc); + bw = router_get_advertised_bandwidth_capped(desc) / 1000; + } r = tor_snprintf(cp, buf_len - (cp-buf), - "w Bandwidth=%d\n", - router_get_advertised_bandwidth_capped(desc) / 1024); + "w Bandwidth=%d\n", bw); + if (r<0) { log_warn(LD_BUG, "Not enough space in buffer."); return -1; } cp += strlen(cp); + if (format == NS_V3_VOTE && rs->has_measured_bw) { + *--cp = '\0'; /* Kill "\n" */ + r = tor_snprintf(cp, buf_len - (cp-buf), + " Measured=%d\n", rs->measured_bw); + if (r<0) { + log_warn(LD_BUG, "Not enough space in buffer for weight line."); + return -1; + } + cp += strlen(cp); + } - summary = policy_summarize(desc->exit_policy); - r = tor_snprintf(cp, buf_len - (cp-buf), "p %s\n", summary); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); + if (desc) { + summary = policy_summarize(desc->exit_policy); + r = tor_snprintf(cp, buf_len - (cp-buf), "p %s\n", summary); + if (r<0) { + log_warn(LD_BUG, "Not enough space in buffer."); + tor_free(summary); + return -1; + } + cp += strlen(cp); tor_free(summary); - return -1; } - cp += strlen(cp); - tor_free(summary); } return 0; @@ -2132,9 +2214,7 @@ get_possible_sybil_list(const smartlist_t *routers) /** 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>. If not <b>exits_can_be_guards</b>, never mark - * an exit as a guard. If <b>listbadexits</b>, consider setting the badexit - * flag. + * the named flag in <b>rs</b>. * * We assume that ri-\>is_running has already been set, e.g. by * dirserv_set_router_is_running(ri, now); @@ -2142,8 +2222,8 @@ get_possible_sybil_list(const smartlist_t *routers) void set_routerstatus_from_routerinfo(routerstatus_t *rs, routerinfo_t *ri, time_t now, - int naming, int exits_can_be_guards, - int listbadexits, int listbaddirs) + int naming, int listbadexits, + int listbaddirs) { int unstable_version = !tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs"); @@ -2172,11 +2252,10 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_valid = ri->is_valid; if (rs->is_fast && - (!rs->is_exit || exits_can_be_guards) && (router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD || router_get_advertised_bandwidth(ri) >= - (exits_can_be_guards ? guard_bandwidth_including_exits : - guard_bandwidth_excluding_exits))) { + MIN(guard_bandwidth_including_exits, + guard_bandwidth_excluding_exits))) { long tk = rep_hist_get_weighted_time_known( ri->cache_info.identity_digest, now); double wfu = rep_hist_get_weighted_fractional_uptime( @@ -2232,6 +2311,177 @@ router_clear_status_flags(routerinfo_t *router) 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 + * or 0 on success. + */ +int +measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line) +{ + char *line = tor_strdup(orig_line); + char *cp = line; + int got_bw = 0; + int got_node_id = 0; + char *strtok_state; /* lame sauce d'jour */ + cp = tor_strtok_r(cp, " \t", &strtok_state); + + if (!cp) { + log_warn(LD_DIRSERV, "Invalid line in bandwidth file: %s", + escaped(orig_line)); + tor_free(line); + return -1; + } + + if (orig_line[strlen(orig_line)-1] != '\n') { + log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s", + escaped(orig_line)); + tor_free(line); + return -1; + } + + do { + if (strcmpstart(cp, "bw=") == 0) { + int parse_ok = 0; + char *endptr; + if (got_bw) { + log_warn(LD_DIRSERV, "Double bw= in bandwidth file line: %s", + escaped(orig_line)); + tor_free(line); + return -1; + } + cp+=strlen("bw="); + + out->bw = tor_parse_long(cp, 0, 0, LONG_MAX, &parse_ok, &endptr); + if (!parse_ok || (*endptr && !TOR_ISSPACE(*endptr))) { + log_warn(LD_DIRSERV, "Invalid bandwidth in bandwidth file line: %s", + escaped(orig_line)); + tor_free(line); + return -1; + } + got_bw=1; + } else if (strcmpstart(cp, "node_id=$") == 0) { + if (got_node_id) { + log_warn(LD_DIRSERV, "Double node_id= in bandwidth file line: %s", + escaped(orig_line)); + tor_free(line); + return -1; + } + cp+=strlen("node_id=$"); + + if (strlen(cp) != HEX_DIGEST_LEN || + base16_decode(out->node_id, DIGEST_LEN, cp, HEX_DIGEST_LEN)) { + log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s", + escaped(orig_line)); + tor_free(line); + return -1; + } + strncpy(out->node_hex, cp, sizeof(out->node_hex)); + got_node_id=1; + } + } while ((cp = tor_strtok_r(NULL, " \t", &strtok_state))); + + if (got_bw && got_node_id) { + tor_free(line); + return 0; + } else { + log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s", + escaped(orig_line)); + tor_free(line); + return -1; + } +} + +/** + * Helper function to apply a parsed measurement line to a list + * of bandwidth statuses. Returns true if a line is found, + * false otherwise. + */ +int +measured_bw_line_apply(measured_bw_line_t *parsed_line, + smartlist_t *routerstatuses) +{ + routerstatus_t *rs = NULL; + if (!routerstatuses) + return 0; + + rs = smartlist_bsearch(routerstatuses, parsed_line->node_id, + compare_digest_to_routerstatus_entry); + + if (rs) { + rs->has_measured_bw = 1; + rs->measured_bw = (uint32_t)parsed_line->bw; + } else { + log_info(LD_DIRSERV, "Node ID %s not found in routerstatus list", + parsed_line->node_hex); + } + + return rs != NULL; +} + +/** + * Read the measured bandwidth file and apply it to the list of + * routerstatuses. Returns -1 on error, 0 otherwise. + */ +int +dirserv_read_measured_bandwidths(const char *from_file, + smartlist_t *routerstatuses) +{ + char line[256]; + FILE *fp = fopen(from_file, "r"); + int applied_lines = 0; + time_t file_time; + int ok; + if (fp == NULL) { + log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s", + from_file); + return -1; + } + + if (!fgets(line, sizeof(line), fp) + || !strlen(line) || line[strlen(line)-1] != '\n') { + log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s", + escaped(line)); + fclose(fp); + return -1; + } + + line[strlen(line)-1] = '\0'; + file_time = tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s", + escaped(line)); + fclose(fp); + return -1; + } + + if ((time(NULL) - file_time) > MAX_MEASUREMENT_AGE) { + log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u", + (unsigned)(time(NULL) - file_time)); + fclose(fp); + return -1; + } + + if (routerstatuses) + smartlist_sort(routerstatuses, compare_routerstatus_entries); + + while (!feof(fp)) { + measured_bw_line_t parsed_line; + if (fgets(line, sizeof(line), fp) && strlen(line)) { + if (measured_bw_line_parse(&parsed_line, line) != -1) { + if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0) + applied_lines++; + } + } + } + + fclose(fp); + log_info(LD_DIRSERV, + "Bandwidth measurement file successfully read. " + "Applied %d measurements.", applied_lines); + return 0; +} + /** Return a new networkstatus_t* containing our current opinion. (For v3 * authorities) */ networkstatus_t * @@ -2249,22 +2499,18 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, int naming = options->NamingAuthoritativeDir; int listbadexits = options->AuthDirListBadExits; int listbaddirs = options->AuthDirListBadDirs; - int exits_can_be_guards; routerlist_t *rl = router_get_routerlist(); time_t now = time(NULL); time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; networkstatus_voter_info_t *voter = NULL; vote_timing_t timing; digestmap_t *omit_as_sybil = NULL; - int vote_on_reachability = 1; + const int vote_on_reachability = running_long_enough_to_decide_unreachable(); + smartlist_t *microdescriptors = NULL; tor_assert(private_key); tor_assert(cert); - if (now - time_of_process_start < - options->TestingAuthDirTimeToLearnReachability) - vote_on_reachability = 0; - if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); return NULL; @@ -2299,27 +2545,24 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, dirserv_compute_performance_thresholds(rl); - /* XXXX We should take steps to keep this from oscillating if - * total_exit_bandwidth is close to total_bandwidth/3. */ - exits_can_be_guards = total_exit_bandwidth >= (total_bandwidth / 3); - routers = smartlist_create(); smartlist_add_all(routers, rl->routers); routers_sort_by_identity(routers); omit_as_sybil = get_possible_sybil_list(routers); routerstatuses = smartlist_create(); + microdescriptors = smartlist_create(); - SMARTLIST_FOREACH(routers, routerinfo_t *, ri, { + SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) { if (ri->cache_info.published_on >= cutoff) { routerstatus_t *rs; vote_routerstatus_t *vrs; + microdesc_t *md; vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); rs = &vrs->status; set_routerstatus_from_routerinfo(rs, ri, now, - naming, exits_can_be_guards, - listbadexits, listbaddirs); + naming, listbadexits, listbaddirs); if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest)) clear_status_flags_on_sybil(rs); @@ -2328,12 +2571,39 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, rs->is_running = 0; vrs->version = version_from_platform(ri->platform); + md = dirvote_create_microdescriptor(ri); + if (md) { + char buf[128]; + vote_microdesc_hash_t *h; + dirvote_format_microdesc_vote_line(buf, sizeof(buf), md); + h = tor_malloc(sizeof(vote_microdesc_hash_t)); + h->microdesc_hash_line = tor_strdup(buf); + h->next = NULL; + vrs->microdesc = h; + md->last_listed = now; + smartlist_add(microdescriptors, md); + } + smartlist_add(routerstatuses, vrs); } - }); + } SMARTLIST_FOREACH_END(ri); + + { + smartlist_t *added = + microdescs_add_list_to_cache(get_microdesc_cache(), + microdescriptors, SAVED_NOWHERE, 0); + smartlist_free(added); + smartlist_free(microdescriptors); + } + smartlist_free(routers); digestmap_free(omit_as_sybil, NULL); + if (options->V3BandwidthsFile) { + dirserv_read_measured_bandwidths(options->V3BandwidthsFile, + routerstatuses); + } + v3_out = tor_malloc_zero(sizeof(networkstatus_t)); v3_out->type = NS_TYPE_VOTE; @@ -2383,15 +2653,22 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, } smartlist_sort_strings(v3_out->known_flags); + if (options->ConsensusParams) { + v3_out->net_params = smartlist_create(); + smartlist_split_string(v3_out->net_params, + options->ConsensusParams, NULL, 0, 0); + smartlist_sort_strings(v3_out->net_params); + } + voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t)); voter->nickname = tor_strdup(options->Nickname); memcpy(voter->identity_digest, identity_digest, DIGEST_LEN); + voter->sigs = smartlist_create(); voter->address = hostname; voter->addr = addr; voter->dir_port = options->DirPort; voter->or_port = options->ORPort; voter->contact = tor_strdup(contact); - memcpy(voter->signing_key_digest, signing_key_digest, DIGEST_LEN); if (options->V3AuthUseLegacyKey) { authority_cert_t *c = get_my_v3_legacy_cert(); if (c) { @@ -2435,13 +2712,12 @@ generate_v2_networkstatus_opinion(void) int versioning = options->VersioningAuthoritativeDir; int listbaddirs = options->AuthDirListBadDirs; int listbadexits = options->AuthDirListBadExits; - int exits_can_be_guards; const char *contact; char *version_lines = NULL; smartlist_t *routers = NULL; digestmap_t *omit_as_sybil = NULL; - private_key = get_identity_key(); + private_key = get_server_identity_key(); if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); @@ -2515,10 +2791,6 @@ generate_v2_networkstatus_opinion(void) dirserv_compute_performance_thresholds(rl); - /* XXXX We should take steps to keep this from oscillating if - * total_exit_bandwidth is close to total_bandwidth/3. */ - exits_can_be_guards = total_exit_bandwidth >= (total_bandwidth / 3); - routers = smartlist_create(); smartlist_add_all(routers, rl->routers); routers_sort_by_identity(routers); @@ -2531,13 +2803,12 @@ generate_v2_networkstatus_opinion(void) char *version = version_from_platform(ri->platform); set_routerstatus_from_routerinfo(&rs, ri, now, - naming, exits_can_be_guards, - listbadexits, listbaddirs); + naming, listbadexits, listbaddirs); if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest)) clear_status_flags_on_sybil(&rs); - if (routerstatus_format_entry(outp, endp-outp, &rs, version, 0, 1)) { + if (routerstatus_format_entry(outp, endp-outp, &rs, version, NS_V2)) { log_warn(LD_BUG, "Unable to print router status."); tor_free(version); goto done; @@ -2559,7 +2830,8 @@ generate_v2_networkstatus_opinion(void) outp += strlen(outp); note_crypto_pk_op(SIGN_DIR); - if (router_append_dirobj_signature(outp,endp-outp,digest,private_key)<0) { + if (router_append_dirobj_signature(outp,endp-outp,digest,DIGEST_LEN, + private_key)<0) { log_warn(LD_BUG, "Unable to sign router status."); goto done; } @@ -2591,10 +2863,8 @@ generate_v2_networkstatus_opinion(void) tor_free(status); tor_free(hostname); tor_free(identity_pkey); - if (routers) - smartlist_free(routers); - if (omit_as_sybil) - digestmap_free(omit_as_sybil, NULL); + smartlist_free(routers); + digestmap_free(omit_as_sybil, NULL); return r; } @@ -2642,7 +2912,8 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, log_info(LD_DIRSERV, "Client requested 'all' network status objects; we have none."); } else if (!strcmpstart(key, "fp/")) { - dir_split_resource_into_fingerprints(key+3, result, NULL, 1, 1); + dir_split_resource_into_fingerprints(key+3, result, NULL, + DSR_HEX|DSR_SORT_UNIQ); } } @@ -2707,10 +2978,12 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, } else if (!strcmpstart(key, "d/")) { by_id = 0; key += strlen("d/"); - dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1); + dir_split_resource_into_fingerprints(key, fps_out, NULL, + DSR_HEX|DSR_SORT_UNIQ); } else if (!strcmpstart(key, "fp/")) { key += strlen("fp/"); - dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1); + dir_split_resource_into_fingerprints(key, fps_out, NULL, + DSR_HEX|DSR_SORT_UNIQ); } else { *msg = "Key not recognized"; return -1; @@ -2775,7 +3048,8 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, } else if (!strcmpstart(key, "/tor/server/d/")) { smartlist_t *digests = smartlist_create(); key += strlen("/tor/server/d/"); - dir_split_resource_into_fingerprints(key, digests, NULL, 1, 1); + dir_split_resource_into_fingerprints(key, digests, NULL, + DSR_HEX|DSR_SORT_UNIQ); SMARTLIST_FOREACH(digests, const char *, d, { signed_descriptor_t *sd = router_get_by_descriptor_digest(d); @@ -2788,7 +3062,8 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, smartlist_t *digests = smartlist_create(); time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH; key += strlen("/tor/server/fp/"); - dir_split_resource_into_fingerprints(key, digests, NULL, 1, 1); + dir_split_resource_into_fingerprints(key, digests, NULL, + DSR_HEX|DSR_SORT_UNIQ); SMARTLIST_FOREACH(digests, const char *, d, { if (router_digest_is_me(d)) { @@ -2857,8 +3132,48 @@ dirserv_orconn_tls_done(const char *address, * skip testing. */ } -/** Auth dir server only: if <b>try_all</b> is 1, launch connections to - * all known routers; else we want to load balance such that we only +/** Called when we, as an authority, receive a new router descriptor either as + * 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) +{ + if (!authdir_mode_handles_descs(get_options(), ri->purpose)) + return 0; + if (!ri_old) { + /* New router: Launch an immediate reachability test, so we will have an + * opinion soon in case we're generating a consensus soon */ + return 1; + } + if (ri_old->is_hibernating && !ri->is_hibernating) { + /* It just came out of hibernation; launch a reachability test */ + return 1; + } + if (! routers_have_same_or_addr(ri, ri_old)) { + /* Address or port changed; launch a reachability test */ + return 1; + } + return 0; +} + +/** Helper function for dirserv_test_reachability(). Start a TLS + * connection to <b>router</b>, and annotate it with when we started + * the test. */ +void +dirserv_single_reachability_test(time_t now, routerinfo_t *router) +{ + tor_addr_t router_addr; + log_debug(LD_OR,"Testing reachability of %s at %s:%u.", + router->nickname, router->address, router->or_port); + /* Remember when we started trying to determine reachability */ + if (!router->testing_since) + router->testing_since = now; + tor_addr_from_ipv4h(&router_addr, router->addr); + connection_or_connect(&router_addr, router->or_port, + router->cache_info.identity_digest); +} + +/** Auth dir server only: load balance such that we only * try a few connections per call. * * The load balancing is such that if we get called once every ten @@ -2866,7 +3181,7 @@ dirserv_orconn_tls_done(const char *address, * bit over 20 minutes). */ void -dirserv_test_reachability(time_t now, int try_all) +dirserv_test_reachability(time_t now) { /* XXX decide what to do here; see or-talk thread "purging old router * information, revocation." -NM @@ -2883,38 +3198,33 @@ dirserv_test_reachability(time_t now, int try_all) SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, router) { const char *id_digest = router->cache_info.identity_digest; - tor_addr_t router_addr; if (router_is_me(router)) continue; if (bridge_auth && router->purpose != ROUTER_PURPOSE_BRIDGE) continue; /* bridge authorities only test reachability on bridges */ // if (router->cache_info.published_on > cutoff) // continue; - if (try_all || (((uint8_t)id_digest[0]) % 128) == ctr) { - log_debug(LD_OR,"Testing reachability of %s at %s:%u.", - router->nickname, router->address, router->or_port); - /* Remember when we started trying to determine reachability */ - if (!router->testing_since) - router->testing_since = now; - tor_addr_from_ipv4h(&router_addr, router->addr); - connection_or_connect(&router_addr, router->or_port, id_digest); + if ((((uint8_t)id_digest[0]) % 128) == ctr) { + dirserv_single_reachability_test(now, router); } } SMARTLIST_FOREACH_END(router); - if (!try_all) /* increment ctr */ - ctr = (ctr + 1) % 128; + ctr = (ctr + 1) % 128; /* increment ctr */ } -/** Given a fingerprint <b>fp</b> which is either set if we're looking - * for a v2 status, or zeroes if we're looking for a v3 status, return - * a pointer to the appropriate cached dir object, or NULL if there isn't - * one available. */ +/** Given a fingerprint <b>fp</b> which is either set if we're looking for a + * v2 status, or zeroes if we're looking for a v3 status, or a NUL-padded + * flavor name if we want a flavored v3 status, return a pointer to the + * appropriate cached dir object, or NULL if there isn't one available. */ static cached_dir_t * lookup_cached_dir_by_fp(const char *fp) { cached_dir_t *d = NULL; - if (tor_digest_is_zero(fp) && cached_v3_networkstatus) - d = cached_v3_networkstatus; - else if (router_digest_is_me(fp) && the_v2_networkstatus) + if (tor_digest_is_zero(fp) && cached_consensuses) + d = strmap_get(cached_consensuses, "ns"); + else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses && + (d = strmap_get(cached_consensuses, fp))) { + /* this here interface is a nasty hack XXXX022 */; + } else if (router_digest_is_me(fp) && the_v2_networkstatus) d = the_v2_networkstatus; else if (cached_v2_networkstatus) d = digestmap_get(cached_v2_networkstatus, fp); @@ -3000,6 +3310,18 @@ dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src) return 0; } +/** Return true iff any of the 256-bit elements in <b>fps</b> is the digest of + * a microdescriptor we have. */ +int +dirserv_have_any_microdesc(const smartlist_t *fps) +{ + microdesc_cache_t *cache = get_microdesc_cache(); + SMARTLIST_FOREACH(fps, const char *, fp, + if (microdesc_cache_lookup_by_digest256(cache, fp)) + return 1); + return 0; +} + /** Return an approximate estimate of the number of bytes that will * be needed to transmit the server descriptors (if is_serverdescs -- * they can be either d/ or fp/ queries) or networkstatus objects (if @@ -3031,6 +3353,17 @@ dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs, return result; } +/** Given a list of microdescriptor hashes, guess how many bytes will be + * needed to transmit them, and return the guess. */ +size_t +dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed) +{ + size_t result = smartlist_len(fps) * microdesc_average_size(NULL); + if (compressed) + result /= 2; + return result; +} + /** When we're spooling data onto our outbuf, add more whenever we dip * below this threshold. */ #define DIRSERV_BUFFER_MIN 16384 @@ -3094,6 +3427,8 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) #endif body = signed_descriptor_get_body(sd); if (conn->zlib_state) { + /* XXXX022 This 'last' business should actually happen on the last + * routerinfo, not on the last fingerprint. */ int last = ! smartlist_len(conn->fingerprint_stack); connection_write_to_buf_zlib(body, sd->signed_descriptor_len, conn, last); @@ -3117,6 +3452,44 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) return 0; } +/** Spooling helper: called when we're sending a bunch of microdescriptors, + * and the outbuf has become too empty. Pulls some entries from + * fingerprint_stack, and writes the corresponding microdescs onto outbuf. If + * we run out of entries, flushes the zlib state and sets the spool source to + * NONE. Returns 0 on success, negative on failure. + */ +static int +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) { + char *fp256 = smartlist_pop_last(conn->fingerprint_stack); + microdesc_t *md = microdesc_cache_lookup_by_digest256(cache, fp256); + tor_free(fp256); + if (!md) + continue; + if (conn->zlib_state) { + /* XXXX022 This 'last' business should actually happen on the last + * routerinfo, not on the last fingerprint. */ + int last = !smartlist_len(conn->fingerprint_stack); + connection_write_to_buf_zlib(md->body, md->bodylen, conn, last); + if (last) { + tor_zlib_free(conn->zlib_state); + conn->zlib_state = NULL; + } + } else { + connection_write_to_buf(md->body, md->bodylen, TO_CONN(conn)); + } + } + if (!smartlist_len(conn->fingerprint_stack)) { + conn->dir_spool_src = DIR_SPOOL_NONE; + smartlist_free(conn->fingerprint_stack); + conn->fingerprint_stack = NULL; + } + return 0; +} + /** Spooling helper: Called when we're sending a directory or networkstatus, * and the outbuf has become too empty. Pulls some bytes from * <b>conn</b>-\>cached_dir-\>dir_z, uncompresses them if appropriate, and @@ -3199,8 +3572,7 @@ connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn) } } else { connection_dirserv_finish_spooling(conn); - if (conn->fingerprint_stack) - smartlist_free(conn->fingerprint_stack); + smartlist_free(conn->fingerprint_stack); conn->fingerprint_stack = NULL; return 0; } @@ -3224,6 +3596,8 @@ connection_dirserv_flushed_some(dir_connection_t *conn) case DIR_SPOOL_SERVER_BY_DIGEST: case DIR_SPOOL_SERVER_BY_FP: return connection_dirserv_add_servers_to_outbuf(conn); + case DIR_SPOOL_MICRODESC: + return connection_dirserv_add_microdescs_to_outbuf(conn); case DIR_SPOOL_CACHED_DIR: return connection_dirserv_add_dir_bytes_to_outbuf(conn); case DIR_SPOOL_NETWORKSTATUS: @@ -3245,10 +3619,10 @@ dirserv_free_all(void) cached_dir_decref(the_v2_networkstatus); cached_dir_decref(cached_directory); clear_cached_dir(&cached_runningrouters); - if (cached_v2_networkstatus) { - digestmap_free(cached_v2_networkstatus, _free_cached_dir); - cached_v2_networkstatus = NULL; - } - cached_dir_decref(cached_v3_networkstatus); + + digestmap_free(cached_v2_networkstatus, _free_cached_dir); + cached_v2_networkstatus = NULL; + strmap_free(cached_consensuses, _free_cached_dir); + cached_consensuses = NULL; } diff --git a/src/or/dirserv.h b/src/or/dirserv.h new file mode 100644 index 0000000000..94e4e811d6 --- /dev/null +++ b/src/or/dirserv.h @@ -0,0 +1,134 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file dirserv.h + * \brief Header file for dirserv.c. + **/ + +#ifndef _TOR_DIRSERV_H +#define _TOR_DIRSERV_H + +/** Maximum length of an exit policy summary. */ +#define MAX_EXITPOLICY_SUMMARY_LEN 1000 + +/** Maximum allowable length of a version line in a networkstatus. */ +#define MAX_V_LINE_LEN 128 +/** Length of "r Authority BadDirectory BadExit Exit Fast Guard HSDir Named + * Running Stable Unnamed V2Dir Valid\n". */ +#define MAX_FLAG_LINE_LEN 96 +/** Length of "w" line for weighting. Currently at most + * "w Bandwidth=<uint32t> Measured=<uint32t>\n" */ +#define MAX_WEIGHT_LINE_LEN (12+10+10+10+1) +/** Maximum length of an exit policy summary line. */ +#define MAX_POLICY_LINE_LEN (3+MAX_EXITPOLICY_SUMMARY_LEN) +/** Amount of space to allocate for each entry: r, s, and v lines. */ +#define RS_ENTRY_LEN \ + ( /* first line */ \ + MAX_NICKNAME_LEN+BASE64_DIGEST_LEN*2+ISO_TIME_LEN+INET_NTOA_BUF_LEN+ \ + 5*2 /* ports */ + 10 /* punctuation */ + \ + /* second line */ \ + MAX_FLAG_LINE_LEN + \ + /* weight line */ \ + MAX_WEIGHT_LINE_LEN + \ + /* p line. */ \ + MAX_POLICY_LINE_LEN + \ + /* v line. */ \ + 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); +int dirserv_load_fingerprint_file(void); +void dirserv_free_fingerprint_list(void); +const char *dirserv_get_nickname_by_digest(const char *digest); +enum was_router_added_t dirserv_add_multiple_descriptors( + const char *desc, uint8_t purpose, + const char *source, + const char **msg); +enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri, + const char **msg, + const char *source); +void dirserv_set_router_is_running(routerinfo_t *router, time_t now); +int list_server_status_v1(smartlist_t *routers, char **router_status_out, + int for_controller); +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); +#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); + +void directory_set_dirty(void); +cached_dir_t *dirserv_get_directory(void); +cached_dir_t *dirserv_get_runningrouters(void); +cached_dir_t *dirserv_get_consensus(const char *flavor_name); +void dirserv_set_cached_directory(const char *directory, time_t when, + int is_running_routers); +void dirserv_set_cached_networkstatus_v2(const char *directory, + const char *identity, + time_t published); +void dirserv_set_cached_consensus_networkstatus(const char *consensus, + const char *flavor_name, + const digests_t *digests, + time_t published); +void dirserv_clear_old_networkstatuses(time_t cutoff); +void dirserv_clear_old_v1_info(time_t now); +void dirserv_get_networkstatus_v2(smartlist_t *result, const char *key); +void dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, + const char *key); +int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, + const char **msg, + int for_unencrypted_conn, + int is_extrainfo); +int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, + const char **msg); +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); +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 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); +size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs, + int compressed); +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, + routerstatus_format_type_t format); +void dirserv_free_all(void); +void cached_dir_decref(cached_dir_t *d); +cached_dir_t *new_cached_dir(char *s, time_t published); + +#ifdef DIRSERV_PRIVATE +int measured_bw_line_parse(measured_bw_line_t *out, const char *line); + +int measured_bw_line_apply(measured_bw_line_t *parsed_line, + smartlist_t *routerstatuses); +#endif + +int dirserv_read_measured_bandwidths(const char *from_file, + smartlist_t *routerstatuses); + +#endif + diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 64e07cc0a2..dd36a0f911 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -5,27 +5,72 @@ #define DIRVOTE_PRIVATE #include "or.h" +#include "config.h" +#include "directory.h" +#include "dirserv.h" +#include "dirvote.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "policies.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" /** * \file dirvote.c * \brief Functions to compute directory consensus, and schedule voting. **/ -static int dirvote_add_signatures_to_pending_consensus( +/** A consensus that we have built and are appending signatures to. Once it's + * time to publish it, it will become an active consensus if it accumulates + * enough signatures. */ +typedef struct pending_consensus_t { + /** The body of the consensus that we're currently building. Once we + * have it built, it goes into dirserv.c */ + char *body; + /** The parsed in-progress consensus document. */ + networkstatus_t *consensus; +} pending_consensus_t; + +static int dirvote_add_signatures_to_all_pending_consensuses( const char *detached_signatures_body, const char **msg_out); +static int dirvote_add_signatures_to_pending_consensus( + pending_consensus_t *pc, + ns_detached_signatures_t *sigs, + const char **msg_out); static char *list_v3_auth_ids(void); static void dirvote_fetch_missing_votes(void); static void dirvote_fetch_missing_signatures(void); static int dirvote_perform_vote(void); static void dirvote_clear_votes(int all_votes); -static int dirvote_compute_consensus(void); +static int dirvote_compute_consensuses(void); 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 10 + +/** Lowest consensus method that contains a 'directory-footer' marker */ +#define MIN_METHOD_FOR_FOOTER 9 + +/** Lowest consensus method that contains bandwidth weights */ +#define MIN_METHOD_FOR_BW_WEIGHTS 9 + +/** Lowest consensus method that contains consensus params */ +#define MIN_METHOD_FOR_PARAMS 7 + +/** Lowest consensus method that generates microdescriptors */ +#define MIN_METHOD_FOR_MICRODESC 8 /* ===== * Voting * =====*/ +/* Overestimated. */ +#define MICRODESC_LINE_LEN 80 + /** Return a new string containing the string representation of the vote in * <b>v3_ns</b>, signed with our v3 signing key <b>private_signing_key</b>. * For v3 authorities. */ @@ -44,6 +89,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, uint32_t addr; routerlist_t *rl = router_get_routerlist(); char *version_lines = NULL; + int r; networkstatus_voter_info_t *voter; tor_assert(private_signing_key); @@ -70,20 +116,30 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, version_lines = tor_malloc(v_len); cp = version_lines; if (client_versions) { - tor_snprintf(cp, v_len-(cp-version_lines), + r = tor_snprintf(cp, v_len-(cp-version_lines), "client-versions %s\n", client_versions); + if (r < 0) { + log_err(LD_BUG, "Insufficient memory for client-versions line"); + tor_assert(0); + } cp += strlen(cp); } - if (server_versions) - tor_snprintf(cp, v_len-(cp-version_lines), + if (server_versions) { + r = tor_snprintf(cp, v_len-(cp-version_lines), "server-versions %s\n", server_versions); + if (r < 0) { + log_err(LD_BUG, "Insufficient memory for server-versions line"); + tor_assert(0); + } + } } else { version_lines = tor_strdup(""); } len = 8192; len += strlen(version_lines); - len += (RS_ENTRY_LEN)*smartlist_len(rl->routers); + len += (RS_ENTRY_LEN+MICRODESC_LINE_LEN)*smartlist_len(rl->routers); + len += strlen("\ndirectory-footer\n"); len += v3_ns->cert->cache_info.signed_descriptor_len; status = tor_malloc(len); @@ -93,17 +149,25 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, char fu[ISO_TIME_LEN+1]; char vu[ISO_TIME_LEN+1]; char *flags = smartlist_join_strings(v3_ns->known_flags, " ", 0, NULL); + char *params; authority_cert_t *cert = v3_ns->cert; + char *methods = + make_consensus_method_list(1, MAX_SUPPORTED_CONSENSUS_METHOD, " "); format_iso_time(published, v3_ns->published); format_iso_time(va, v3_ns->valid_after); format_iso_time(fu, v3_ns->fresh_until); format_iso_time(vu, v3_ns->valid_until); + if (v3_ns->net_params) + params = smartlist_join_strings(v3_ns->net_params, " ", 0, NULL); + else + params = tor_strdup(""); + tor_assert(cert); - tor_snprintf(status, len, + r = tor_snprintf(status, len, "network-status-version 3\n" "vote-status %s\n" - "consensus-methods 1 2 3 4 5\n" + "consensus-methods %s\n" "published %s\n" "valid-after %s\n" "fresh-until %s\n" @@ -111,24 +175,38 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, "voting-delay %d %d\n" "%s" /* versions */ "known-flags %s\n" + "params %s\n" "dir-source %s %s %s %s %d %d\n" "contact %s\n", v3_ns->type == NS_TYPE_VOTE ? "vote" : "opinion", + methods, published, va, fu, vu, v3_ns->vote_seconds, v3_ns->dist_seconds, version_lines, flags, + params, voter->nickname, fingerprint, voter->address, - ipaddr, voter->dir_port, voter->or_port, voter->contact); + ipaddr, voter->dir_port, voter->or_port, voter->contact); + if (r < 0) { + log_err(LD_BUG, "Insufficient memory for network status line"); + tor_assert(0); + } + + tor_free(params); tor_free(flags); + tor_free(methods); outp = status + strlen(status); endp = status + len; if (!tor_digest_is_zero(voter->legacy_id_digest)) { char fpbuf[HEX_DIGEST_LEN+1]; base16_encode(fpbuf, sizeof(fpbuf), voter->legacy_id_digest, DIGEST_LEN); - tor_snprintf(outp, endp-outp, "legacy-dir-key %s\n", fpbuf); + r = tor_snprintf(outp, endp-outp, "legacy-dir-key %s\n", fpbuf); + if (r < 0) { + log_err(LD_BUG, "Insufficient memory for legacy-dir-key line"); + tor_assert(0); + } outp += strlen(outp); } @@ -139,15 +217,32 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, outp += cert->cache_info.signed_descriptor_len; } - SMARTLIST_FOREACH(v3_ns->routerstatus_list, vote_routerstatus_t *, vrs, - { + SMARTLIST_FOREACH_BEGIN(v3_ns->routerstatus_list, vote_routerstatus_t *, + vrs) { + vote_microdesc_hash_t *h; if (routerstatus_format_entry(outp, endp-outp, &vrs->status, - vrs->version, 0, 0) < 0) { + vrs->version, NS_V3_VOTE) < 0) { log_warn(LD_BUG, "Unable to print router status."); goto err; } outp += strlen(outp); - }); + + for (h = vrs->microdesc; h; h = h->next) { + size_t mlen = strlen(h->microdesc_hash_line); + if (outp+mlen >= endp) { + log_warn(LD_BUG, "Can't fit microdesc line in vote."); + } + memcpy(outp, h->microdesc_hash_line, mlen+1); + outp += strlen(outp); + } + } SMARTLIST_FOREACH_END(vrs); + + r = tor_snprintf(outp, endp-outp, "directory-footer\n"); + if (r < 0) { + log_err(LD_BUG, "Insufficient memory for directory-footer line"); + tor_assert(0); + } + outp += strlen(outp); { char signing_key_fingerprint[FINGERPRINT_LEN+1]; @@ -170,10 +265,10 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, outp += strlen(outp); } - if (router_get_networkstatus_v3_hash(status, digest)<0) + if (router_get_networkstatus_v3_hash(status, digest, DIGEST_SHA1)<0) goto err; note_crypto_pk_op(SIGN_DIR); - if (router_append_dirobj_signature(outp,endp-outp,digest, + if (router_append_dirobj_signature(outp,endp-outp,digest, DIGEST_LEN, private_signing_key)<0) { log_warn(LD_BUG, "Unable to sign networkstatus vote."); goto err; @@ -216,6 +311,20 @@ get_voter(const networkstatus_t *vote) return smartlist_get(vote->voters, 0); } +/** Return the signature made by <b>voter</b> using the algorithm + * <b>alg</b>, or NULL if none is found. */ +document_signature_t * +voter_get_sig_by_algorithm(const networkstatus_voter_info_t *voter, + digest_algorithm_t alg) +{ + if (!voter->sigs) + return NULL; + SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig, + if (sig->alg == alg) + return sig); + return NULL; +} + /** Temporary structure used in constructing a list of dir-source entries * for a consensus. One of these is generated for every vote, and one more * for every legacy key in each vote. */ @@ -275,34 +384,8 @@ get_frequent_members(smartlist_t *out, smartlist_t *in, int min) /** Given a sorted list of strings <b>lst</b>, return the member that appears * most. Break ties in favor of later-occurring members. */ -static const char * -get_most_frequent_member(smartlist_t *lst) -{ - const char *most_frequent = NULL; - int most_frequent_count = 0; - - const char *cur = NULL; - int count = 0; - - SMARTLIST_FOREACH(lst, const char *, s, - { - if (cur && !strcmp(s, cur)) { - ++count; - } else { - if (count >= most_frequent_count) { - most_frequent = cur; - most_frequent_count = count; - } - cur = s; - count = 1; - } - }); - if (count >= most_frequent_count) { - most_frequent = cur; - most_frequent_count = count; - } - return most_frequent; -} +#define get_most_frequent_member(lst) \ + smartlist_get_most_frequent_string(lst) /** Return 0 if and only if <b>a</b> and <b>b</b> are routerstatuses * that come from the same routerinfo, with the same derived elements. @@ -344,7 +427,8 @@ _compare_vote_rs(const void **_a, const void **_b) * in favor of smaller descriptor digest. */ static vote_routerstatus_t * -compute_routerstatus_consensus(smartlist_t *votes) +compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, + char *microdesc_digest256_out) { vote_routerstatus_t *most = NULL, *cur = NULL; int most_n = 0, cur_n = 0; @@ -380,18 +464,45 @@ compute_routerstatus_consensus(smartlist_t *votes) } tor_assert(most); + + if (consensus_method >= MIN_METHOD_FOR_MICRODESC && + microdesc_digest256_out) { + smartlist_t *digests = smartlist_create(); + const char *best_microdesc_digest; + SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) { + char d[DIGEST256_LEN]; + if (compare_vote_rs(rs, most)) + continue; + if (!vote_routerstatus_find_microdesc_hash(d, rs, consensus_method, + DIGEST_SHA256)) + smartlist_add(digests, tor_memdup(d, sizeof(d))); + } SMARTLIST_FOREACH_END(rs); + smartlist_sort_digests256(digests); + best_microdesc_digest = smartlist_get_most_frequent_digest256(digests); + if (best_microdesc_digest) + memcpy(microdesc_digest256_out, best_microdesc_digest, DIGEST256_LEN); + SMARTLIST_FOREACH(digests, char *, cp, tor_free(cp)); + smartlist_free(digests); + } + return most; } -/** Given a list of strings in <b>lst</b>, set the DIGEST_LEN-byte digest at - * <b>digest_out</b> to the hash of the concatenation of those strings. */ +/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest + * at <b>digest_out</b> to the hash of the concatenation of those strings, + * computed with the algorithm <b>alg</b>. */ static void -hash_list_members(char *digest_out, smartlist_t *lst) +hash_list_members(char *digest_out, size_t len_out, + smartlist_t *lst, digest_algorithm_t alg) { - crypto_digest_env_t *d = crypto_new_digest_env(); + crypto_digest_env_t *d; + if (alg == DIGEST_SHA1) + d = crypto_new_digest_env(); + else + d = crypto_new_digest256_env(alg); SMARTLIST_FOREACH(lst, const char *, cp, crypto_digest_add_bytes(d, cp, strlen(cp))); - crypto_digest_get_digest(d, digest_out, DIGEST_LEN); + crypto_digest_get_digest(d, digest_out, len_out); crypto_free_digest_env(d); } @@ -455,7 +566,31 @@ compute_consensus_method(smartlist_t *votes) static int consensus_method_is_supported(int method) { - return (method >= 1) && (method <= 5); + return (method >= 1) && (method <= MAX_SUPPORTED_CONSENSUS_METHOD); +} + +/** Return a newly allocated string holding the numbers between low and high + * (inclusive) that are supported consensus methods. */ +static char * +make_consensus_method_list(int low, int high, const char *separator) +{ + char *list; + + char b[32]; + int i; + smartlist_t *lst; + lst = smartlist_create(); + for (i = low; i <= high; ++i) { + if (!consensus_method_is_supported(i)) + continue; + tor_snprintf(b, sizeof(b), "%d", i); + smartlist_add(lst, tor_strdup(b)); + } + list = smartlist_join_strings(lst, separator, 0, NULL); + tor_assert(list); + SMARTLIST_FOREACH(lst, char *, cp, tor_free(cp)); + smartlist_free(lst); + return list; } /** Helper: given <b>lst</b>, a list of version strings such that every @@ -475,6 +610,728 @@ compute_consensus_versions_list(smartlist_t *lst, int n_versioning) return result; } +/** 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) +{ + int i; + int32_t *vals; + + int cur_param_len; + const char *cur_param; + const char *eq; + char *result; + + const int n_votes = smartlist_len(votes); + smartlist_t *output; + smartlist_t *param_list = smartlist_create(); + + /* We require that the parameter lists in the votes are well-formed: that + is, that their keywords are unique and sorted, and that their values are + between INT32_MIN and INT32_MAX inclusive. This should be guaranteed by + the parsing code. */ + + vals = tor_malloc(sizeof(int)*n_votes); + + SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { + if (!v->net_params) + continue; + smartlist_add_all(param_list, v->net_params); + } SMARTLIST_FOREACH_END(v); + + if (smartlist_len(param_list) == 0) { + tor_free(vals); + smartlist_free(param_list); + return NULL; + } + + smartlist_sort_strings(param_list); + i = 0; + cur_param = smartlist_get(param_list, 0); + eq = strchr(cur_param, '='); + tor_assert(eq); + cur_param_len = (int)(eq+1 - cur_param); + + output = smartlist_create(); + + SMARTLIST_FOREACH_BEGIN(param_list, const char *, param) { + const char *next_param; + int ok=0; + eq = strchr(param, '='); + tor_assert(i<n_votes); + vals[i++] = (int32_t) + tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL); + tor_assert(ok); + + if (param_sl_idx+1 == smartlist_len(param_list)) + next_param = NULL; + else + 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); + + i = 0; + if (next_param) { + eq = strchr(next_param, '='); + cur_param_len = (int)(eq+1 - next_param); + } + } + } SMARTLIST_FOREACH_END(param); + + result = smartlist_join_strings(output, " ", 0, NULL); + SMARTLIST_FOREACH(output, char *, cp, tor_free(cp)); + smartlist_free(output); + smartlist_free(param_list); + tor_free(vals); + return result; +} + +#define RANGE_CHECK(a,b,c,d,e,f,g,mx) \ + ((a) >= 0 && (a) <= (mx) && (b) >= 0 && (b) <= (mx) && \ + (c) >= 0 && (c) <= (mx) && (d) >= 0 && (d) <= (mx) && \ + (e) >= 0 && (e) <= (mx) && (f) >= 0 && (f) <= (mx) && \ + (g) >= 0 && (g) <= (mx)) + +#define CHECK_EQ(a, b, margin) \ + ((a)-(b) >= 0 ? (a)-(b) <= (margin) : (b)-(a) <= (margin)) + +typedef enum { + BW_WEIGHTS_NO_ERROR = 0, + BW_WEIGHTS_RANGE_ERROR = 1, + BW_WEIGHTS_SUMG_ERROR = 2, + BW_WEIGHTS_SUME_ERROR = 3, + BW_WEIGHTS_SUMD_ERROR = 4, + BW_WEIGHTS_BALANCE_MID_ERROR = 5, + BW_WEIGHTS_BALANCE_EG_ERROR = 6 +} bw_weights_error_t; + +/** + * Verify that any weightings satisfy the balanced formulas. + */ +static bw_weights_error_t +networkstatus_check_weights(int64_t Wgg, int64_t Wgd, int64_t Wmg, + int64_t Wme, int64_t Wmd, int64_t Wee, + int64_t Wed, int64_t scale, int64_t G, + int64_t M, int64_t E, int64_t D, int64_t T, + int64_t margin, int do_balance) { + bw_weights_error_t berr = BW_WEIGHTS_NO_ERROR; + + // Wed + Wmd + Wgd == 1 + if (!CHECK_EQ(Wed + Wmd + Wgd, scale, margin)) { + berr = BW_WEIGHTS_SUMD_ERROR; + goto out; + } + + // Wmg + Wgg == 1 + if (!CHECK_EQ(Wmg + Wgg, scale, margin)) { + berr = BW_WEIGHTS_SUMG_ERROR; + goto out; + } + + // Wme + Wee == 1 + if (!CHECK_EQ(Wme + Wee, scale, margin)) { + berr = BW_WEIGHTS_SUME_ERROR; + goto out; + } + + // Verify weights within range 0->1 + if (!RANGE_CHECK(Wgg, Wgd, Wmg, Wme, Wmd, Wed, Wee, scale)) { + berr = BW_WEIGHTS_RANGE_ERROR; + goto out; + } + + if (do_balance) { + // Wgg*G + Wgd*D == Wee*E + Wed*D, already scaled + if (!CHECK_EQ(Wgg*G + Wgd*D, Wee*E + Wed*D, (margin*T)/3)) { + berr = BW_WEIGHTS_BALANCE_EG_ERROR; + goto out; + } + + // Wgg*G + Wgd*D == M*scale + Wmd*D + Wme*E + Wmg*G, already scaled + if (!CHECK_EQ(Wgg*G + Wgd*D, M*scale + Wmd*D + Wme*E + Wmg*G, + (margin*T)/3)) { + berr = BW_WEIGHTS_BALANCE_MID_ERROR; + goto out; + } + } + + out: + if (berr) { + log_info(LD_DIR, + "Bw weight mismatch %d. G="I64_FORMAT" M="I64_FORMAT + " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT + " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d" + " Wgd=%d Wgg=%d Wme=%d Wmg=%d", + berr, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee, + (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg); + } + + return berr; +} + +/** + * This function computes the bandwidth weights for consensus method 10. + * + * It returns true if weights could be computed, false otherwise. + */ +static int +networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G, + int64_t M, int64_t E, int64_t D, + int64_t T, int64_t weight_scale) +{ + bw_weights_error_t berr = 0; + int64_t Wgg = -1, Wgd = -1; + int64_t Wmg = -1, Wme = -1, Wmd = -1; + int64_t Wed = -1, Wee = -1; + const char *casename; + char buf[512]; + int r; + + if (G <= 0 || M <= 0 || E <= 0 || D <= 0) { + log_warn(LD_DIR, "Consensus with empty bandwidth: " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT + " D="I64_FORMAT" T="I64_FORMAT, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + return 0; + } + + /* + * Computed from cases in 3.4.3 of dir-spec.txt + * + * 1. Neither are scarce + * 2. Both Guard and Exit are scarce + * a. R+D <= S + * b. R+D > S + * 3. One of Guard or Exit is scarce + * a. S+D < T/3 + * b. S+D >= T/3 + */ + if (3*E >= T && 3*G >= T) { // E >= T/3 && G >= T/3 + /* Case 1: Neither are scarce. */ + casename = "Case 1 (Wgd=Wmd=Wed)"; + Wgd = weight_scale/3; + Wed = weight_scale/3; + Wmd = weight_scale/3; + Wee = (weight_scale*(E+G+M))/(3*E); + Wme = weight_scale - Wee; + Wmg = (weight_scale*(2*G-E-M))/(3*G); + Wgg = weight_scale - Wmg; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, + weight_scale, G, M, E, D, T, 10, 1); + + if (berr) { + log_warn(LD_DIR, + "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT + " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT + " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d" + " Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d", + berr, casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee, + (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale); + return 0; + } + } else if (3*E < T && 3*G < T) { // E < T/3 && G < T/3 + int64_t R = MIN(E, G); + int64_t S = MAX(E, G); + /* + * Case 2: Both Guards and Exits are scarce + * Balance D between E and G, depending upon + * D capacity and scarcity. + */ + if (R+D < S) { // Subcase a + Wgg = weight_scale; + Wee = weight_scale; + Wmg = 0; + Wme = 0; + Wmd = 0; + if (E < G) { + casename = "Case 2a (E scarce)"; + Wed = weight_scale; + Wgd = 0; + } else { /* E >= G */ + casename = "Case 2a (G scarce)"; + Wed = 0; + Wgd = weight_scale; + } + } else { // Subcase b: R+D >= S + casename = "Case 2b1 (Wgg=1, Wmd=Wgd)"; + Wee = (weight_scale*(E - G + M))/E; + Wed = (weight_scale*(D - 2*E + 4*G - 2*M))/(3*D); + Wme = (weight_scale*(G-M))/E; + Wmg = 0; + Wgg = weight_scale; + Wmd = (weight_scale - Wed)/2; + Wgd = (weight_scale - Wed)/2; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, + weight_scale, G, M, E, D, T, 10, 1); + + if (berr) { + casename = "Case 2b2 (Wgg=1, Wee=1)"; + Wgg = weight_scale; + Wee = weight_scale; + Wed = (weight_scale*(D - 2*E + G + M))/(3*D); + Wmd = (weight_scale*(D - 2*M + G + E))/(3*D); + Wme = 0; + Wmg = 0; + + if (Wmd < 0) { // Can happen if M > T/3 + casename = "Case 2b3 (Wmd=0)"; + Wmd = 0; + log_warn(LD_DIR, + "Too much Middle bandwidth on the network to calculate " + "balanced bandwidth-weights. Consider increasing the " + "number of Guard nodes by lowering the requirements."); + } + Wgd = weight_scale - Wed - Wmd; + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, + Wed, weight_scale, G, M, E, D, T, 10, 1); + } + if (berr != BW_WEIGHTS_NO_ERROR && + berr != BW_WEIGHTS_BALANCE_MID_ERROR) { + log_warn(LD_DIR, + "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT + " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT + " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d" + " Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d", + berr, casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee, + (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale); + return 0; + } + } + } else { // if (E < T/3 || G < T/3) { + int64_t S = MIN(E, G); + // Case 3: Exactly one of Guard or Exit is scarce + if (!(3*E < T || 3*G < T) || !(3*G >= T || 3*E >= T)) { + log_warn(LD_BUG, + "Bw-Weights Case 3 v10 but with G="I64_FORMAT" M=" + I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + } + + if (3*(S+D) < T) { // Subcase a: S+D < T/3 + if (G < E) { + casename = "Case 3a (G scarce)"; + Wgg = Wgd = weight_scale; + Wmd = Wed = Wmg = 0; + // Minor subcase, if E is more scarce than M, + // keep its bandwidth in place. + if (E < M) Wme = 0; + else Wme = (weight_scale*(E-M))/(2*E); + Wee = weight_scale-Wme; + } else { // G >= E + casename = "Case 3a (E scarce)"; + Wee = Wed = weight_scale; + Wmd = Wgd = Wme = 0; + // Minor subcase, if G is more scarce than M, + // keep its bandwidth in place. + if (G < M) Wmg = 0; + else Wmg = (weight_scale*(G-M))/(2*G); + Wgg = weight_scale-Wmg; + } + } else { // Subcase b: S+D >= T/3 + // D != 0 because S+D >= T/3 + if (G < E) { + casename = "Case 3bg (G scarce, Wgg=1, Wmd == Wed)"; + Wgg = weight_scale; + Wgd = (weight_scale*(D - 2*G + E + M))/(3*D); + Wmg = 0; + Wee = (weight_scale*(E+M))/(2*E); + Wme = weight_scale - Wee; + Wmd = (weight_scale - Wgd)/2; + Wed = (weight_scale - Wgd)/2; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, + Wed, weight_scale, G, M, E, D, T, 10, 1); + } else { // G >= E + casename = "Case 3be (E scarce, Wee=1, Wmd == Wgd)"; + Wee = weight_scale; + Wed = (weight_scale*(D - 2*E + G + M))/(3*D); + Wme = 0; + Wgg = (weight_scale*(G+M))/(2*G); + Wmg = weight_scale - Wgg; + Wmd = (weight_scale - Wed)/2; + Wgd = (weight_scale - Wed)/2; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, + Wed, weight_scale, G, M, E, D, T, 10, 1); + } + if (berr) { + log_warn(LD_DIR, + "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT + " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT + " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d" + " Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d", + berr, casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee, + (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale); + return 0; + } + } + } + + /* We cast down the weights to 32 bit ints on the assumption that + * weight_scale is ~= 10000. We need to ensure a rogue authority + * doesn't break this assumption to rig our weights */ + tor_assert(0 < weight_scale && weight_scale < INT32_MAX); + + /* + * Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine + * that middle nodes need different bandwidth weights for dirport traffic, + * or that weird exit policies need special weight, or that bridges + * need special weight. + * + * NOTE: This list is sorted. + */ + r = tor_snprintf(buf, sizeof(buf), + "bandwidth-weights Wbd=%d Wbe=%d Wbg=%d Wbm=%d " + "Wdb=%d " + "Web=%d Wed=%d Wee=%d Weg=%d Wem=%d " + "Wgb=%d Wgd=%d Wgg=%d Wgm=%d " + "Wmb=%d Wmd=%d Wme=%d Wmg=%d Wmm=%d\n", + (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale, + (int)weight_scale, + (int)weight_scale, (int)Wed, (int)Wee, (int)Wed, (int)Wee, + (int)weight_scale, (int)Wgd, (int)Wgg, (int)Wgg, + (int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale); + if (r<0) { + log_warn(LD_BUG, + "Not enough space in buffer for bandwidth-weights line."); + *buf = '\0'; + return 0; + } + smartlist_add(chunks, tor_strdup(buf)); + + log_notice(LD_CIRC, "Computed bandwidth weights for %s with v10: " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + return 1; +} +/** + * This function computes the bandwidth weights for consensus method 9. + * + * It has been obsoleted in favor of consensus method 10. + */ +static void +networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M, + int64_t E, int64_t D, int64_t T, + int64_t weight_scale) +{ + int64_t Wgg = -1, Wgd = -1; + int64_t Wmg = -1, Wme = -1, Wmd = -1; + int64_t Wed = -1, Wee = -1; + const char *casename; + char buf[512]; + int r; + + if (G <= 0 || M <= 0 || E <= 0 || D <= 0) { + log_warn(LD_DIR, "Consensus with empty bandwidth: " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT + " D="I64_FORMAT" T="I64_FORMAT, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + return; + } + + /* + * Computed from cases in 3.4.3 of dir-spec.txt + * + * 1. Neither are scarce + * 2. Both Guard and Exit are scarce + * a. R+D <= S + * b. R+D > S + * 3. One of Guard or Exit is scarce + * a. S+D < T/3 + * b. S+D >= T/3 + */ + if (3*E >= T && 3*G >= T) { // E >= T/3 && G >= T/3 + bw_weights_error_t berr = 0; + /* Case 1: Neither are scarce. + * + * Attempt to ensure that we have a large amount of exit bandwidth + * in the middle position. + */ + casename = "Case 1 (Wme*E = Wmd*D)"; + Wgg = (weight_scale*(D+E+G+M))/(3*G); + if (D==0) Wmd = 0; + else Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D); + Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E); + Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E); + Wgd = 0; + Wmg = weight_scale - Wgg; + Wed = weight_scale - Wmd; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, + weight_scale, G, M, E, D, T, 10, 1); + + if (berr) { + log_warn(LD_DIR, "Bw Weights error %d for case %s. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT + " D="I64_FORMAT" T="I64_FORMAT, + berr, casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + } + } else if (3*E < T && 3*G < T) { // E < T/3 && G < T/3 + int64_t R = MIN(E, G); + int64_t S = MAX(E, G); + /* + * Case 2: Both Guards and Exits are scarce + * Balance D between E and G, depending upon + * D capacity and scarcity. + */ + if (R+D < S) { // Subcase a + Wgg = weight_scale; + Wee = weight_scale; + Wmg = 0; + Wme = 0; + Wmd = 0; + if (E < G) { + casename = "Case 2a (E scarce)"; + Wed = weight_scale; + Wgd = 0; + } else { /* E >= G */ + casename = "Case 2a (G scarce)"; + Wed = 0; + Wgd = weight_scale; + } + } else { // Subcase b: R+D > S + bw_weights_error_t berr = 0; + casename = "Case 2b (Wme*E == Wmd*D)"; + if (D != 0) { + Wgg = weight_scale; + Wgd = (weight_scale*(D + E - 2*G + M))/(3*D); // T/3 >= G (Ok) + Wmd = (weight_scale*(D + E + G - 2*M))/(6*D); // T/3 >= M + Wme = (weight_scale*(D + E + G - 2*M))/(6*E); + Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E); // 2E+M >= T/3 + Wmg = 0; + Wed = weight_scale - Wgd - Wmd; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed, + weight_scale, G, M, E, D, T, 10, 1); + } + + if (D == 0 || berr) { // Can happen if M > T/3 + casename = "Case 2b (E=G)"; + Wgg = weight_scale; + Wee = weight_scale; + Wmg = 0; + Wme = 0; + Wmd = 0; + if (D == 0) Wgd = 0; + else Wgd = (weight_scale*(D+E-G))/(2*D); + Wed = weight_scale - Wgd; + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, + Wed, weight_scale, G, M, E, D, T, 10, 1); + } + if (berr != BW_WEIGHTS_NO_ERROR && + berr != BW_WEIGHTS_BALANCE_MID_ERROR) { + log_warn(LD_DIR, "Bw Weights error %d for case %s. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT + " D="I64_FORMAT" T="I64_FORMAT, + berr, casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + } + } + } else { // if (E < T/3 || G < T/3) { + int64_t S = MIN(E, G); + // Case 3: Exactly one of Guard or Exit is scarce + if (!(3*E < T || 3*G < T) || !(3*G >= T || 3*E >= T)) { + log_warn(LD_BUG, + "Bw-Weights Case 3 but with G="I64_FORMAT" M=" + I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + } + + if (3*(S+D) < T) { // Subcase a: S+D < T/3 + if (G < E) { + casename = "Case 3a (G scarce)"; + Wgg = Wgd = weight_scale; + Wmd = Wed = Wmg = 0; + // Minor subcase, if E is more scarce than M, + // keep its bandwidth in place. + if (E < M) Wme = 0; + else Wme = (weight_scale*(E-M))/(2*E); + Wee = weight_scale-Wme; + } else { // G >= E + casename = "Case 3a (E scarce)"; + Wee = Wed = weight_scale; + Wmd = Wgd = Wme = 0; + // Minor subcase, if G is more scarce than M, + // keep its bandwidth in place. + if (G < M) Wmg = 0; + else Wmg = (weight_scale*(G-M))/(2*G); + Wgg = weight_scale-Wmg; + } + } else { // Subcase b: S+D >= T/3 + bw_weights_error_t berr = 0; + // D != 0 because S+D >= T/3 + if (G < E) { + casename = "Case 3b (G scarce, Wme*E == Wmd*D)"; + Wgd = (weight_scale*(D + E - 2*G + M))/(3*D); + Wmd = (weight_scale*(D + E + G - 2*M))/(6*D); + Wme = (weight_scale*(D + E + G - 2*M))/(6*E); + Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E); + Wgg = weight_scale; + Wmg = 0; + Wed = weight_scale - Wgd - Wmd; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, + Wed, weight_scale, G, M, E, D, T, 10, 1); + } else { // G >= E + casename = "Case 3b (E scarce, Wme*E == Wmd*D)"; + Wgg = (weight_scale*(D + E + G + M))/(3*G); + Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D); + Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E); + Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E); + Wgd = 0; + Wmg = weight_scale - Wgg; + Wed = weight_scale - Wmd; + + berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, + Wed, weight_scale, G, M, E, D, T, 10, 1); + } + if (berr) { + log_warn(LD_DIR, "Bw Weights error %d for case %s. " + "G="I64_FORMAT" M="I64_FORMAT + " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT, + berr, casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + } + } + } + + /* We cast down the weights to 32 bit ints on the assumption that + * weight_scale is ~= 10000. We need to ensure a rogue authority + * doesn't break this assumption to rig our weights */ + tor_assert(0 < weight_scale && weight_scale < INT32_MAX); + + if (Wgg < 0 || Wgg > weight_scale) { + log_warn(LD_DIR, "Bw %s: Wgg="I64_FORMAT"! G="I64_FORMAT + " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, I64_PRINTF_ARG(Wgg), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + + Wgg = MAX(MIN(Wgg, weight_scale), 0); + } + if (Wgd < 0 || Wgd > weight_scale) { + log_warn(LD_DIR, "Bw %s: Wgd="I64_FORMAT"! G="I64_FORMAT + " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, I64_PRINTF_ARG(Wgd), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + Wgd = MAX(MIN(Wgd, weight_scale), 0); + } + if (Wmg < 0 || Wmg > weight_scale) { + log_warn(LD_DIR, "Bw %s: Wmg="I64_FORMAT"! G="I64_FORMAT + " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, I64_PRINTF_ARG(Wmg), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + Wmg = MAX(MIN(Wmg, weight_scale), 0); + } + if (Wme < 0 || Wme > weight_scale) { + log_warn(LD_DIR, "Bw %s: Wme="I64_FORMAT"! G="I64_FORMAT + " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, I64_PRINTF_ARG(Wme), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + Wme = MAX(MIN(Wme, weight_scale), 0); + } + if (Wmd < 0 || Wmd > weight_scale) { + log_warn(LD_DIR, "Bw %s: Wmd="I64_FORMAT"! G="I64_FORMAT + " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, I64_PRINTF_ARG(Wmd), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + Wmd = MAX(MIN(Wmd, weight_scale), 0); + } + if (Wee < 0 || Wee > weight_scale) { + log_warn(LD_DIR, "Bw %s: Wee="I64_FORMAT"! G="I64_FORMAT + " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, I64_PRINTF_ARG(Wee), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + Wee = MAX(MIN(Wee, weight_scale), 0); + } + if (Wed < 0 || Wed > weight_scale) { + log_warn(LD_DIR, "Bw %s: Wed="I64_FORMAT"! G="I64_FORMAT + " M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, I64_PRINTF_ARG(Wed), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); + Wed = MAX(MIN(Wed, weight_scale), 0); + } + + // Add consensus weight keywords + smartlist_add(chunks, tor_strdup("bandwidth-weights ")); + /* + * Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine + * that middle nodes need different bandwidth weights for dirport traffic, + * or that weird exit policies need special weight, or that bridges + * need special weight. + * + * NOTE: This list is sorted. + */ + r = tor_snprintf(buf, sizeof(buf), + "Wbd=%d Wbe=%d Wbg=%d Wbm=%d " + "Wdb=%d " + "Web=%d Wed=%d Wee=%d Weg=%d Wem=%d " + "Wgb=%d Wgd=%d Wgg=%d Wgm=%d " + "Wmb=%d Wmd=%d Wme=%d Wmg=%d Wmm=%d\n", + (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale, + (int)weight_scale, + (int)weight_scale, (int)Wed, (int)Wee, (int)Wed, (int)Wee, + (int)weight_scale, (int)Wgd, (int)Wgg, (int)Wgg, + (int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale); + if (r<0) { + log_warn(LD_BUG, + "Not enough space in buffer for bandwidth-weights line."); + *buf = '\0'; + } + smartlist_add(chunks, tor_strdup(buf)); + log_notice(LD_CIRC, "Computed bandwidth weights for %s with v9: " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT, + casename, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T)); +} + /** Given a list of vote networkstatus_t in <b>votes</b>, our public * authority <b>identity_key</b>, our private authority <b>signing_key</b>, * and the number of <b>total_authorities</b> that we believe exist in our @@ -489,18 +1346,27 @@ networkstatus_compute_consensus(smartlist_t *votes, crypto_pk_env_t *identity_key, crypto_pk_env_t *signing_key, const char *legacy_id_key_digest, - crypto_pk_env_t *legacy_signing_key) + crypto_pk_env_t *legacy_signing_key, + consensus_flavor_t flavor) { smartlist_t *chunks; char *result = NULL; int consensus_method; - time_t valid_after, fresh_until, valid_until; int vote_seconds, dist_seconds; char *client_versions = NULL, *server_versions = NULL; smartlist_t *flags; + const char *flavor_name; + int64_t G=0, M=0, E=0, D=0, T=0; /* For bandwidth weights */ + const routerstatus_format_type_t rs_format = + flavor == FLAV_NS ? NS_V3_CONSENSUS : NS_V3_CONSENSUS_MICRODESC; + char *params = NULL; + int added_weights = 0; + tor_assert(flavor == FLAV_NS || flavor == FLAV_MICRODESC); tor_assert(total_authorities >= smartlist_len(votes)); + flavor_name = networkstatus_get_flavor_name(flavor); + if (!smartlist_len(votes)) { log_warn(LD_DIR, "Can't compute a consensus from no votes."); return NULL; @@ -593,7 +1459,7 @@ networkstatus_compute_consensus(smartlist_t *votes, chunks = smartlist_create(); { - char buf[1024]; + char *buf=NULL; char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1], vu_buf[ISO_TIME_LEN+1]; char *flaglist; @@ -602,16 +1468,20 @@ networkstatus_compute_consensus(smartlist_t *votes, format_iso_time(vu_buf, valid_until); flaglist = smartlist_join_strings(flags, " ", 0, NULL); - smartlist_add(chunks, tor_strdup("network-status-version 3\n" - "vote-status consensus\n")); + tor_asprintf(&buf, "network-status-version 3%s%s\n" + "vote-status consensus\n", + flavor == FLAV_NS ? "" : " ", + flavor == FLAV_NS ? "" : flavor_name); + + smartlist_add(chunks, buf); if (consensus_method >= 2) { - tor_snprintf(buf, sizeof(buf), "consensus-method %d\n", + tor_asprintf(&buf, "consensus-method %d\n", consensus_method); - smartlist_add(chunks, tor_strdup(buf)); + smartlist_add(chunks, buf); } - tor_snprintf(buf, sizeof(buf), + tor_asprintf(&buf, "valid-after %s\n" "fresh-until %s\n" "valid-until %s\n" @@ -622,18 +1492,26 @@ networkstatus_compute_consensus(smartlist_t *votes, va_buf, fu_buf, vu_buf, vote_seconds, dist_seconds, client_versions, server_versions, flaglist); - smartlist_add(chunks, tor_strdup(buf)); + smartlist_add(chunks, buf); tor_free(flaglist); } + if (consensus_method >= MIN_METHOD_FOR_PARAMS) { + params = dirvote_compute_params(votes); + if (params) { + smartlist_add(chunks, tor_strdup("params ")); + smartlist_add(chunks, params); + smartlist_add(chunks, tor_strdup("\n")); + } + } + /* Sort the votes. */ smartlist_sort(votes, _compare_votes_by_authority_id); /* Add the authority sections. */ { smartlist_t *dir_sources = smartlist_create(); - SMARTLIST_FOREACH(votes, networkstatus_t *, v, - { + SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { dir_src_ent_t *e = tor_malloc_zero(sizeof(dir_src_ent_t)); e->v = v; e->digest = get_voter(v)->identity_digest; @@ -647,18 +1525,17 @@ networkstatus_compute_consensus(smartlist_t *votes, e_legacy->is_legacy = 1; smartlist_add(dir_sources, e_legacy); } - }); + } SMARTLIST_FOREACH_END(v); smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id); - SMARTLIST_FOREACH(dir_sources, const dir_src_ent_t *, e, - { - char buf[1024]; + 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; networkstatus_voter_info_t *voter = get_voter(v); + char *buf = NULL; if (e->is_legacy) tor_assert(consensus_method >= 2); @@ -669,22 +1546,22 @@ networkstatus_compute_consensus(smartlist_t *votes, base16_encode(votedigest, sizeof(votedigest), voter->vote_digest, DIGEST_LEN); - tor_snprintf(buf, sizeof(buf), + tor_asprintf(&buf, "dir-source %s%s %s %s %s %d %d\n", voter->nickname, e->is_legacy ? "-legacy" : "", fingerprint, voter->address, ip, voter->dir_port, voter->or_port); - smartlist_add(chunks, tor_strdup(buf)); + smartlist_add(chunks, buf); if (! e->is_legacy) { - tor_snprintf(buf, sizeof(buf), + tor_asprintf(&buf, "contact %s\n" "vote-digest %s\n", voter->contact, votedigest); - smartlist_add(chunks, tor_strdup(buf)); + smartlist_add(chunks, buf); } - }); + } SMARTLIST_FOREACH_END(e); SMARTLIST_FOREACH(dir_sources, dir_src_ent_t *, e, tor_free(e)); smartlist_free(dir_sources); } @@ -701,7 +1578,10 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_t *versions = smartlist_create(); smartlist_t *exitsummaries = smartlist_create(); uint32_t *bandwidths = tor_malloc(sizeof(uint32_t) * smartlist_len(votes)); + uint32_t *measured_bws = tor_malloc(sizeof(uint32_t) * + smartlist_len(votes)); int num_bandwidths; + int num_mbws; int *n_voter_flags; /* n_voter_flags[j] is the number of flags that * votes[j] knows about. */ @@ -813,10 +1693,12 @@ networkstatus_compute_consensus(smartlist_t *votes, const char *chosen_name = NULL; int exitsummary_disagreement = 0; int is_named = 0, is_unnamed = 0, is_running = 0; + int is_guard = 0, is_exit = 0; int naming_conflict = 0; int n_listing = 0; int i; - char buf[256]; + char *buf=NULL; + char microdesc_digest[DIGEST256_LEN]; /* Of the next-to-be-considered digest in each voter, which is first? */ SMARTLIST_FOREACH(votes, networkstatus_t *, v, { @@ -835,6 +1717,7 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_clear(chosen_flags); smartlist_clear(versions); num_bandwidths = 0; + num_mbws = 0; /* Okay, go through all the entries for this digest. */ SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { @@ -868,6 +1751,9 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* count bandwidths */ + if (rs->status.has_measured_bw) + measured_bws[num_mbws++] = rs->status.measured_bw; + if (rs->status.has_bandwidth) bandwidths[num_bandwidths++] = rs->status.bandwidth; } SMARTLIST_FOREACH_END(v); @@ -879,7 +1765,9 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Figure out the most popular opinion of what the most recent * routerinfo and its contents are. */ - rs = compute_routerstatus_consensus(matching_descs); + memset(microdesc_digest, 0, sizeof(microdesc_digest)); + rs = compute_routerstatus_consensus(matching_descs, consensus_method, + microdesc_digest); /* Copy bits of that into rs_out. */ tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN)); memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN); @@ -925,7 +1813,11 @@ networkstatus_compute_consensus(smartlist_t *votes, } else { if (flag_counts[fl_sl_idx] > n_flag_voters[fl_sl_idx]/2) { smartlist_add(chosen_flags, (char*)fl); - if (!strcmp(fl, "Running")) + if (!strcmp(fl, "Exit")) + is_exit = 1; + else if (!strcmp(fl, "Guard")) + is_guard = 1; + else if (!strcmp(fl, "Running")) is_running = 1; } } @@ -945,11 +1837,31 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* Pick a bandwidth */ - if (consensus_method >= 5 && num_bandwidths > 0) { + if (consensus_method >= 6 && num_mbws > 2) { + rs_out.has_bandwidth = 1; + rs_out.bandwidth = median_uint32(measured_bws, num_mbws); + } else if (consensus_method >= 5 && num_bandwidths > 0) { rs_out.has_bandwidth = 1; rs_out.bandwidth = median_uint32(bandwidths, num_bandwidths); } + if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { + if (rs_out.has_bandwidth) { + T += rs_out.bandwidth; + if (is_exit && is_guard) + D += rs_out.bandwidth; + else if (is_exit) + E += rs_out.bandwidth; + else if (is_guard) + G += rs_out.bandwidth; + else + M += rs_out.bandwidth; + } else { + log_warn(LD_BUG, "Missing consensus bandwidth for router %s", + rs_out.nickname); + } + } + /* Ok, we already picked a descriptor digest we want to list * previously. Now we want to use the exit policy summary from * that descriptor. If everybody plays nice all the voters who @@ -1034,11 +1946,23 @@ networkstatus_compute_consensus(smartlist_t *votes, } } - /* Okay!! Now we can write the descriptor... */ - /* First line goes into "buf". */ - routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1, 0); - smartlist_add(chunks, tor_strdup(buf)); - /* Second line is all flags. The "\n" is missing. */ + { + char buf[4096]; + /* Okay!! Now we can write the descriptor... */ + /* First line goes into "buf". */ + routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, + rs_format); + smartlist_add(chunks, tor_strdup(buf)); + } + /* Now an m line, if applicable. */ + if (flavor == FLAV_MICRODESC && + !tor_digest256_is_zero(microdesc_digest)) { + char m[BASE64_DIGEST256_LEN+1], *cp; + digest256_to_base64(m, microdesc_digest); + tor_asprintf(&cp, "m %s\n", m); + smartlist_add(chunks, cp); + } + /* Next line is all flags. The "\n" is missing. */ smartlist_add(chunks, smartlist_join_strings(chosen_flags, " ", 0, NULL)); /* Now the version line. */ @@ -1049,24 +1973,16 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_add(chunks, tor_strdup("\n")); /* Now the weight line. */ if (rs_out.has_bandwidth) { - int r = tor_snprintf(buf, sizeof(buf), - "w Bandwidth=%d\n", rs_out.bandwidth); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer for weight line."); - *buf = '\0'; - } - smartlist_add(chunks, tor_strdup(buf)); - }; + char *cp=NULL; + tor_asprintf(&cp, "w Bandwidth=%d\n", rs_out.bandwidth); + smartlist_add(chunks, cp); + } + /* Now the exitpolicy summary line. */ - if (rs_out.has_exitsummary) { - char buf[MAX_POLICY_LINE_LEN+1]; - int r = tor_snprintf(buf, sizeof(buf), "p %s\n", rs_out.exitsummary); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer for exitpolicy line."); - *buf = '\0'; - } - smartlist_add(chunks, tor_strdup(buf)); - }; + if (rs_out.has_exitsummary && flavor == FLAV_NS) { + tor_asprintf(&buf, "p %s\n", rs_out.exitsummary); + smartlist_add(chunks, buf); + } /* And the loop is over and we move on to the next router */ } @@ -1087,34 +2003,97 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_free(versions); smartlist_free(exitsummaries); tor_free(bandwidths); + tor_free(measured_bws); + } + + if (consensus_method >= MIN_METHOD_FOR_FOOTER) { + /* Starting with consensus method 9, we clearly mark the directory + * footer region */ + smartlist_add(chunks, tor_strdup("directory-footer\n")); + } + + if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { + int64_t weight_scale = BW_WEIGHT_SCALE; + char *bw_weight_param = NULL; + + // Parse params, extract BW_WEIGHT_SCALE if present + // DO NOT use consensus_param_bw_weight_scale() in this code! + // The consensus is not formed yet! + if (params) { + if (strcmpstart(params, "bwweightscale=") == 0) + bw_weight_param = params; + else + bw_weight_param = strstr(params, " bwweightscale="); + } + + if (bw_weight_param) { + int ok=0; + char *eq = strchr(bw_weight_param, '='); + if (eq) { + weight_scale = tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, + NULL); + if (!ok) { + log_warn(LD_DIR, "Bad element '%s' in bw weight param", + escaped(bw_weight_param)); + weight_scale = BW_WEIGHT_SCALE; + } + } else { + log_warn(LD_DIR, "Bad element '%s' in bw weight param", + escaped(bw_weight_param)); + weight_scale = BW_WEIGHT_SCALE; + } + } + + if (consensus_method < 10) { + networkstatus_compute_bw_weights_v9(chunks, G, M, E, D, T, weight_scale); + added_weights = 1; + } else { + added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, + T, weight_scale); + } } /* Add a signature. */ { - char digest[DIGEST_LEN]; + char digest[DIGEST256_LEN]; char fingerprint[HEX_DIGEST_LEN+1]; char signing_key_fingerprint[HEX_DIGEST_LEN+1]; + digest_algorithm_t digest_alg = + flavor == FLAV_NS ? DIGEST_SHA1 : DIGEST_SHA256; + size_t digest_len = + flavor == FLAV_NS ? DIGEST_LEN : DIGEST256_LEN; + const char *algname = crypto_digest_algorithm_get_name(digest_alg); + char *buf = NULL; + char sigbuf[4096]; - char buf[4096]; smartlist_add(chunks, tor_strdup("directory-signature ")); /* Compute the hash of the chunks. */ - hash_list_members(digest, chunks); + hash_list_members(digest, digest_len, chunks, digest_alg); /* Get the fingerprints */ crypto_pk_get_fingerprint(identity_key, fingerprint, 0); crypto_pk_get_fingerprint(signing_key, signing_key_fingerprint, 0); /* add the junk that will go at the end of the line. */ - tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint, - signing_key_fingerprint); + if (flavor == FLAV_NS) { + tor_asprintf(&buf, "%s %s\n", fingerprint, + signing_key_fingerprint); + } else { + tor_asprintf(&buf, "%s %s %s\n", + algname, fingerprint, + signing_key_fingerprint); + } + smartlist_add(chunks, buf); /* And the signature. */ - if (router_append_dirobj_signature(buf, sizeof(buf), digest, + sigbuf[0] = '\0'; + if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf), + digest, digest_len, signing_key)) { log_warn(LD_BUG, "Couldn't sign consensus networkstatus."); return NULL; /* This leaks, but it should never happen. */ } - smartlist_add(chunks, tor_strdup(buf)); + smartlist_add(chunks, tor_strdup(sigbuf)); if (legacy_id_key_digest && legacy_signing_key && consensus_method >= 3) { smartlist_add(chunks, tor_strdup("directory-signature ")); @@ -1122,14 +2101,23 @@ networkstatus_compute_consensus(smartlist_t *votes, legacy_id_key_digest, DIGEST_LEN); crypto_pk_get_fingerprint(legacy_signing_key, signing_key_fingerprint, 0); - tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint, - signing_key_fingerprint); - if (router_append_dirobj_signature(buf, sizeof(buf), digest, + if (flavor == FLAV_NS) { + tor_asprintf(&buf, "%s %s\n", fingerprint, + signing_key_fingerprint); + } else { + tor_asprintf(&buf, "%s %s %s\n", + algname, fingerprint, + signing_key_fingerprint); + } + smartlist_add(chunks, buf); + sigbuf[0] = '\0'; + if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf), + digest, digest_len, legacy_signing_key)) { log_warn(LD_BUG, "Couldn't sign consensus networkstatus."); return NULL; /* This leaks, but it should never happen. */ } - smartlist_add(chunks, tor_strdup(buf)); + smartlist_add(chunks, tor_strdup(sigbuf)); } } @@ -1146,11 +2134,15 @@ networkstatus_compute_consensus(smartlist_t *votes, networkstatus_t *c; if (!(c = networkstatus_parse_vote_from_string(result, NULL, NS_TYPE_CONSENSUS))) { - log_err(LD_BUG,"Generated a networkstatus consensus we couldn't " + log_err(LD_BUG, "Generated a networkstatus consensus we couldn't " "parse."); tor_free(result); return NULL; } + // Verify balancing parameters + if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS && added_weights) { + networkstatus_verify_bw_weights(c); + } networkstatus_vote_free(c); } @@ -1171,10 +2163,14 @@ networkstatus_add_detached_signatures(networkstatus_t *target, const char **msg_out) { int r = 0; + const char *flavor; + smartlist_t *siglist; tor_assert(sigs); tor_assert(target); tor_assert(target->type == NS_TYPE_CONSENSUS); + flavor = networkstatus_get_flavor_name(target->flavor); + /* Do the times seem right? */ if (target->valid_after != sigs->valid_after) { *msg_out = "Valid-After times do not match " @@ -1191,79 +2187,179 @@ networkstatus_add_detached_signatures(networkstatus_t *target, "when adding detached signatures to consensus"; return -1; } - /* Are they the same consensus? */ - if (memcmp(target->networkstatus_digest, sigs->networkstatus_digest, - DIGEST_LEN)) { - *msg_out = "Digest mismatch when adding detached signatures to consensus"; + siglist = strmap_get(sigs->signatures, flavor); + if (!siglist) { + *msg_out = "No signatures for given consensus flavor"; return -1; } - /* For each voter in src... */ - SMARTLIST_FOREACH_BEGIN(sigs->signatures, networkstatus_voter_info_t *, - src_voter) { - char voter_identity[HEX_DIGEST_LEN+1]; - networkstatus_voter_info_t *target_voter = - networkstatus_get_voter_by_id(target, src_voter->identity_digest); - authority_cert_t *cert = NULL; - - base16_encode(voter_identity, sizeof(voter_identity), - src_voter->identity_digest, DIGEST_LEN); - log_info(LD_DIR, "Looking at signature from %s", voter_identity); - /* If the target doesn't know about this voter, then forget it. */ - if (!target_voter) { - log_info(LD_DIR, "We do not know about %s", voter_identity); - continue; + /** Make sure all the digests we know match, and at least one matches. */ + { + digests_t *digests = strmap_get(sigs->digests, flavor); + int n_matches = 0; + digest_algorithm_t alg; + if (!digests) { + *msg_out = "No digests for given consensus flavor"; + return -1; + } + for (alg = DIGEST_SHA1; alg < N_DIGEST_ALGORITHMS; ++alg) { + if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) { + if (!memcmp(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) { + ++n_matches; + } else { + *msg_out = "Mismatched digest."; + return -1; + } } + } + if (!n_matches) { + *msg_out = "No regognized digests for given consensus flavor"; + } + } - /* If the target already has a good signature from this voter, then skip - * this one. */ - if (target_voter->good_signature) { - log_info(LD_DIR, "We already have a good signature from %s", - voter_identity); - continue; - } + /* For each voter in src... */ + SMARTLIST_FOREACH_BEGIN(siglist, document_signature_t *, sig) { + char voter_identity[HEX_DIGEST_LEN+1]; + networkstatus_voter_info_t *target_voter = + networkstatus_get_voter_by_id(target, sig->identity_digest); + authority_cert_t *cert = NULL; + const char *algorithm; + document_signature_t *old_sig = NULL; + + algorithm = crypto_digest_algorithm_get_name(sig->alg); + + base16_encode(voter_identity, sizeof(voter_identity), + sig->identity_digest, DIGEST_LEN); + log_info(LD_DIR, "Looking at signature from %s using %s", voter_identity, + algorithm); + /* If the target doesn't know about this voter, then forget it. */ + if (!target_voter) { + log_info(LD_DIR, "We do not know any voter with ID %s", voter_identity); + continue; + } - /* Try checking the signature if we haven't already. */ - if (!src_voter->good_signature && !src_voter->bad_signature) { - cert = authority_cert_get_by_digests(src_voter->identity_digest, - src_voter->signing_key_digest); - if (cert) { - networkstatus_check_voter_signature(target, src_voter, cert); - } + old_sig = voter_get_sig_by_algorithm(target_voter, sig->alg); + + /* If the target already has a good signature from this voter, then skip + * this one. */ + if (old_sig && old_sig->good_signature) { + log_info(LD_DIR, "We already have a good signature from %s using %s", + voter_identity, algorithm); + continue; + } + + /* Try checking the signature if we haven't already. */ + if (!sig->good_signature && !sig->bad_signature) { + cert = authority_cert_get_by_digests(sig->identity_digest, + sig->signing_key_digest); + if (cert) + networkstatus_check_document_signature(target, sig, cert); + } + + /* If this signature is good, or we don't have any signature yet, + * then maybe add it. */ + if (sig->good_signature || !old_sig || old_sig->bad_signature) { + log_info(LD_DIR, "Adding signature from %s with %s", voter_identity, + algorithm); + ++r; + if (old_sig) { + smartlist_remove(target_voter->sigs, old_sig); + document_signature_free(old_sig); } + smartlist_add(target_voter->sigs, document_signature_dup(sig)); + } else { + log_info(LD_DIR, "Not adding signature from %s", voter_identity); + } + } SMARTLIST_FOREACH_END(sig); + + return r; +} + +/** Return a newly allocated string containing all the signatures on + * <b>consensus</b> by all voters. If <b>for_detached_signatures</b> is true, + * then the signatures will be put in a detached signatures document, so + * prefix any non-NS-flavored signatures with "additional-signature" rather + * than "directory-signature". */ +static char * +networkstatus_format_signatures(networkstatus_t *consensus, + int for_detached_signatures) +{ + smartlist_t *elements; + char buf[4096]; + char *result = NULL; + int n_sigs = 0; + const consensus_flavor_t flavor = consensus->flavor; + const char *flavor_name = networkstatus_get_flavor_name(flavor); + const char *keyword; + + if (for_detached_signatures && flavor != FLAV_NS) + keyword = "additional-signature"; + else + keyword = "directory-signature"; + + elements = smartlist_create(); - /* If this signature is good, or we don't have any signature yet, - * then add it. */ - if (src_voter->good_signature || !target_voter->signature) { - log_info(LD_DIR, "Adding signature from %s", voter_identity); - ++r; - tor_free(target_voter->signature); - target_voter->signature = - tor_memdup(src_voter->signature, src_voter->signature_len); - memcpy(target_voter->signing_key_digest, src_voter->signing_key_digest, - DIGEST_LEN); - target_voter->signature_len = src_voter->signature_len; - target_voter->good_signature = src_voter->good_signature; - target_voter->bad_signature = src_voter->bad_signature; + SMARTLIST_FOREACH_BEGIN(consensus->voters, networkstatus_voter_info_t *, v) { + SMARTLIST_FOREACH_BEGIN(v->sigs, document_signature_t *, sig) { + char sk[HEX_DIGEST_LEN+1]; + char id[HEX_DIGEST_LEN+1]; + if (!sig->signature || sig->bad_signature) + continue; + ++n_sigs; + base16_encode(sk, sizeof(sk), sig->signing_key_digest, DIGEST_LEN); + base16_encode(id, sizeof(id), sig->identity_digest, DIGEST_LEN); + if (flavor == FLAV_NS) { + tor_snprintf(buf, sizeof(buf), + "%s %s %s\n-----BEGIN SIGNATURE-----\n", + keyword, id, sk); } else { - log_info(LD_DIR, "Not adding signature from %s", voter_identity); + const char *digest_name = + crypto_digest_algorithm_get_name(sig->alg); + tor_snprintf(buf, sizeof(buf), + "%s%s%s %s %s %s\n-----BEGIN SIGNATURE-----\n", + keyword, + for_detached_signatures ? " " : "", + for_detached_signatures ? flavor_name : "", + digest_name, id, sk); } - } SMARTLIST_FOREACH_END(src_voter); + smartlist_add(elements, tor_strdup(buf)); + base64_encode(buf, sizeof(buf), sig->signature, sig->signature_len); + strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf)); + smartlist_add(elements, tor_strdup(buf)); + } SMARTLIST_FOREACH_END(sig); + } SMARTLIST_FOREACH_END(v); - return r; + result = smartlist_join_strings(elements, "", 0, NULL); + SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); + smartlist_free(elements); + if (!n_sigs) + tor_free(result); + return result; } /** Return a newly allocated string holding the detached-signatures document - * corresponding to the signatures on <b>consensus</b>. */ + * corresponding to the signatures on <b>consensuses</b>, which must contain + * exactly one FLAV_NS consensus, and no more than one consensus for each + * other flavor. */ char * -networkstatus_get_detached_signatures(networkstatus_t *consensus) +networkstatus_get_detached_signatures(smartlist_t *consensuses) { smartlist_t *elements; char buf[4096]; - char *result = NULL; - int n_sigs = 0; - tor_assert(consensus); - tor_assert(consensus->type == NS_TYPE_CONSENSUS); + char *result = NULL, *sigs = NULL; + networkstatus_t *consensus_ns = NULL; + tor_assert(consensuses); + + SMARTLIST_FOREACH(consensuses, networkstatus_t *, ns, { + tor_assert(ns); + tor_assert(ns->type == NS_TYPE_CONSENSUS); + if (ns && ns->flavor == FLAV_NS) + consensus_ns = ns; + }); + if (!consensus_ns) { + log_warn(LD_BUG, "No NS consensus given."); + return NULL; + } elements = smartlist_create(); @@ -1272,10 +2368,11 @@ networkstatus_get_detached_signatures(networkstatus_t *consensus) vu_buf[ISO_TIME_LEN+1]; char d[HEX_DIGEST_LEN+1]; - base16_encode(d, sizeof(d), consensus->networkstatus_digest, DIGEST_LEN); - format_iso_time(va_buf, consensus->valid_after); - format_iso_time(fu_buf, consensus->fresh_until); - format_iso_time(vu_buf, consensus->valid_until); + base16_encode(d, sizeof(d), + consensus_ns->digests.d[DIGEST_SHA1], DIGEST_LEN); + format_iso_time(va_buf, consensus_ns->valid_after); + format_iso_time(fu_buf, consensus_ns->fresh_until); + format_iso_time(vu_buf, consensus_ns->valid_until); tor_snprintf(buf, sizeof(buf), "consensus-digest %s\n" @@ -1285,45 +2382,89 @@ networkstatus_get_detached_signatures(networkstatus_t *consensus) smartlist_add(elements, tor_strdup(buf)); } - SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, v, - { - char sk[HEX_DIGEST_LEN+1]; - char id[HEX_DIGEST_LEN+1]; - if (!v->signature || v->bad_signature) + /* Get all the digests for the non-FLAV_NS consensuses */ + SMARTLIST_FOREACH_BEGIN(consensuses, networkstatus_t *, ns) { + const char *flavor_name = networkstatus_get_flavor_name(ns->flavor); + int alg; + if (ns->flavor == FLAV_NS) + continue; + + /* start with SHA256; we don't include SHA1 for anything but the basic + * consensus. */ + for (alg = DIGEST_SHA256; alg < N_DIGEST_ALGORITHMS; ++alg) { + char d[HEX_DIGEST256_LEN+1]; + const char *alg_name = + crypto_digest_algorithm_get_name(alg); + if (tor_mem_is_zero(ns->digests.d[alg], DIGEST256_LEN)) continue; - ++n_sigs; - base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN); - base16_encode(id, sizeof(id), v->identity_digest, DIGEST_LEN); - tor_snprintf(buf, sizeof(buf), - "directory-signature %s %s\n-----BEGIN SIGNATURE-----\n", - id, sk); - smartlist_add(elements, tor_strdup(buf)); - base64_encode(buf, sizeof(buf), v->signature, v->signature_len); - strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf)); + base16_encode(d, sizeof(d), ns->digests.d[alg], DIGEST256_LEN); + tor_snprintf(buf, sizeof(buf), "additional-digest %s %s %s\n", + flavor_name, alg_name, d); smartlist_add(elements, tor_strdup(buf)); - }); + } + } SMARTLIST_FOREACH_END(ns); + + /* Now get all the sigs for non-FLAV_NS consensuses */ + SMARTLIST_FOREACH_BEGIN(consensuses, networkstatus_t *, ns) { + char *sigs; + if (ns->flavor == FLAV_NS) + continue; + sigs = networkstatus_format_signatures(ns, 1); + if (!sigs) { + log_warn(LD_DIR, "Couldn't format signatures"); + goto err; + } + smartlist_add(elements, sigs); + } SMARTLIST_FOREACH_END(ns); - result = smartlist_join_strings(elements, "", 0, NULL); + /* Now add the FLAV_NS consensus signatrures. */ + sigs = networkstatus_format_signatures(consensus_ns, 1); + if (!sigs) + goto err; + smartlist_add(elements, sigs); + result = smartlist_join_strings(elements, "", 0, NULL); + err: SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); smartlist_free(elements); - if (!n_sigs) - tor_free(result); return result; } +/** Return a newly allocated string holding a detached-signatures document for + * all of the in-progress consensuses in the <b>n_flavors</b>-element array at + * <b>pending</b>. */ +static char * +get_detached_signatures_from_pending_consensuses(pending_consensus_t *pending, + int n_flavors) +{ + int flav; + char *signatures; + smartlist_t *c = smartlist_create(); + for (flav = 0; flav < n_flavors; ++flav) { + if (pending[flav].consensus) + smartlist_add(c, pending[flav].consensus); + } + signatures = networkstatus_get_detached_signatures(c); + smartlist_free(c); + return signatures; +} + /** Release all storage held in <b>s</b>. */ void ns_detached_signatures_free(ns_detached_signatures_t *s) { + if (!s) + return; if (s->signatures) { - SMARTLIST_FOREACH(s->signatures, networkstatus_voter_info_t *, v, - { - tor_free(v->signature); - tor_free(v); - }); - smartlist_free(s->signatures); + STRMAP_FOREACH(s->signatures, flavor, smartlist_t *, sigs) { + SMARTLIST_FOREACH(sigs, document_signature_t *, sig, + document_signature_free(sig)); + smartlist_free(sigs); + } STRMAP_FOREACH_END; + strmap_free(s->signatures, NULL); + strmap_free(s->digests, _tor_free); } + tor_free(s); } @@ -1513,7 +2654,7 @@ dirvote_act(or_options_t *options, time_t now) if (voting_schedule.voting_ends < now && !voting_schedule.have_built_consensus) { log_notice(LD_DIR, "Time to compute a consensus."); - dirvote_compute_consensus(); + dirvote_compute_consensuses(); /* XXXX We will want to try again later if we haven't got enough * votes yet. Implement this if it turns out to ever happen. */ voting_schedule.have_built_consensus = 1; @@ -1550,14 +2691,13 @@ static smartlist_t *pending_vote_list = NULL; /** List of pending_vote_t for the previous vote. After we've used them to * build a consensus, the votes go here for the next period. */ static smartlist_t *previous_vote_list = NULL; -/** The body of the consensus that we're currently building. Once we - * have it built, it goes into dirserv.c */ -static char *pending_consensus_body = NULL; + +static pending_consensus_t pending_consensuses[N_CONSENSUS_FLAVORS]; + /** The detached signatures for the consensus that we're currently * building. */ static char *pending_consensus_signatures = NULL; -/** The parsed in-progress consensus document. */ -static networkstatus_t *pending_consensus = NULL; + /** List of ns_detached_signatures_t: hold signatures that get posted to us * before we have generated the consensus on our own. */ static smartlist_t *pending_consensus_signature_list = NULL; @@ -1651,15 +2791,39 @@ dirvote_fetch_missing_votes(void) static void dirvote_fetch_missing_signatures(void) { - if (!pending_consensus) + int need_any = 0; + int i; + for (i=0; i < N_CONSENSUS_FLAVORS; ++i) { + networkstatus_t *consensus = pending_consensuses[i].consensus; + if (!consensus || + networkstatus_check_consensus_signature(consensus, -1) == 1) { + /* We have no consensus, or we have one that's signed by everybody. */ + continue; + } + need_any = 1; + } + if (!need_any) return; - if (networkstatus_check_consensus_signature(pending_consensus, -1) == 1) - return; /* we have a signature from everybody. */ directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL); } +/** Release all storage held by pending consensuses (those waiting for + * signatures). */ +static void +dirvote_clear_pending_consensuses(void) +{ + int i; + for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) { + pending_consensus_t *pc = &pending_consensuses[i]; + tor_free(pc->body); + + networkstatus_vote_free(pc->consensus); + pc->consensus = NULL; + } +} + /** Drop all currently pending votes, consensus, and detached signatures. */ static void dirvote_clear_votes(int all_votes) @@ -1697,12 +2861,8 @@ dirvote_clear_votes(int all_votes) tor_free(cp)); smartlist_clear(pending_consensus_signature_list); } - tor_free(pending_consensus_body); tor_free(pending_consensus_signatures); - if (pending_consensus) { - networkstatus_vote_free(pending_consensus); - pending_consensus = NULL; - } + dirvote_clear_pending_consensuses(); } /** Return a newly allocated string containing the hex-encoded v3 authority @@ -1760,7 +2920,13 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) } tor_assert(smartlist_len(vote->voters) == 1); vi = get_voter(vote); - tor_assert(vi->good_signature == 1); + { + int any_sig_good = 0; + SMARTLIST_FOREACH(vi->sigs, document_signature_t *, sig, + if (sig->good_signature) + any_sig_good = 1); + tor_assert(any_sig_good); + } ds = trusteddirserver_get_by_v3_auth_digest(vi->identity_digest); if (!ds) { char *keys = list_v3_auth_ids(); @@ -1797,6 +2963,9 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) goto err; } + /* Fetch any new router descriptors we just learned about */ + update_consensus_router_descriptor_downloads(time(NULL), 1, vote); + /* Now see whether we already have a vote from this authority. */ SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { if (! memcmp(v->vote->cert->cache_info.identity_digest, @@ -1805,7 +2974,8 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) networkstatus_voter_info_t *vi_old = get_voter(v->vote); if (!memcmp(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) { /* Ah, it's the same vote. Not a problem. */ - log_info(LD_DIR, "Discarding a vote we already have."); + log_info(LD_DIR, "Discarding a vote we already have (from %s).", + vi->address); if (*status_out < 200) *status_out = 200; goto discard; @@ -1832,7 +3002,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) goto err; } } - }); + }); pending_vote = tor_malloc_zero(sizeof(pending_vote_t)); pending_vote->vote_body = new_cached_dir(tor_strndup(vote_body, @@ -1856,8 +3026,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) *status_out = 400; discard: - if (vote) - networkstatus_vote_free(vote); + networkstatus_vote_free(vote); if (end_of_vote && !strcmpstart(end_of_vote, "network-status-version ")) { vote_body = end_of_vote; @@ -1884,14 +3053,18 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) * pending_consensus: it won't be ready to be published until we have * everybody else's signatures collected too. (V3 Authority only) */ static int -dirvote_compute_consensus(void) +dirvote_compute_consensuses(void) { /* Have we got enough votes to try? */ - int n_votes, n_voters; + int n_votes, n_voters, n_vote_running = 0; smartlist_t *votes = NULL, *votestrings = NULL; char *consensus_body = NULL, *signatures = NULL, *votefile; networkstatus_t *consensus = NULL; authority_cert_t *my_cert; + pending_consensus_t pending[N_CONSENSUS_FLAVORS]; + int flav; + + memset(pending, 0, sizeof(pending)); if (!pending_vote_list) pending_vote_list = smartlist_create(); @@ -1903,6 +3076,19 @@ dirvote_compute_consensus(void) "%d of %d", n_votes, n_voters/2); goto err; } + tor_assert(pending_vote_list); + SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { + if (smartlist_string_isin(v->vote->known_flags, "Running")) + n_vote_running++; + }); + if (!n_vote_running) { + /* See task 1066. */ + log_warn(LD_DIR, "Nobody has voted on the Running flag. Generating " + "and publishing a consensus without Running nodes " + "would make many clients stop working. Not " + "generating a consensus!"); + goto err; + } if (!(my_cert = get_my_v3_authority_cert())) { log_warn(LD_DIR, "Can't generate consensus without a certificate."); @@ -1931,6 +3117,7 @@ dirvote_compute_consensus(void) char legacy_dbuf[DIGEST_LEN]; crypto_pk_env_t *legacy_sign=NULL; char *legacy_id_digest = NULL; + int n_generated = 0; if (get_options()->V3AuthUseLegacyKey) { authority_cert_t *cert = get_my_v3_legacy_cert(); legacy_sign = get_my_v3_legacy_signing_key(); @@ -1939,39 +3126,58 @@ dirvote_compute_consensus(void) legacy_id_digest = legacy_dbuf; } } - consensus_body = networkstatus_compute_consensus( + + for (flav = 0; flav < N_CONSENSUS_FLAVORS; ++flav) { + const char *flavor_name = networkstatus_get_flavor_name(flav); + consensus_body = networkstatus_compute_consensus( votes, n_voters, my_cert->identity_key, - get_my_v3_authority_signing_key(), legacy_id_digest, legacy_sign); - } - if (!consensus_body) { - log_warn(LD_DIR, "Couldn't generate a consensus at all!"); - goto err; - } - consensus = networkstatus_parse_vote_from_string(consensus_body, NULL, - NS_TYPE_CONSENSUS); - if (!consensus) { - log_warn(LD_DIR, "Couldn't parse consensus we generated!"); - goto err; + get_my_v3_authority_signing_key(), legacy_id_digest, legacy_sign, + flav); + + if (!consensus_body) { + log_warn(LD_DIR, "Couldn't generate a %s consensus at all!", + flavor_name); + continue; + } + consensus = networkstatus_parse_vote_from_string(consensus_body, NULL, + NS_TYPE_CONSENSUS); + if (!consensus) { + log_warn(LD_DIR, "Couldn't parse %s consensus we generated!", + flavor_name); + tor_free(consensus_body); + continue; + } + + /* 'Check' our own signature, to mark it valid. */ + networkstatus_check_consensus_signature(consensus, -1); + + pending[flav].body = consensus_body; + pending[flav].consensus = consensus; + n_generated++; + consensus_body = NULL; + consensus = NULL; + } + if (!n_generated) { + log_warn(LD_DIR, "Couldn't generate any consensus flavors at all."); + goto err; + } } - /* 'Check' our own signature, to mark it valid. */ - networkstatus_check_consensus_signature(consensus, -1); - signatures = networkstatus_get_detached_signatures(consensus); + signatures = get_detached_signatures_from_pending_consensuses( + pending, N_CONSENSUS_FLAVORS); + if (!signatures) { log_warn(LD_DIR, "Couldn't extract signatures."); goto err; } - tor_free(pending_consensus_body); - pending_consensus_body = consensus_body; + dirvote_clear_pending_consensuses(); + memcpy(pending_consensuses, pending, sizeof(pending)); + tor_free(pending_consensus_signatures); pending_consensus_signatures = signatures; - if (pending_consensus) - networkstatus_vote_free(pending_consensus); - pending_consensus = consensus; - if (pending_consensus_signature_list) { int n_sigs = 0; /* we may have gotten signatures for this consensus before we built @@ -1979,7 +3185,7 @@ dirvote_compute_consensus(void) SMARTLIST_FOREACH(pending_consensus_signature_list, char *, sig, { const char *msg = NULL; - int r = dirvote_add_signatures_to_pending_consensus(sig, &msg); + int r = dirvote_add_signatures_to_all_pending_consensuses(sig, &msg); if (r >= 0) n_sigs += r; else @@ -2003,10 +3209,10 @@ dirvote_compute_consensus(void) strlen(pending_consensus_signatures), 0); log_notice(LD_DIR, "Signature(s) posted."); + smartlist_free(votes); return 0; err: - if (votes) - smartlist_free(votes); + smartlist_free(votes); tor_free(consensus_body); tor_free(signatures); networkstatus_vote_free(consensus); @@ -2015,76 +3221,62 @@ dirvote_compute_consensus(void) } /** Helper: we just got the <b>detached_signatures_body</b> sent to us as - * signatures on the currently pending consensus. Add them to the consensus + * signatures on the currently pending consensus. Add them to <b>pc</b> * as appropriate. Return the number of signatures added. (?) */ static int dirvote_add_signatures_to_pending_consensus( - const char *detached_signatures_body, + pending_consensus_t *pc, + ns_detached_signatures_t *sigs, const char **msg_out) { - ns_detached_signatures_t *sigs = NULL; + const char *flavor_name; int r = -1; - tor_assert(detached_signatures_body); - tor_assert(msg_out); - /* Only call if we have a pending consensus right now. */ - tor_assert(pending_consensus); - tor_assert(pending_consensus_body); + tor_assert(pc->consensus); + tor_assert(pc->body); tor_assert(pending_consensus_signatures); + flavor_name = networkstatus_get_flavor_name(pc->consensus->flavor); *msg_out = NULL; - if (!(sigs = networkstatus_parse_detached_signatures( - detached_signatures_body, NULL))) { - *msg_out = "Couldn't parse detached signatures."; - goto err; + { + smartlist_t *sig_list = strmap_get(sigs->signatures, flavor_name); + log_info(LD_DIR, "Have %d signatures for adding to %s consensus.", + sig_list ? smartlist_len(sig_list) : 0, flavor_name); } - - log_info(LD_DIR, "Have %d signatures for adding to consensus.", - smartlist_len(sigs->signatures)); - r = networkstatus_add_detached_signatures(pending_consensus, - sigs, msg_out); + r = networkstatus_add_detached_signatures(pc->consensus, sigs, msg_out); log_info(LD_DIR,"Added %d signatures to consensus.", r); if (r >= 1) { - char *new_detached = - networkstatus_get_detached_signatures(pending_consensus); - const char *src; + char *new_signatures = + networkstatus_format_signatures(pc->consensus, 0); char *dst, *dst_end; size_t new_consensus_len; - if (!new_detached) { + if (!new_signatures) { *msg_out = "No signatures to add"; goto err; } new_consensus_len = - strlen(pending_consensus_body) + strlen(new_detached) + 1; - pending_consensus_body = tor_realloc(pending_consensus_body, - new_consensus_len); - dst_end = pending_consensus_body + new_consensus_len; - dst = strstr(pending_consensus_body, "directory-signature "); + strlen(pc->body) + strlen(new_signatures) + 1; + pc->body = tor_realloc(pc->body, new_consensus_len); + dst_end = pc->body + new_consensus_len; + dst = strstr(pc->body, "directory-signature "); tor_assert(dst); - src = strstr(new_detached, "directory-signature "); - tor_assert(src); - strlcpy(dst, src, dst_end-dst); + strlcpy(dst, new_signatures, dst_end-dst); /* We remove this block once it has failed to crash for a while. But * unless it shows up in profiles, we're probably better leaving it in, * just in case we break detached signature processing at some point. */ { - ns_detached_signatures_t *sigs = - networkstatus_parse_detached_signatures(new_detached, NULL); networkstatus_t *v = networkstatus_parse_vote_from_string( - pending_consensus_body, NULL, + pc->body, NULL, NS_TYPE_CONSENSUS); - tor_assert(sigs); - ns_detached_signatures_free(sigs); tor_assert(v); networkstatus_vote_free(v); } - tor_free(pending_consensus_signatures); - pending_consensus_signatures = new_detached; *msg_out = "Signatures added"; + tor_free(new_signatures); } else if (r == 0) { *msg_out = "Signatures ignored"; } else { @@ -2096,8 +3288,62 @@ dirvote_add_signatures_to_pending_consensus( if (!*msg_out) *msg_out = "Unrecognized error while adding detached signatures."; done: - if (sigs) - ns_detached_signatures_free(sigs); + return r; +} + +static int +dirvote_add_signatures_to_all_pending_consensuses( + const char *detached_signatures_body, + const char **msg_out) +{ + int r=0, i, n_added = 0, errors = 0; + ns_detached_signatures_t *sigs; + tor_assert(detached_signatures_body); + tor_assert(msg_out); + tor_assert(pending_consensus_signatures); + + if (!(sigs = networkstatus_parse_detached_signatures( + detached_signatures_body, NULL))) { + *msg_out = "Couldn't parse detached signatures."; + goto err; + } + + for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) { + int res; + pending_consensus_t *pc = &pending_consensuses[i]; + if (!pc->consensus) + continue; + res = dirvote_add_signatures_to_pending_consensus(pc, sigs, msg_out); + if (res < 0) + errors++; + else + n_added += res; + } + + if (errors && !n_added) { + r = -1; + goto err; + } + + if (n_added && pending_consensuses[FLAV_NS].consensus) { + char *new_detached = + get_detached_signatures_from_pending_consensuses( + pending_consensuses, N_CONSENSUS_FLAVORS); + if (new_detached) { + tor_free(pending_consensus_signatures); + pending_consensus_signatures = new_detached; + } + } + + r = n_added; + goto done; + err: + if (!*msg_out) + *msg_out = "Unrecognized error while adding detached signatures."; + done: + ns_detached_signatures_free(sigs); + /* XXXX NM Check how return is used. We can now have an error *and* + signatures added. */ return r; } @@ -2110,10 +3356,10 @@ dirvote_add_signatures(const char *detached_signatures_body, const char *source, const char **msg) { - if (pending_consensus) { + if (pending_consensuses[FLAV_NS].consensus) { log_notice(LD_DIR, "Got a signature from %s. " "Adding it to the pending consensus.", source); - return dirvote_add_signatures_to_pending_consensus( + return dirvote_add_signatures_to_all_pending_consensuses( detached_signatures_body, msg); } else { log_notice(LD_DIR, "Got a signature from %s. " @@ -2132,17 +3378,25 @@ dirvote_add_signatures(const char *detached_signatures_body, static int dirvote_publish_consensus(void) { - /* Can we actually publish it yet? */ - if (!pending_consensus || - networkstatus_check_consensus_signature(pending_consensus, 1)<0) { - log_warn(LD_DIR, "Not enough info to publish pending consensus"); - return -1; - } + int i; + + /* Now remember all the other consensuses as if we were a directory cache. */ + for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) { + pending_consensus_t *pending = &pending_consensuses[i]; + const char *name; + name = networkstatus_get_flavor_name(i); + tor_assert(name); + if (!pending->consensus || + networkstatus_check_consensus_signature(pending->consensus, 1)<0) { + log_warn(LD_DIR, "Not enough info to publish pending %s consensus",name); + continue; + } - if (networkstatus_set_current_consensus(pending_consensus_body, 0)) - log_warn(LD_DIR, "Error publishing consensus"); - else - log_notice(LD_DIR, "Consensus published."); + if (networkstatus_set_current_consensus(pending->body, name, 0)) + log_warn(LD_DIR, "Error publishing %s consensus", name); + else + log_notice(LD_DIR, "Published %s consensus", name); + } return 0; } @@ -2152,20 +3406,16 @@ void dirvote_free_all(void) { dirvote_clear_votes(1); - /* now empty as a result of clear_pending_votes. */ + /* now empty as a result of dirvote_clear_votes(). */ smartlist_free(pending_vote_list); pending_vote_list = NULL; smartlist_free(previous_vote_list); previous_vote_list = NULL; - tor_free(pending_consensus_body); + dirvote_clear_pending_consensuses(); tor_free(pending_consensus_signatures); - if (pending_consensus) { - networkstatus_vote_free(pending_consensus); - pending_consensus = NULL; - } if (pending_consensus_signature_list) { - /* now empty as a result of clear_pending_votes. */ + /* now empty as a result of dirvote_clear_votes(). */ smartlist_free(pending_consensus_signature_list); pending_consensus_signature_list = NULL; } @@ -2177,13 +3427,14 @@ dirvote_free_all(void) /** Return the body of the consensus that we're currently trying to build. */ const char * -dirvote_get_pending_consensus(void) +dirvote_get_pending_consensus(consensus_flavor_t flav) { - return pending_consensus_body; + tor_assert(((int)flav) >= 0 && flav < N_CONSENSUS_FLAVORS); + return pending_consensuses[flav].body; } /** Return the signatures that we know for the consensus that we're currently - * trying to build */ + * trying to build. */ const char * dirvote_get_pending_detached_signatures(void) { @@ -2229,15 +3480,147 @@ dirvote_get_vote(const char *fp, int flags) } else { if (pending_vote_list && include_pending) { SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, - if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + if (!memcmp(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN)) return pv->vote_body); } if (previous_vote_list && include_previous) { SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv, - if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + if (!memcmp(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN)) return pv->vote_body); } } return NULL; } +/** Construct and return a new microdescriptor from a routerinfo <b>ri</b>. + * + * XXX Right now, there is only one way to generate microdescriptors from + * router descriptors. This may change in future consensus methods. If so, + * we'll need an internal way to remember which method we used, and ask for a + * particular method. + **/ +microdesc_t * +dirvote_create_microdescriptor(const routerinfo_t *ri) +{ + microdesc_t *result = NULL; + char *key = NULL, *summary = NULL, *family = NULL; + char buf[1024]; + size_t keylen; + char *out = buf, *end = buf+sizeof(buf); + + if (crypto_pk_write_public_key_to_string(ri->onion_pkey, &key, &keylen)<0) + goto done; + summary = policy_summarize(ri->exit_policy); + if (ri->declared_family) + family = smartlist_join_strings(ri->declared_family, " ", 0, NULL); + + if (tor_snprintf(out, end-out, "onion-key\n%s", key)<0) + goto done; + out += strlen(out); + if (family) { + if (tor_snprintf(out, end-out, "family %s\n", family)<0) + goto done; + out += strlen(out); + } + if (summary && strcmp(summary, "reject 1-65535")) { + if (tor_snprintf(out, end-out, "p %s\n", summary)<0) + goto done; + out += strlen(out); + } + *out = '\0'; /* Make sure it's nul-terminated. This should be a no-op */ + + { + smartlist_t *lst = microdescs_parse_from_string(buf, out, 0, 1); + if (smartlist_len(lst) != 1) { + log_warn(LD_DIR, "We generated a microdescriptor we couldn't parse."); + SMARTLIST_FOREACH(lst, microdesc_t *, md, microdesc_free(md)); + smartlist_free(lst); + goto done; + } + result = smartlist_get(lst, 0); + smartlist_free(lst); + } + + done: + tor_free(key); + tor_free(summary); + tor_free(family); + return result; +} + +/** Cached space-separated string to hold */ +static char *microdesc_consensus_methods = NULL; + +/** Format the appropriate vote line to describe the microdescriptor <b>md</b> + * in a consensus vote document. Write it into the <b>out_len</b>-byte buffer + * in <b>out</b>. Return -1 on failure and the number of characters written + * on success. */ +ssize_t +dirvote_format_microdesc_vote_line(char *out, size_t out_len, + const microdesc_t *md) +{ + char d64[BASE64_DIGEST256_LEN+1]; + if (!microdesc_consensus_methods) { + microdesc_consensus_methods = + make_consensus_method_list(MIN_METHOD_FOR_MICRODESC, + MAX_SUPPORTED_CONSENSUS_METHOD, + ","); + tor_assert(microdesc_consensus_methods); + } + if (digest256_to_base64(d64, md->digest)<0) + return -1; + + if (tor_snprintf(out, out_len, "m %s sha256=%s\n", + microdesc_consensus_methods, d64)<0) + return -1; + + return strlen(out); +} + +/** If <b>vrs</b> has a hash made for the consensus method <b>method</b> with + * the digest algorithm <b>alg</b>, decode it and copy it into + * <b>digest256_out</b> and return 0. Otherwise return -1. */ +int +vote_routerstatus_find_microdesc_hash(char *digest256_out, + const vote_routerstatus_t *vrs, + int method, + digest_algorithm_t alg) +{ + /* XXXX only returns the sha256 method. */ + const vote_microdesc_hash_t *h; + char mstr[64]; + size_t mlen; + char dstr[64]; + + tor_snprintf(mstr, sizeof(mstr), "%d", method); + mlen = strlen(mstr); + tor_snprintf(dstr, sizeof(dstr), " %s=", + crypto_digest_algorithm_get_name(alg)); + + for (h = vrs->microdesc; h; h = h->next) { + const char *cp = h->microdesc_hash_line; + size_t num_len; + /* cp looks like \d+(,\d+)* (digesttype=val )+ . Let's hunt for mstr in + * the first part. */ + while (1) { + num_len = strspn(cp, "1234567890"); + if (num_len == mlen && !memcmp(mstr, cp, mlen)) { + /* This is the line. */ + char buf[BASE64_DIGEST256_LEN+1]; + /* XXXX ignores extraneous stuff if the digest is too long. This + * seems harmless enough, right? */ + cp = strstr(cp, dstr); + if (!cp) + return -1; + cp += strlen(dstr); + strlcpy(buf, cp, sizeof(buf)); + return digest256_from_base64(digest256_out, buf); + } + if (num_len == 0 || cp[num_len] != ',') + break; + cp += num_len + 1; + } + } + return -1; +} + diff --git a/src/or/dirvote.h b/src/or/dirvote.h new file mode 100644 index 0000000000..e384dc53b3 --- /dev/null +++ b/src/or/dirvote.h @@ -0,0 +1,93 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file dirvote.h + * \brief Header file for dirvote.c. + **/ + +#ifndef _TOR_DIRVOTE_H +#define _TOR_DIRVOTE_H + +/** Lowest allowable value for VoteSeconds. */ +#define MIN_VOTE_SECONDS 20 +/** Lowest allowable value for DistSeconds. */ +#define MIN_DIST_SECONDS 20 +/** Smallest allowable voting interval. */ +#define MIN_VOTE_INTERVAL 300 + +/** Precision multiplier for the Bw weights */ +#define BW_WEIGHT_SCALE 10000 + +void dirvote_free_all(void); + +/* vote manipulation */ +char *networkstatus_compute_consensus(smartlist_t *votes, + int total_authorities, + crypto_pk_env_t *identity_key, + crypto_pk_env_t *signing_key, + const char *legacy_identity_key_digest, + crypto_pk_env_t *legacy_signing_key, + consensus_flavor_t flavor); +int networkstatus_add_detached_signatures(networkstatus_t *target, + ns_detached_signatures_t *sigs, + const char **msg_out); +char *networkstatus_get_detached_signatures(smartlist_t *consensuses); +void ns_detached_signatures_free(ns_detached_signatures_t *s); + +/* cert manipulation */ +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); + +/* invoked on timers and by outside triggers. */ +struct pending_vote_t * dirvote_add_vote(const char *vote_body, + const char **msg_out, + int *status_out); +int dirvote_add_signatures(const char *detached_signatures_body, + const char *source, + const char **msg_out); + +/* Item access */ +const char *dirvote_get_pending_consensus(consensus_flavor_t flav); +const char *dirvote_get_pending_detached_signatures(void); +#define DGV_BY_ID 1 +#define DGV_INCLUDE_PENDING 2 +#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, + routerinfo_t *ri, time_t now, + int naming, int listbadexits, + int listbaddirs); +void router_clear_status_flags(routerinfo_t *ri); +networkstatus_t * +dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, + authority_cert_t *cert); + +microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri); +ssize_t dirvote_format_microdesc_vote_line(char *out, size_t out_len, + const microdesc_t *md); + +int vote_routerstatus_find_microdesc_hash(char *digest256_out, + const vote_routerstatus_t *vrs, + int method, + digest_algorithm_t alg); +document_signature_t *voter_get_sig_by_algorithm( + const networkstatus_voter_info_t *voter, + digest_algorithm_t alg); + +#ifdef DIRVOTE_PRIVATE +char *format_networkstatus_vote(crypto_pk_env_t *private_key, + networkstatus_t *v3_ns); +char *dirvote_compute_params(smartlist_t *votes); +#endif + +#endif + diff --git a/src/or/dns.c b/src/or/dns.c index 98eb27f8b3..4e319b7d83 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -12,8 +12,63 @@ **/ #include "or.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "control.h" +#include "dns.h" +#include "main.h" +#include "policies.h" +#include "relay.h" +#include "router.h" #include "ht.h" +#ifdef HAVE_EVENT2_DNS_H +#include <event2/event.h> +#include <event2/dns.h> +#else +#include <event.h> #include "eventdns.h" +#ifndef HAVE_EVDNS_SET_DEFAULT_OUTGOING_BIND_ADDRESS +#define HAVE_EVDNS_SET_DEFAULT_OUTGOING_BIND_ADDRESS +#endif +#endif + +#ifndef HAVE_EVENT2_DNS_H +struct evdns_base; +struct evdns_request; +#define evdns_base_new(x,y) tor_malloc(1) +#define evdns_base_clear_nameservers_and_suspend(base) \ + evdns_clear_nameservers_and_suspend() +#define evdns_base_search_clear(base) evdns_search_clear() +#define evdns_base_set_default_outgoing_bind_address(base, a, len) \ + evdns_set_default_outgoing_bind_address((a),(len)) +#define evdns_base_resolv_conf_parse(base, options, fname) \ + evdns_resolv_conf_parse((options), (fname)) +#define evdns_base_count_nameservers(base) \ + evdns_count_nameservers() +#define evdns_base_resume(base) \ + evdns_resume() +#define evdns_base_config_windows_nameservers(base) \ + evdns_config_windows_nameservers() +#define evdns_base_set_option_(base, opt, val) \ + evdns_set_option((opt),(val),DNS_OPTIONS_ALL) +#define evdns_base_resolve_ipv4(base, addr, options, cb, ptr) \ + ((evdns_resolve_ipv4(addr, options, cb, ptr)<0) ? NULL : ((void*)1)) +#define evdns_base_resolve_reverse(base, addr, options, cb, ptr) \ + ((evdns_resolve_reverse(addr, options, cb, ptr)<0) ? NULL : ((void*)1)) +#define evdns_base_resolve_reverse_ipv6(base, addr, options, cb, ptr) \ + ((evdns_resolve_reverse_ipv6(addr, options, cb, ptr)<0) ? NULL : ((void*)1)) + +#elif defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER < 0x02000303 +#define evdns_base_set_option_(base, opt, val) \ + evdns_base_set_option((base), (opt),(val),DNS_OPTIONS_ALL) + +#else +#define evdns_base_set_option_ evdns_base_set_option + +#endif /** Longest hostname we're willing to resolve. */ #define MAX_ADDRESSLEN 256 @@ -28,6 +83,9 @@ #define DNS_RESOLVE_FAILED_PERMANENT 2 #define DNS_RESOLVE_SUCCEEDED 3 +/** Our evdns_base; this structure handles all our name lookups. */ +static struct evdns_base *the_evdns_base = NULL; + /** Have we currently configured nameservers with eventdns? */ static int nameservers_configured = 0; /** Did our most recent attempt to configure nameservers with eventdns fail? */ @@ -89,6 +147,8 @@ typedef struct cached_resolve_t { uint32_t ttl; /**< What TTL did the nameserver tell us? */ /** Connections that want to know when we get an answer for this resolve. */ pending_connection_t *pending_connections; + /** Position of this element in the heap*/ + int minheap_idx; } cached_resolve_t; static void purge_expired_resolves(time_t now); @@ -211,8 +271,16 @@ dns_reset(void) { or_options_t *options = get_options(); if (! server_mode(options)) { - evdns_clear_nameservers_and_suspend(); - evdns_search_clear(); + + if (!the_evdns_base) { + if (!(the_evdns_base = evdns_base_new(tor_libevent_get_base(), 0))) { + log_err(LD_BUG, "Couldn't create an evdns_base"); + return -1; + } + } + + evdns_base_clear_nameservers_and_suspend(the_evdns_base); + evdns_base_search_clear(the_evdns_base); nameservers_configured = 0; tor_free(resolv_conf_fname); resolv_conf_mtime = 0; @@ -262,6 +330,8 @@ dns_get_expiry_ttl(uint32_t ttl) static void _free_cached_resolve(cached_resolve_t *r) { + if (!r) + return; while (r->pending_connections) { pending_connection_t *victim = r->pending_connections; r->pending_connections = victim->next; @@ -303,6 +373,7 @@ set_expiry(cached_resolve_t *resolve, time_t expires) resolve->expire = expires; smartlist_pqueue_add(cached_resolve_pqueue, _compare_cached_resolves_by_expiry, + STRUCT_OFFSET(cached_resolve_t, minheap_idx), resolve); } @@ -325,8 +396,7 @@ dns_free_all(void) _free_cached_resolve(item); } HT_CLEAR(cache_map, &cache_root); - if (cached_resolve_pqueue) - smartlist_free(cached_resolve_pqueue); + smartlist_free(cached_resolve_pqueue); cached_resolve_pqueue = NULL; tor_free(resolv_conf_fname); } @@ -349,7 +419,8 @@ purge_expired_resolves(time_t now) if (resolve->expire > now) break; smartlist_pqueue_pop(cached_resolve_pqueue, - _compare_cached_resolves_by_expiry); + _compare_cached_resolves_by_expiry, + STRUCT_OFFSET(cached_resolve_t, minheap_idx)); if (resolve->state == CACHE_STATE_PENDING) { log_debug(LD_EXIT, @@ -393,7 +464,7 @@ purge_expired_resolves(time_t now) log_err(LD_BUG, "The expired resolve we purged didn't match any in" " the cache. Tried to purge %s (%p); instead got %s (%p).", resolve->address, (void*)resolve, - removed ? removed->address : "NULL", (void*)remove); + removed ? removed->address : "NULL", (void*)removed); } tor_assert(removed == resolve); } else { @@ -611,7 +682,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, * know the answer. */ if (tor_addr_from_str(&addr, exitconn->_base.address) >= 0) { if (tor_addr_family(&addr) == AF_INET) { - tor_addr_assign(&exitconn->_base.addr, &addr); + tor_addr_copy(&exitconn->_base.addr, &addr); exitconn->address_ttl = DEFAULT_DNS_TTL; return 1; } else { @@ -711,6 +782,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, resolve = tor_malloc_zero(sizeof(cached_resolve_t)); resolve->magic = CACHED_RESOLVE_MAGIC; resolve->state = CACHE_STATE_PENDING; + resolve->minheap_idx = -1; resolve->is_reverse = is_reverse; strlcpy(resolve->address, exitconn->_base.address, sizeof(resolve->address)); @@ -807,7 +879,8 @@ connection_dns_remove(edge_connection_t *conn) tor_free(pend); log_debug(LD_EXIT, "First connection (fd %d) no longer waiting " "for resolve of %s", - conn->_base.s, escaped_safe_str(conn->_base.address)); + conn->_base.s, + escaped_safe_str(conn->_base.address)); return; } else { for ( ; pend->next; pend = pend->next) { @@ -1108,6 +1181,14 @@ configure_nameservers(int force) conf_fname = "/etc/resolv.conf"; #endif + if (!the_evdns_base) { + if (!(the_evdns_base = evdns_base_new(tor_libevent_get_base(), 0))) { + log_err(LD_BUG, "Couldn't create an evdns_base"); + return -1; + } + } + +#ifdef HAVE_EVDNS_SET_DEFAULT_OUTGOING_BIND_ADDRESS if (options->OutboundBindAddress) { tor_addr_t addr; if (tor_addr_from_str(&addr, options->OutboundBindAddress) < 0) { @@ -1122,16 +1203,13 @@ configure_nameservers(int force) log_warn(LD_BUG, "Couldn't convert outbound bind address to sockaddr." " Ignoring."); } else { - evdns_set_default_outgoing_bind_address((struct sockaddr *)&ss, - socklen); + evdns_base_set_default_outgoing_bind_address(the_evdns_base, + (struct sockaddr *)&ss, + socklen); } } } - - if (options->ServerDNSRandomizeCase) - evdns_set_option("randomize-case:", "1", DNS_OPTIONS_ALL); - else - evdns_set_option("randomize-case:", "0", DNS_OPTIONS_ALL); +#endif evdns_set_log_fn(evdns_log_cb); if (conf_fname) { @@ -1146,16 +1224,17 @@ configure_nameservers(int force) return 0; } if (nameservers_configured) { - evdns_search_clear(); - evdns_clear_nameservers_and_suspend(); + evdns_base_search_clear(the_evdns_base); + evdns_base_clear_nameservers_and_suspend(the_evdns_base); } log_info(LD_EXIT, "Parsing resolver configuration in '%s'", conf_fname); - if ((r = evdns_resolv_conf_parse(DNS_OPTIONS_ALL, conf_fname))) { + if ((r = evdns_base_resolv_conf_parse(the_evdns_base, + DNS_OPTIONS_ALL, conf_fname))) { log_warn(LD_EXIT, "Unable to parse '%s', or no nameservers in '%s' (%d)", conf_fname, conf_fname, r); goto err; } - if (evdns_count_nameservers() == 0) { + if (evdns_base_count_nameservers(the_evdns_base) == 0) { log_warn(LD_EXIT, "Unable to find any nameservers in '%s'.", conf_fname); goto err; } @@ -1163,38 +1242,47 @@ configure_nameservers(int force) resolv_conf_fname = tor_strdup(conf_fname); resolv_conf_mtime = st.st_mtime; if (nameservers_configured) - evdns_resume(); + evdns_base_resume(the_evdns_base); } #ifdef MS_WINDOWS else { if (nameservers_configured) { - evdns_search_clear(); - evdns_clear_nameservers_and_suspend(); + evdns_base_search_clear(the_evdns_base); + evdns_base_clear_nameservers_and_suspend(the_evdns_base); } - if (evdns_config_windows_nameservers()) { + if (evdns_base_config_windows_nameservers(the_evdns_base)) { log_warn(LD_EXIT,"Could not config nameservers."); goto err; } - if (evdns_count_nameservers() == 0) { + if (evdns_base_count_nameservers(the_evdns_base) == 0) { log_warn(LD_EXIT, "Unable to find any platform nameservers in " "your Windows configuration."); goto err; } if (nameservers_configured) - evdns_resume(); + evdns_base_resume(the_evdns_base); tor_free(resolv_conf_fname); resolv_conf_mtime = 0; } #endif - if (evdns_count_nameservers() == 1) { - evdns_set_option("max-timeouts:", "16", DNS_OPTIONS_ALL); - evdns_set_option("timeout:", "10", DNS_OPTIONS_ALL); +#define SET(k,v) evdns_base_set_option_(the_evdns_base, (k), (v)) + + if (evdns_base_count_nameservers(the_evdns_base) == 1) { + SET("max-timeouts:", "16"); + SET("timeout:", "10"); } else { - evdns_set_option("max-timeouts:", "3", DNS_OPTIONS_ALL); - evdns_set_option("timeout:", "5", DNS_OPTIONS_ALL); + SET("max-timeouts:", "3"); + SET("timeout:", "5"); } + if (options->ServerDNSRandomizeCase) + SET("randomize-case:", "1"); + else + SET("randomize-case:", "0"); + +#undef SET + dns_servers_relaunch_checks(); nameservers_configured = 1; @@ -1292,6 +1380,7 @@ static int launch_resolve(edge_connection_t *exitconn) { char *addr = tor_strdup(exitconn->_base.address); + struct evdns_request *req = NULL; tor_addr_t a; int r; int options = get_options()->ServerDNSSearchDomains ? 0 @@ -1307,28 +1396,34 @@ launch_resolve(edge_connection_t *exitconn) r = tor_addr_parse_reverse_lookup_name( &a, exitconn->_base.address, AF_UNSPEC, 0); + + tor_assert(the_evdns_base); if (r == 0) { log_info(LD_EXIT, "Launching eventdns request for %s", escaped_safe_str(exitconn->_base.address)); - r = evdns_resolve_ipv4(exitconn->_base.address, options, - evdns_callback, addr); + req = evdns_base_resolve_ipv4(the_evdns_base, + exitconn->_base.address, options, + evdns_callback, addr); } else if (r == 1) { log_info(LD_EXIT, "Launching eventdns reverse request for %s", escaped_safe_str(exitconn->_base.address)); if (tor_addr_family(&a) == AF_INET) - r = evdns_resolve_reverse(tor_addr_to_in(&a), DNS_QUERY_NO_SEARCH, + req = evdns_base_resolve_reverse(the_evdns_base, + tor_addr_to_in(&a), DNS_QUERY_NO_SEARCH, evdns_callback, addr); else - r = evdns_resolve_reverse_ipv6(tor_addr_to_in6(&a), DNS_QUERY_NO_SEARCH, + req = evdns_base_resolve_reverse_ipv6(the_evdns_base, + tor_addr_to_in6(&a), DNS_QUERY_NO_SEARCH, evdns_callback, addr); } else if (r == -1) { log_warn(LD_BUG, "Somehow a malformed in-addr.arpa address reached here."); } - if (r) { - log_warn(LD_EXIT, "eventdns rejected address %s: error %d.", - escaped_safe_str(addr), r); - r = evdns_err_is_transient(r) ? -2 : -1; + r = 0; + if (!req) { + log_warn(LD_EXIT, "eventdns rejected address %s.", + escaped_safe_str(addr)); + r = -1; tor_free(addr); /* There is no evdns request in progress; stop * addr from getting leaked. */ } @@ -1449,8 +1544,8 @@ evdns_wildcard_check_callback(int result, char type, int count, int ttl, } log(dns_wildcard_one_notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, "Your DNS provider gave an answer for \"%s\", which " - "is not supposed to exist. Apparently they are hijacking " - "DNS failures. Trying to correct for this. We've noticed %d " + "is not supposed to exist. Apparently they are hijacking " + "DNS failures. Trying to correct for this. We've noticed %d " "possibly bad address%s so far.", string_address, strmap_size(dns_wildcard_response_count), (strmap_size(dns_wildcard_response_count) == 1) ? "" : "es"); @@ -1466,17 +1561,20 @@ static void launch_wildcard_check(int min_len, int max_len, const char *suffix) { char *addr; - int r; + struct evdns_request *req; addr = crypto_random_hostname(min_len, max_len, "", suffix); log_info(LD_EXIT, "Testing whether our DNS server is hijacking nonexistent " "domains with request for bogus hostname \"%s\"", addr); - r = evdns_resolve_ipv4(/* This "addr" tells us which address to resolve */ + tor_assert(the_evdns_base); + req = evdns_base_resolve_ipv4( + the_evdns_base, + /* This "addr" tells us which address to resolve */ addr, DNS_QUERY_NO_SEARCH, evdns_wildcard_check_callback, /* This "addr" is an argument to the callback*/ addr); - if (r) { + if (!req) { /* There is no evdns request in progress; stop addr from getting leaked */ tor_free(addr); } @@ -1488,6 +1586,7 @@ static void launch_test_addresses(int fd, short event, void *args) { or_options_t *options = get_options(); + struct evdns_request *req; (void)fd; (void)event; (void)args; @@ -1499,14 +1598,19 @@ launch_test_addresses(int fd, short event, void *args) * be an exit server.*/ if (!options->ServerDNSTestAddresses) return; - SMARTLIST_FOREACH(options->ServerDNSTestAddresses, const char *, address, - { - int r = evdns_resolve_ipv4(address, DNS_QUERY_NO_SEARCH, evdns_callback, - tor_strdup(address)); - if (r) - log_info(LD_EXIT, "eventdns rejected test address %s: error %d", - escaped_safe_str(address), r); - }); + tor_assert(the_evdns_base); + SMARTLIST_FOREACH_BEGIN(options->ServerDNSTestAddresses, + const char *, address) { + char *a = tor_strdup(address); + req = evdns_base_resolve_ipv4(the_evdns_base, + address, DNS_QUERY_NO_SEARCH, evdns_callback, a); + + if (!req) { + log_info(LD_EXIT, "eventdns rejected test address %s", + escaped_safe_str(address)); + tor_free(a); + } + } SMARTLIST_FOREACH_END(address); } #define N_WILDCARD_CHECKS 2 @@ -1547,7 +1651,7 @@ dns_launch_wildcard_checks(void) void dns_launch_correctness_checks(void) { - static struct event launch_event; + static struct event *launch_event = NULL; struct timeval timeout; if (!get_options()->ServerDNSDetectHijacking) return; @@ -1555,10 +1659,12 @@ dns_launch_correctness_checks(void) /* Wait a while before launching requests for test addresses, so we can * get the results from checking for wildcarding. */ - evtimer_set(&launch_event, launch_test_addresses, NULL); + if (! launch_event) + launch_event = tor_evtimer_new(tor_libevent_get_base(), + launch_test_addresses, NULL); timeout.tv_sec = 30; timeout.tv_usec = 0; - if (evtimer_add(&launch_event, &timeout)<0) { + if (evtimer_add(launch_event, &timeout)<0) { log_warn(LD_BUG, "Couldn't add timer for checking for dns hijacking"); } } @@ -1574,10 +1680,9 @@ dns_seems_to_be_broken(void) void dns_reset_correctness_checks(void) { - if (dns_wildcard_response_count) { - strmap_free(dns_wildcard_response_count, _tor_free); - dns_wildcard_response_count = NULL; - } + strmap_free(dns_wildcard_response_count, _tor_free); + dns_wildcard_response_count = NULL; + n_wildcard_requests = 0; if (dns_wildcard_list) { @@ -1622,6 +1727,30 @@ assert_resolve_ok(cached_resolve_t *resolve) } } +/** Return the number of DNS cache entries as an int */ +static int +dns_cache_entry_count(void) +{ + return HT_SIZE(&cache_root); +} + +/** Log memory information about our internal DNS cache at level 'severity'. */ +void +dump_dns_mem_usage(int severity) +{ + /* This should never be larger than INT_MAX. */ + int hash_count = dns_cache_entry_count(); + size_t hash_mem = sizeof(struct cached_resolve_t) * hash_count; + hash_mem += HT_MEM_USAGE(&cache_root); + + /* Print out the count and estimated size of our &cache_root. It undercounts + hostnames in cached reverse resolves. + */ + log(severity, LD_MM, "Our DNS cache has %d entries.", hash_count); + log(severity, LD_MM, "Our DNS cache size is approximately %u bytes.", + (unsigned)hash_mem); +} + #ifdef DEBUG_DNS_CACHE /** Exit with an assertion if the DNS cache is corrupt. */ static void @@ -1642,7 +1771,8 @@ _assert_cache_ok(void) return; smartlist_pqueue_assert_ok(cached_resolve_pqueue, - _compare_cached_resolves_by_expiry); + _compare_cached_resolves_by_expiry, + STRUCT_OFFSET(cached_resolve_t, minheap_idx)); SMARTLIST_FOREACH(cached_resolve_pqueue, cached_resolve_t *, res, { diff --git a/src/or/dns.h b/src/or/dns.h new file mode 100644 index 0000000000..c4fd4d1fb7 --- /dev/null +++ b/src/or/dns.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file dns.h + * \brief Header file for dns.c. + **/ + +#ifndef _TOR_DNS_H +#define _TOR_DNS_H + +int dns_init(void); +int has_dns_init_failed(void); +void dns_free_all(void); +uint32_t dns_clip_ttl(uint32_t ttl); +int dns_reset(void); +void connection_dns_remove(edge_connection_t *conn); +void assert_connection_edge_not_dns_pending(edge_connection_t *conn); +void assert_all_pending_dns_resolves_ok(void); +void dns_cancel_pending_resolve(const char *question); +int dns_resolve(edge_connection_t *exitconn); +void dns_launch_correctness_checks(void); +int dns_seems_to_be_broken(void); +void dns_reset_correctness_checks(void); +void dump_dns_mem_usage(int severity); + +#endif + diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index bceaa462b3..ad4f4122bc 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -9,7 +9,21 @@ **/ #include "or.h" +#include "dnsserv.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "control.h" +#include "main.h" +#include "policies.h" +#ifdef HAVE_EVENT2_DNS_H +#include <event2/dns.h> +#include <event2/dns_compat.h> +/* XXXX022 this implies we want an improved evdns */ +#include <event2/dns_struct.h> +#else #include "eventdns.h" +#endif /** Helper function: called by evdns whenever the client sends a request to our * DNSPort. We need to eventually answer the request <b>req</b>. @@ -85,12 +99,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) evdns_server_request_respond(req, DNS_ERR_NONE); return; } - if (q->type == EVDNS_TYPE_A) { - /* Refuse any attempt to resolve a noconnect address, right now. */ - if (hostname_is_noconnect_address(q->name)) { - err = DNS_ERR_REFUSED; - } - } else { + if (q->type != EVDNS_TYPE_A) { tor_assert(q->type == EVDNS_TYPE_PTR); } @@ -132,17 +141,18 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) control_event_stream_status(conn, STREAM_EVENT_NEW, 0); - /* Now, throw the connection over to get rewritten (which will answer it - * immediately if it's in the cache, or completely bogus, or automapped), - * and then attached to a circuit. */ + /* Now, unless a controller asked us to leave streams unattached, + * throw the connection over to get rewritten (which will + * answer it immediately if it's in the cache, or completely bogus, or + * automapped), and then attached to a circuit. */ log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", - escaped_safe_str(q->name)); + escaped_safe_str_client(q->name)); q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */ - connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); + connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); /* Now, the connection is marked if it was bad. */ - log_info(LD_APP, "Passed request for %s to rewrite_and_attach.", - escaped_safe_str(q_name)); + log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", + escaped_safe_str_client(q_name)); tor_free(q_name); } @@ -177,17 +187,18 @@ dnsserv_launch_request(const char *name, int reverse) return -1; } - /* Now, throw the connection over to get rewritten (which will answer it - * immediately if it's in the cache, or completely bogus, or automapped), - * and then attached to a circuit. */ + /* Now, unless a controller asked us to leave streams unattached, + * throw the connection over to get rewritten (which will + * answer it immediately if it's in the cache, or completely bogus, or + * automapped), and then attached to a circuit. */ log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", - escaped_safe_str(name)); + escaped_safe_str_client(name)); q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */ - connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); + connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); /* Now, the connection is marked if it was bad. */ - log_info(LD_APP, "Passed request for %s to rewrite_and_attach.", - escaped_safe_str(q_name)); + log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", + escaped_safe_str_client(q_name)); tor_free(q_name); return 0; } @@ -297,8 +308,8 @@ dnsserv_configure_listener(connection_t *conn) tor_assert(conn->s >= 0); tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); - conn->dns_server_port = evdns_add_server_port(conn->s, 0, - evdns_server_callback, NULL); + conn->dns_server_port = + tor_evdns_add_server_port(conn->s, 0, evdns_server_callback, NULL); } /** Free the evdns server port for <b>conn</b>, which must be an diff --git a/src/or/dnsserv.h b/src/or/dnsserv.h new file mode 100644 index 0000000000..5bf154ebb2 --- /dev/null +++ b/src/or/dnsserv.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file dnsserv.h + * \brief Header file for dnsserv.c. + **/ + +#ifndef _TOR_DNSSERV_H +#define _TOR_DNSSERV_H + +void dnsserv_configure_listener(connection_t *conn); +void dnsserv_close_listener(connection_t *conn); +void dnsserv_resolved(edge_connection_t *conn, + int answer_type, + size_t answer_len, + const char *answer, + int ttl); +void dnsserv_reject_request(edge_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 a889e803ed..b929303fd5 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -31,6 +31,7 @@ */ #include "eventdns_tor.h" +#include "../common/util.h" #include <sys/types.h> /* #define NDEBUG */ @@ -89,6 +90,7 @@ #include <stdarg.h> #include "eventdns.h" + #ifdef WIN32 #include <windows.h> #include <winsock2.h> @@ -173,8 +175,6 @@ struct evdns_request { /* these objects are kept in a circular list */ struct evdns_request *next, *prev; - u16 timeout_event_deleted; /**< Debugging: where was timeout_event - * deleted? 0 for "it's added." */ struct event timeout_event; u16 trans_id; /* the transaction id */ @@ -214,8 +214,6 @@ struct nameserver { struct event event; /* these objects are kept in a circular list */ struct nameserver *next, *prev; - u16 timeout_event_deleted; /**< Debugging: where was timeout_event - * deleted? 0 for "it's added." */ struct event timeout_event; /* used to keep the timeout for */ /* when we next probe this server. */ /* Valid if state == 0 */ @@ -474,51 +472,10 @@ sockaddr_eq(const struct sockaddr *sa1, const struct sockaddr *sa2, return 1; } -/* for debugging bug 929. XXXX022 */ -static int -_add_timeout_event(u16 *lineno, struct event *ev, struct timeval *to) -{ - *lineno = 0; - return evtimer_add(ev, to); -} -#define add_timeout_event(s, to) \ - (_add_timeout_event(&(s)->timeout_event_deleted, &(s)->timeout_event, (to))) - -/* for debugging bug 929. XXXX022 */ -static int -_del_timeout_event(u16 *lineno, struct event *ev, int line) -{ - if (*lineno) { - log(EVDNS_LOG_DEBUG, - "Duplicate timeout event_del from line %d: first call " - "was at %d.", line, (int)*lineno); - return 0; - } else { - *lineno = (u16)line; - return event_del(ev); - } -} -#define del_timeout_event(s) \ - (_del_timeout_event(&(s)->timeout_event_deleted, &(s)->timeout_event, \ - __LINE__)) -/* For debugging bug 929/957. XXXX022 */ -static int -_del_timeout_event_if_set(u16 *lineno, struct event *ev, int line) -{ - if (*lineno == 0) { - log(EVDNS_LOG_DEBUG, - "Event that I thought was non-added as of line %d " - "was actually added on line %d", - line, (int)*lineno); - *lineno = line; - return event_del(ev); - } - return 0; -} -#define del_timeout_event_if_set(s) \ - _del_timeout_event_if_set(&(s)->timeout_event_deleted, \ - &(s)->timeout_event, \ - __LINE__) +#define add_timeout_event(s, to) \ + (event_add(&(s)->timeout_event, (to))) +#define del_timeout_event(s) \ + (event_del(&(s)->timeout_event)) /* This walks the list of inflight requests to find the */ /* one with a matching transaction id. Returns NULL on */ @@ -555,7 +512,7 @@ static void nameserver_probe_failed(struct nameserver *const ns) { const struct timeval * timeout; del_timeout_event(ns); - CLEAR(&ns->timeout_event); + if (ns->state == 1) { /* This can happen if the nameserver acts in a way which makes us mark */ /* it as bad and then starts sending good replies. */ @@ -567,8 +524,6 @@ nameserver_probe_failed(struct nameserver *const ns) { global_nameserver_timeouts_length - 1)]; ns->failed_times++; - del_timeout_event_if_set(ns); - evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns); if (add_timeout_event(ns, (struct timeval *) timeout) < 0) { log(EVDNS_LOG_WARN, "Error from libevent when adding timer event for %s", @@ -597,8 +552,6 @@ nameserver_failed(struct nameserver *const ns, const char *msg) { ns->state = 0; ns->failed_times = 1; - del_timeout_event_if_set(ns); - evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns); if (add_timeout_event(ns, (struct timeval *) &global_nameserver_timeouts[0]) < 0) { log(EVDNS_LOG_WARN, "Error from libevent when adding timer event for %s", @@ -634,7 +587,6 @@ nameserver_up(struct nameserver *const ns) { log(EVDNS_LOG_WARN, "Nameserver %s is back up", debug_ntop((struct sockaddr *)&ns->address)); del_timeout_event(ns); - CLEAR(&ns->timeout_event); ns->state = 1; ns->failed_times = 0; ns->timedout = 0; @@ -666,7 +618,6 @@ request_finished(struct evdns_request *const req, struct evdns_request **head) { log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx", (unsigned long) req); del_timeout_event(req); - CLEAR(&req->timeout_event); search_request_finished(req); global_requests_inflight--; @@ -1342,8 +1293,8 @@ server_port_read(struct evdns_server_port *s) { static void server_port_flush(struct evdns_server_port *port) { - while (port->pending_replies) { - struct server_request *req = port->pending_replies; + struct server_request *req = port->pending_replies; + while (req) { ssize_t r = sendto(port->socket, req->response, req->response_len, 0, (struct sockaddr*) &req->addr, (socklen_t)req->addrlen); if (r < 0) { @@ -1355,6 +1306,9 @@ server_port_flush(struct evdns_server_port *port) if (server_request_free(req)) { /* we released the last reference to req->port. */ return; + } else { + assert(port->pending_replies != req); + req = port->pending_replies; } } @@ -2046,7 +2000,6 @@ evdns_request_timeout_callback(int fd, short events, void *arg) { * request_finished; that one already deletes the timeout event. * XXXX021 port this change to libevent. */ del_timeout_event(req); - CLEAR(&req->timeout_event); evdns_request_transmit(req); } } @@ -2109,8 +2062,7 @@ evdns_request_transmit(struct evdns_request *req) { /* transmitted; we need to check for timeout. */ log(EVDNS_LOG_DEBUG, "Setting timeout for request %lx", (unsigned long) req); - del_timeout_event_if_set(req); - evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req); + if (add_timeout_event(req, &global_timeout) < 0) { log(EVDNS_LOG_WARN, "Error from libevent when adding timer for request %lx", @@ -2225,7 +2177,6 @@ evdns_clear_nameservers_and_suspend(void) (void) event_del(&server->event); CLEAR(&server->event); del_timeout_event(server); - CLEAR(&server->timeout_event); if (server->socket >= 0) CLOSE_SOCKET(server->socket); CLEAR(server); @@ -2243,7 +2194,6 @@ evdns_clear_nameservers_and_suspend(void) req->ns = NULL; /* ???? What to do about searches? */ del_timeout_event(req); - CLEAR(&req->timeout_event); req->trans_id = 0; req->transmit_me = 0; @@ -2292,6 +2242,21 @@ evdns_resume(void) } static int +sockaddr_is_loopback(const struct sockaddr *addr) +{ + static const char LOOPBACK_S6[16] = + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"; + if (addr->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)addr; + return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; + } else if (addr->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; + return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); + } + return 0; +} + +static int _evdns_nameserver_add_impl(const struct sockaddr *address, socklen_t addrlen) { /* first check to see if we already have this nameserver */ @@ -2318,7 +2283,8 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, if (!ns) return -1; memset(ns, 0, sizeof(struct nameserver)); - ns->timeout_event_deleted = __LINE__; + + evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns); ns->socket = socket(PF_INET, SOCK_DGRAM, 0); if (ns->socket < 0) { err = 1; goto out1; } @@ -2331,7 +2297,8 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, fcntl(ns->socket, F_SETFL, O_NONBLOCK); #endif - if (global_bind_addr_is_set) { + if (global_bind_addr_is_set && + !sockaddr_is_loopback((struct sockaddr*)&global_bind_address)) { if (bind(ns->socket, (struct sockaddr *)&global_bind_address, global_bind_addrlen) < 0) { log(EVDNS_LOG_DEBUG, "Couldn't bind to outgoing address."); @@ -2553,7 +2520,8 @@ request_new(int type, const char *name, int flags, } memset(req, 0, sizeof(struct evdns_request)); - req->timeout_event_deleted = __LINE__; + + evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req); if (global_randomize_case) { unsigned i; @@ -2941,14 +2909,6 @@ evdns_resolv_set_defaults(int flags) { if (flags & DNS_OPTION_NAMESERVERS) evdns_nameserver_ip_add("127.0.0.1"); } -#ifndef HAVE_STRTOK_R -static char * -strtok_r(char *s, const char *delim, char **state) { - (void)state; - return strtok(s, delim); -} -#endif - /* helper version of atoi which returns -1 on error */ static int strtoint(const char *const str) { @@ -3025,9 +2985,9 @@ static void resolv_conf_parse_line(char *const start, int flags) { char *strtok_state; static const char *const delims = " \t"; -#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) +#define NEXT_TOKEN tor_strtok_r(NULL, delims, &strtok_state) - char *const first_token = strtok_r(start, delims, &strtok_state); + char *const first_token = tor_strtok_r(start, delims, &strtok_state); if (!first_token) return; if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) { @@ -3171,14 +3131,13 @@ load_nameservers_with_getnetworkparams(void) IP_ADDR_STRING *ns; GetNetworkParams_fn_t fn; - /* XXXX Possibly, we should hardcode the location of this DLL. */ - if (!(handle = LoadLibrary("iphlpapi.dll"))) { + if (!(handle = load_windows_system_library(TEXT("iphlpapi.dll")))) { log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll"); /* right now status = 0, doesn't that mean "good" - mikec */ status = -1; goto done; } - if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, "GetNetworkParams"))) { + if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, TEXT("GetNetworkParams")))) { log(EVDNS_LOG_WARN, "Could not get address of function."); /* same as above */ status = -1; @@ -3241,9 +3200,10 @@ load_nameservers_with_getnetworkparams(void) } static int -config_nameserver_from_reg_key(HKEY key, const char *subkey) +config_nameserver_from_reg_key(HKEY key, const TCHAR *subkey) { char *buf; + char ansibuf[MAX_PATH] = {0}; DWORD bufsz = 0, type = 0; int status = 0; @@ -3255,24 +3215,30 @@ config_nameserver_from_reg_key(HKEY key, const char *subkey) if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz) == ERROR_SUCCESS && bufsz > 1) { - status = evdns_nameserver_ip_add_line(buf); + wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH);/*XXXX UNICODE */ + status = evdns_nameserver_ip_add_line(ansibuf); } mm_free(buf); return status; } -#define SERVICES_KEY "System\\CurrentControlSet\\Services\\" -#define WIN_NS_9X_KEY SERVICES_KEY "VxD\\MSTCP" -#define WIN_NS_NT_KEY SERVICES_KEY "Tcpip\\Parameters" +#define SERVICES_KEY TEXT("System\\CurrentControlSet\\Services\\") +#define WIN_NS_9X_KEY SERVICES_KEY TEXT("VxD\\MSTCP") +#define WIN_NS_NT_KEY SERVICES_KEY TEXT("Tcpip\\Parameters") static int load_nameservers_from_registry(void) { int found = 0; int r; + OSVERSIONINFO info; + memset(&info, 0, sizeof(info)); + info.dwOSVersionInfoSize = sizeof (info); + GetVersionEx(&info); + #define TRY(k, name) \ - if (!found && config_nameserver_from_reg_key(k,name) == 0) { \ + if (!found && config_nameserver_from_reg_key(k,TEXT(name)) == 0) { \ log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ found = 1; \ } else if (!found) { \ @@ -3280,7 +3246,7 @@ load_nameservers_from_registry(void) #k,#name); \ } - if (((int)GetVersion()) > 0) { /* NT */ + if (info.dwMajorVersion >= 5) { /* NT */ HKEY nt_key = 0, interfaces_key = 0; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, @@ -3288,7 +3254,7 @@ load_nameservers_from_registry(void) log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError()); return -1; } - r = RegOpenKeyEx(nt_key, "Interfaces", 0, + r = RegOpenKeyEx(nt_key, TEXT("Interfaces"), 0, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &interfaces_key); if (r != ERROR_SUCCESS) { @@ -3384,8 +3350,7 @@ evdns_shutdown(int fail_requests) if (server->socket >= 0) CLOSE_SOCKET(server->socket); (void) event_del(&server->event); - if (server->state == 0) - del_timeout_event(server); + del_timeout_event(server); CLEAR(server); mm_free(server); if (server_next == server_head) diff --git a/src/or/geoip.c b/src/or/geoip.c index eb8460e24e..ee8d72ee1d 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -3,15 +3,23 @@ /** * \file geoip.c - * \brief Functions related to maintaining an IP-to-country database and to - * summarizing client connections by country. + * \brief Functions related to maintaining an IP-to-country database; + * to summarizing client connections by country to entry guards, bridges, + * and directory servers; and for statistics on answering network status + * requests. */ #define GEOIP_PRIVATE #include "or.h" #include "ht.h" +#include "config.h" +#include "control.h" +#include "dnsserv.h" +#include "geoip.h" +#include "routerlist.h" static void clear_geoip_db(void); +static void init_geoip_countries(void); /** An entry from the GeoIP file: maps an IP range to a country. */ typedef struct geoip_entry_t { @@ -20,16 +28,11 @@ typedef struct geoip_entry_t { intptr_t country; /**< An index into geoip_countries */ } geoip_entry_t; -/** For how many periods should we remember per-country request history? */ -#define REQUEST_HIST_LEN 3 -/** How long are the periods for which we should remember request history? */ -#define REQUEST_HIST_PERIOD (8*60*60) - /** A per-country record for GeoIP request history. */ typedef struct geoip_country_t { char countrycode[3]; - uint32_t n_v2_ns_requests[REQUEST_HIST_LEN]; - uint32_t n_v3_ns_requests[REQUEST_HIST_LEN]; + uint32_t n_v2_ns_requests; + uint32_t n_v3_ns_requests; } geoip_country_t; /** A list of geoip_country_t */ @@ -42,7 +45,7 @@ static strmap_t *country_idxplus1_by_lc_code = NULL; static smartlist_t *geoip_entries = NULL; /** 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 zero. + * if it is a valid 2-letter country code, otherwise return -1. */ country_t geoip_get_country(const char *country) @@ -101,11 +104,11 @@ geoip_parse_entry(const char *line) { unsigned int low, high; char b[3]; - if (!geoip_countries) { - geoip_countries = smartlist_create(); + if (!geoip_countries) + init_geoip_countries(); + if (!geoip_entries) geoip_entries = smartlist_create(); - country_idxplus1_by_lc_code = strmap_new(); - } + while (TOR_ISSPACE(*line)) ++line; if (*line == '#') @@ -142,6 +145,7 @@ _geoip_compare_entries(const void **_a, const void **_b) static int _geoip_compare_key_to_entry(const void *_key, const void **_member) { + /* No alignment issue here, since _key really is a pointer to uint32_t */ const uint32_t addr = *(uint32_t *)_key; const geoip_entry_t *entry = *_member; if (addr < entry->ip_low) @@ -160,6 +164,24 @@ should_record_bridge_info(or_options_t *options) return options->BridgeRelay && options->BridgeRecordUsageByCountry; } +/** Set up a new list of geoip countries with no countries (yet) set in it, + * except for the unknown country. + */ +static void +init_geoip_countries(void) +{ + geoip_country_t *geoip_unresolved; + geoip_countries = smartlist_create(); + /* Add a geoip_country_t for requests that could not be resolved to a + * country as first element (index 0) to geoip_countries. */ + geoip_unresolved = tor_malloc_zero(sizeof(geoip_country_t)); + strlcpy(geoip_unresolved->countrycode, "??", + sizeof(geoip_unresolved->countrycode)); + smartlist_add(geoip_countries, geoip_unresolved); + country_idxplus1_by_lc_code = strmap_new(); + strmap_set_lc(country_idxplus1_by_lc_code, "??", (void*)(1)); +} + /** Clear the GeoIP database and reload it from the file * <b>filename</b>. Return 0 on success, -1 on failure. * @@ -185,10 +207,8 @@ geoip_load_file(const char *filename, or_options_t *options) filename, msg); return -1; } - if (!geoip_countries) { - geoip_countries = smartlist_create(); - country_idxplus1_by_lc_code = strmap_new(); - } + if (!geoip_countries) + init_geoip_countries(); if (geoip_entries) { SMARTLIST_FOREACH(geoip_entries, geoip_entry_t *, e, tor_free(e)); smartlist_free(geoip_entries); @@ -215,9 +235,10 @@ geoip_load_file(const char *filename, or_options_t *options) } /** Given an IP address in host order, return a number representing the - * country to which that address belongs, or -1 for unknown. The return value - * will always be less than geoip_get_n_countries(). To decode it, - * call geoip_get_country_name(). + * country to which that address belongs, -1 for "No geoip information + * available", or 0 for the 'unknown country'. The return value will always + * be less than geoip_get_n_countries(). To decode it, call + * geoip_get_country_name(). */ int geoip_get_country_by_ip(uint32_t ipaddr) @@ -226,13 +247,15 @@ geoip_get_country_by_ip(uint32_t ipaddr) if (!geoip_entries) return -1; ent = smartlist_bsearch(geoip_entries, &ipaddr, _geoip_compare_key_to_entry); - return ent ? (int)ent->country : -1; + return ent ? (int)ent->country : 0; } /** Return the number of countries recognized by the GeoIP database. */ int geoip_get_n_countries(void) { + if (!geoip_countries) + init_geoip_countries(); return (int) smartlist_len(geoip_countries); } @@ -261,8 +284,8 @@ geoip_is_loaded(void) typedef struct clientmap_entry_t { HT_ENTRY(clientmap_entry_t) node; uint32_t ipaddr; - time_t last_seen; /* The last 2 bits of this value hold the client - * operation. */ + unsigned int last_seen_in_minutes:30; + unsigned int action:2; } clientmap_entry_t; #define ACTION_MASK 3 @@ -270,14 +293,6 @@ typedef struct clientmap_entry_t { /** Map from client IP address to last time seen. */ static HT_HEAD(clientmap, clientmap_entry_t) client_history = HT_INITIALIZER(); -/** Time at which we started tracking client IP history. */ -static time_t client_history_starts = 0; - -/** When did the current period of checking per-country request history - * start? */ -static time_t current_request_period_starts = 0; -/** How many older request periods are we remembering? */ -static int n_old_request_periods = 0; /** Hashtable helper: compute a hash of a clientmap_entry_t. */ static INLINE unsigned @@ -289,7 +304,7 @@ clientmap_entry_hash(const clientmap_entry_t *a) static INLINE int clientmap_entries_eq(const clientmap_entry_t *a, const clientmap_entry_t *b) { - return a->ipaddr == b->ipaddr; + return a->ipaddr == b->ipaddr && a->action == b->action; } HT_PROTOTYPE(clientmap, clientmap_entry_t, node, clientmap_entry_hash, @@ -297,8 +312,87 @@ HT_PROTOTYPE(clientmap, clientmap_entry_t, node, clientmap_entry_hash, HT_GENERATE(clientmap, clientmap_entry_t, node, clientmap_entry_hash, clientmap_entries_eq, 0.6, malloc, realloc, free); +/** Clear history of connecting clients used by entry and bridge stats. */ +static void +client_history_clear(void) +{ + clientmap_entry_t **ent, **next, *this; + for (ent = HT_START(clientmap, &client_history); ent != NULL; + ent = next) { + if ((*ent)->action == GEOIP_CLIENT_CONNECT) { + this = *ent; + next = HT_NEXT_RMV(clientmap, &client_history, ent); + tor_free(this); + } else { + next = HT_NEXT(clientmap, &client_history, ent); + } + } +} + +/** How often do we update our estimate which share of v2 and v3 directory + * requests is sent to us? We could as well trigger updates of shares from + * network status updates, but that means adding a lot of calls into code + * that is independent from geoip stats (and keeping them up-to-date). We + * are perfectly fine with an approximation of 15-minute granularity. */ +#define REQUEST_SHARE_INTERVAL (15 * 60) + +/** When did we last determine which share of v2 and v3 directory requests + * is sent to us? */ +static time_t last_time_determined_shares = 0; + +/** Sum of products of v2 shares times the number of seconds for which we + * consider these shares as valid. */ +static double v2_share_times_seconds; + +/** Sum of products of v3 shares times the number of seconds for which we + * consider these shares as valid. */ +static double v3_share_times_seconds; + +/** Number of seconds we are determining v2 and v3 shares. */ +static int share_seconds; + +/** Try to determine which fraction of v2 and v3 directory requests aimed at + * caches will be sent to us at time <b>now</b> and store that value in + * order to take a mean value later on. */ +static void +geoip_determine_shares(time_t now) +{ + double v2_share = 0.0, v3_share = 0.0; + if (router_get_my_share_of_directory_requests(&v2_share, &v3_share) < 0) + return; + if (last_time_determined_shares) { + v2_share_times_seconds += v2_share * + ((double) (now - last_time_determined_shares)); + v3_share_times_seconds += v3_share * + ((double) (now - last_time_determined_shares)); + share_seconds += (int)(now - last_time_determined_shares); + } + last_time_determined_shares = now; +} + +/** Calculate which fraction of v2 and v3 directory requests aimed at caches + * have been sent to us since the last call of this function up to time + * <b>now</b>. Set *<b>v2_share_out</b> and *<b>v3_share_out</b> to the + * fractions of v2 and v3 protocol shares we expect to have seen. Reset + * counters afterwards. Return 0 on success, -1 on failure (e.g. when zero + * seconds have passed since the last call).*/ +static int +geoip_get_mean_shares(time_t now, double *v2_share_out, + double *v3_share_out) +{ + geoip_determine_shares(now); + if (!share_seconds) + return -1; + *v2_share_out = v2_share_times_seconds / ((double) share_seconds); + *v3_share_out = v3_share_times_seconds / ((double) share_seconds); + v2_share_times_seconds = v3_share_times_seconds = 0.0; + share_seconds = 0; + return 0; +} + /** Note that we've seen a client connect from the IP <b>addr</b> (host order) - * at time <b>now</b>. Ignored by all but bridges. */ + * at time <b>now</b>. Ignored by all but bridges and directories if + * configured accordingly. */ void geoip_note_client_seen(geoip_client_action_t action, uint32_t addr, time_t now) @@ -306,72 +400,45 @@ geoip_note_client_seen(geoip_client_action_t action, or_options_t *options = get_options(); clientmap_entry_t lookup, *ent; if (action == GEOIP_CLIENT_CONNECT) { - if (!(options->BridgeRelay && options->BridgeRecordUsageByCountry)) - return; - /* Did we recently switch from bridge to relay or back? */ - if (client_history_starts > now) + /* Only remember statistics as entry guard or as bridge. */ + if (!options->EntryStatistics && + (!(options->BridgeRelay && options->BridgeRecordUsageByCountry))) return; } else { -#ifndef ENABLE_GEOIP_STATS - return; -#else if (options->BridgeRelay || options->BridgeAuthoritativeDir || - !options->DirRecordUsageByCountry) + !options->DirReqStatistics) return; -#endif } - /* Rotate the current request period. */ - while (current_request_period_starts + REQUEST_HIST_PERIOD < now) { - if (!geoip_countries) - geoip_countries = smartlist_create(); - if (!current_request_period_starts) { - current_request_period_starts = now; - break; - } - SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { - memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1], - sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); - memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1], - sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); - c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0; - c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0; - }); - current_request_period_starts += REQUEST_HIST_PERIOD; - if (n_old_request_periods < REQUEST_HIST_LEN-1) - ++n_old_request_periods; - } - - /* We use the low 3 bits of the time to encode the action. Since we're - * potentially remembering tons of clients, we don't want to make - * clientmap_entry_t larger than it has to be. */ - now = (now & ~ACTION_MASK) | (((int)action) & ACTION_MASK); lookup.ipaddr = addr; + lookup.action = (int)action; ent = HT_FIND(clientmap, &client_history, &lookup); if (ent) { - ent->last_seen = now; + ent->last_seen_in_minutes = now / 60; } else { ent = tor_malloc_zero(sizeof(clientmap_entry_t)); ent->ipaddr = addr; - ent->last_seen = now; + ent->last_seen_in_minutes = now / 60; + ent->action = (int)action; HT_INSERT(clientmap, &client_history, ent); } if (action == GEOIP_CLIENT_NETWORKSTATUS || action == GEOIP_CLIENT_NETWORKSTATUS_V2) { int country_idx = geoip_get_country_by_ip(addr); + if (country_idx < 0) + country_idx = 0; /** unresolved requests are stored at index 0. */ if (country_idx >= 0 && country_idx < smartlist_len(geoip_countries)) { geoip_country_t *country = smartlist_get(geoip_countries, country_idx); if (action == GEOIP_CLIENT_NETWORKSTATUS) - ++country->n_v3_ns_requests[REQUEST_HIST_LEN-1]; + ++country->n_v3_ns_requests; else - ++country->n_v2_ns_requests[REQUEST_HIST_LEN-1]; + ++country->n_v2_ns_requests; } - } - if (!client_history_starts) { - client_history_starts = now; - current_request_period_starts = now; + /* Periodically determine share of requests that we should see */ + if (last_time_determined_shares + REQUEST_SHARE_INTERVAL < now) + geoip_determine_shares(now); } } @@ -380,8 +447,8 @@ geoip_note_client_seen(geoip_client_action_t action, static int _remove_old_client_helper(struct clientmap_entry_t *ent, void *_cutoff) { - time_t cutoff = *(time_t*)_cutoff; - if (ent->last_seen < cutoff) { + time_t cutoff = *(time_t*)_cutoff / 60; + if (ent->last_seen_in_minutes < cutoff) { tor_free(ent); return 1; } else { @@ -389,18 +456,45 @@ _remove_old_client_helper(struct clientmap_entry_t *ent, void *_cutoff) } } -/** Forget about all clients that haven't connected since <b>cutoff</b>. - * If <b>cutoff</b> is in the future, clients won't be added to the history - * until this time is reached. This is useful to prevent relays that switch - * to bridges from reporting unbelievable numbers of clients. */ +/** Forget about all clients that haven't connected since <b>cutoff</b>. */ void geoip_remove_old_clients(time_t cutoff) { clientmap_HT_FOREACH_FN(&client_history, _remove_old_client_helper, &cutoff); - if (client_history_starts < cutoff) - client_history_starts = cutoff; +} + +/** How many responses are we giving to clients requesting v2 network + * statuses? */ +static uint32_t ns_v2_responses[GEOIP_NS_RESPONSE_NUM]; + +/** How many responses are we giving to clients requesting v3 network + * statuses? */ +static uint32_t ns_v3_responses[GEOIP_NS_RESPONSE_NUM]; + +/** Note that we've rejected a client's request for a v2 or v3 network + * status, encoded in <b>action</b> for reason <b>reason</b> at time + * <b>now</b>. */ +void +geoip_note_ns_response(geoip_client_action_t action, + geoip_ns_response_t response) +{ + static int arrays_initialized = 0; + if (!get_options()->DirReqStatistics) + return; + if (!arrays_initialized) { + memset(ns_v2_responses, 0, sizeof(ns_v2_responses)); + memset(ns_v3_responses, 0, sizeof(ns_v3_responses)); + arrays_initialized = 1; + } + tor_assert(action == GEOIP_CLIENT_NETWORKSTATUS || + action == GEOIP_CLIENT_NETWORKSTATUS_V2); + tor_assert(response < GEOIP_NS_RESPONSE_NUM); + if (action == GEOIP_CLIENT_NETWORKSTATUS) + ns_v3_responses[response]++; + else + ns_v2_responses[response]++; } /** Do not mention any country from which fewer than this number of IPs have @@ -414,13 +508,6 @@ geoip_remove_old_clients(time_t cutoff) * multiple of this value. */ #define IP_GRANULARITY 8 -/** Return the time at which we started recording geoip data. */ -time_t -geoip_get_history_start(void) -{ - return client_history_starts; -} - /** Helper type: used to sort per-country totals by value. */ typedef struct c_hist_t { char country[3]; /**< Two-letter country code. */ @@ -442,97 +529,319 @@ _c_hist_compare(const void **_a, const void **_b) return strcmp(a->country, b->country); } -/** How long do we have to have observed per-country request history before we - * are willing to talk about it? */ -#define GEOIP_MIN_OBSERVATION_TIME (12*60*60) +/** When there are incomplete directory requests at the end of a 24-hour + * period, consider those requests running for longer than this timeout as + * failed, the others as still running. */ +#define DIRREQ_TIMEOUT (10*60) -/** Return the lowest x such that x is at least <b>number</b>, and x modulo - * <b>divisor</b> == 0. */ -static INLINE unsigned -round_to_next_multiple_of(unsigned number, unsigned divisor) +/** Entry in a map from either conn->global_identifier for direct requests + * or a unique circuit identifier for tunneled requests to request time, + * response size, and completion time of a network status request. Used to + * measure download times of requests to derive average client + * bandwidths. */ +typedef struct dirreq_map_entry_t { + HT_ENTRY(dirreq_map_entry_t) node; + /** Unique identifier for this network status request; this is either the + * conn->global_identifier of the dir conn (direct request) or a new + * locally unique identifier of a circuit (tunneled request). This ID is + * only unique among other direct or tunneled requests, respectively. */ + uint64_t dirreq_id; + unsigned int state:3; /**< State of this directory request. */ + unsigned int type:1; /**< Is this a direct or a tunneled request? */ + unsigned int completed:1; /**< Is this request complete? */ + unsigned int action:2; /**< Is this a v2 or v3 request? */ + /** When did we receive the request and started sending the response? */ + struct timeval request_time; + size_t response_size; /**< What is the size of the response in bytes? */ + struct timeval completion_time; /**< When did the request succeed? */ +} dirreq_map_entry_t; + +/** Map of all directory requests asking for v2 or v3 network statuses in + * the current geoip-stats interval. Values are + * of type *<b>dirreq_map_entry_t</b>. */ +static HT_HEAD(dirreqmap, dirreq_map_entry_t) dirreq_map = + HT_INITIALIZER(); + +static int +dirreq_map_ent_eq(const dirreq_map_entry_t *a, + const dirreq_map_entry_t *b) { - number += divisor - 1; - number -= number % divisor; - return number; + return a->dirreq_id == b->dirreq_id && a->type == b->type; } -/** Return a newly allocated comma-separated string containing entries for all - * the countries from which we've seen enough clients connect. The entry - * format is cc=num where num is the number of IPs we've seen connecting from - * that country, and cc is a lowercased country code. Returns NULL if we don't - * want to export geoip data yet. */ -char * -geoip_get_client_history(time_t now, geoip_client_action_t action) +static unsigned +dirreq_map_ent_hash(const dirreq_map_entry_t *entry) +{ + unsigned u = (unsigned) entry->dirreq_id; + u += entry->type << 20; + return u; +} + +HT_PROTOTYPE(dirreqmap, dirreq_map_entry_t, node, dirreq_map_ent_hash, + dirreq_map_ent_eq); +HT_GENERATE(dirreqmap, dirreq_map_entry_t, node, dirreq_map_ent_hash, + dirreq_map_ent_eq, 0.6, malloc, realloc, free); + +/** Helper: Put <b>entry</b> into map of directory requests using + * <b>type</b> and <b>dirreq_id</b> as key parts. If there is + * already an entry for that key, print out a BUG warning and return. */ +static void +_dirreq_map_put(dirreq_map_entry_t *entry, dirreq_type_t type, + uint64_t dirreq_id) +{ + dirreq_map_entry_t *old_ent; + tor_assert(entry->type == type); + tor_assert(entry->dirreq_id == dirreq_id); + + /* XXXX022 once we're sure the bug case never happens, we can switch + * to HT_INSERT */ + old_ent = HT_REPLACE(dirreqmap, &dirreq_map, entry); + if (old_ent && old_ent != entry) { + log_warn(LD_BUG, "Error when putting directory request into local " + "map. There was already an entry for the same identifier."); + return; + } +} + +/** Helper: Look up and return an entry in the map of directory requests + * using <b>type</b> and <b>dirreq_id</b> as key parts. If there + * is no such entry, return NULL. */ +static dirreq_map_entry_t * +_dirreq_map_get(dirreq_type_t type, uint64_t dirreq_id) +{ + dirreq_map_entry_t lookup; + lookup.type = type; + lookup.dirreq_id = dirreq_id; + return HT_FIND(dirreqmap, &dirreq_map, &lookup); +} + +/** Note that an either direct or tunneled (see <b>type</b>) directory + * request for a network status with unique ID <b>dirreq_id</b> of size + * <b>response_size</b> and action <b>action</b> (either v2 or v3) has + * started. */ +void +geoip_start_dirreq(uint64_t dirreq_id, size_t response_size, + geoip_client_action_t action, dirreq_type_t type) +{ + dirreq_map_entry_t *ent; + if (!get_options()->DirReqStatistics) + return; + ent = tor_malloc_zero(sizeof(dirreq_map_entry_t)); + ent->dirreq_id = dirreq_id; + tor_gettimeofday(&ent->request_time); + ent->response_size = response_size; + ent->action = action; + ent->type = type; + _dirreq_map_put(ent, type, dirreq_id); +} + +/** Change the state of the either direct or tunneled (see <b>type</b>) + * directory request with <b>dirreq_id</b> to <b>new_state</b> and + * possibly mark it as completed. If no entry can be found for the given + * key parts (e.g., if this is a directory request that we are not + * measuring, or one that was started in the previous measurement period), + * or if the state cannot be advanced to <b>new_state</b>, do nothing. */ +void +geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, + dirreq_state_t new_state) +{ + dirreq_map_entry_t *ent; + if (!get_options()->DirReqStatistics) + return; + ent = _dirreq_map_get(type, dirreq_id); + if (!ent) + return; + if (new_state == DIRREQ_IS_FOR_NETWORK_STATUS) + return; + if (new_state - 1 != ent->state) + return; + ent->state = new_state; + if ((type == DIRREQ_DIRECT && + new_state == DIRREQ_FLUSHING_DIR_CONN_FINISHED) || + (type == DIRREQ_TUNNELED && + new_state == DIRREQ_OR_CONN_BUFFER_FLUSHED)) { + tor_gettimeofday(&ent->completion_time); + ent->completed = 1; + } +} + +/** Return a newly allocated comma-separated string containing statistics + * on network status downloads. The string contains the number of completed + * requests, timeouts, and still running requests as well as the download + * times by deciles and quartiles. Return NULL if we have not observed + * requests for long enough. */ +static char * +geoip_get_dirreq_history(geoip_client_action_t action, + dirreq_type_t type) { char *result = NULL; - if (!geoip_is_loaded()) + smartlist_t *dirreq_completed = NULL; + uint32_t complete = 0, timeouts = 0, running = 0; + int bufsize = 1024, written; + dirreq_map_entry_t **ptr, **next, *ent; + struct timeval now; + + tor_gettimeofday(&now); + if (action != GEOIP_CLIENT_NETWORKSTATUS && + action != GEOIP_CLIENT_NETWORKSTATUS_V2) return NULL; - if (client_history_starts < (now - GEOIP_MIN_OBSERVATION_TIME)) { - char buf[32]; - smartlist_t *chunks = NULL; - smartlist_t *entries = NULL; - int n_countries = geoip_get_n_countries(); - int i; - clientmap_entry_t **ent; - unsigned *counts = tor_malloc_zero(sizeof(unsigned)*n_countries); - unsigned total = 0; - unsigned granularity = IP_GRANULARITY; -#ifdef ENABLE_GEOIP_STATS - if (get_options()->DirRecordUsageByCountry) - granularity = get_options()->DirRecordUsageGranularity; -#endif - HT_FOREACH(ent, clientmap, &client_history) { - int country; - if (((*ent)->last_seen & ACTION_MASK) != (int)action) - continue; - country = geoip_get_country_by_ip((*ent)->ipaddr); - if (country < 0) - continue; - tor_assert(0 <= country && country < n_countries); - ++counts[country]; - ++total; - } - /* Don't record anything if we haven't seen enough IPs. */ - if (total < MIN_IPS_TO_NOTE_ANYTHING) - goto done; - /* Make a list of c_hist_t */ - entries = smartlist_create(); - for (i = 0; i < n_countries; ++i) { - unsigned c = counts[i]; - const char *countrycode; - c_hist_t *ent; - /* Only report a country if it has a minimum number of IPs. */ - if (c >= MIN_IPS_TO_NOTE_COUNTRY) { - c = round_to_next_multiple_of(c, granularity); - countrycode = geoip_get_country_name(i); - ent = tor_malloc(sizeof(c_hist_t)); - strlcpy(ent->country, countrycode, sizeof(ent->country)); - ent->total = c; - smartlist_add(entries, ent); + dirreq_completed = smartlist_create(); + for (ptr = HT_START(dirreqmap, &dirreq_map); ptr; ptr = next) { + ent = *ptr; + if (ent->action != action || ent->type != type) { + next = HT_NEXT(dirreqmap, &dirreq_map, ptr); + continue; + } else { + if (ent->completed) { + smartlist_add(dirreq_completed, ent); + complete++; + next = HT_NEXT_RMV(dirreqmap, &dirreq_map, ptr); + } else { + if (tv_mdiff(&ent->request_time, &now) / 1000 > DIRREQ_TIMEOUT) + timeouts++; + else + running++; + next = HT_NEXT_RMV(dirreqmap, &dirreq_map, ptr); + tor_free(ent); } } - /* Sort entries. Note that we must do this _AFTER_ rounding, or else - * the sort order could leak info. */ - smartlist_sort(entries, _c_hist_compare); - - /* Build the result. */ - chunks = smartlist_create(); - SMARTLIST_FOREACH(entries, c_hist_t *, ch, { - tor_snprintf(buf, sizeof(buf), "%s=%u", ch->country, ch->total); - smartlist_add(chunks, tor_strdup(buf)); - }); - result = smartlist_join_strings(chunks, ",", 0, NULL); - done: - tor_free(counts); - if (chunks) { - SMARTLIST_FOREACH(chunks, char *, c, tor_free(c)); - smartlist_free(chunks); - } - if (entries) { - SMARTLIST_FOREACH(entries, c_hist_t *, c, tor_free(c)); - smartlist_free(entries); + } +#define DIR_REQ_GRANULARITY 4 + complete = round_uint32_to_next_multiple_of(complete, + DIR_REQ_GRANULARITY); + timeouts = round_uint32_to_next_multiple_of(timeouts, + DIR_REQ_GRANULARITY); + running = round_uint32_to_next_multiple_of(running, + DIR_REQ_GRANULARITY); + result = tor_malloc_zero(bufsize); + written = tor_snprintf(result, bufsize, "complete=%u,timeout=%u," + "running=%u", complete, timeouts, running); + if (written < 0) { + tor_free(result); + goto done; + } + +#define MIN_DIR_REQ_RESPONSES 16 + if (complete >= MIN_DIR_REQ_RESPONSES) { + uint32_t *dltimes; + /* We may have rounded 'completed' up. Here we want to use the + * real value. */ + complete = smartlist_len(dirreq_completed); + dltimes = tor_malloc_zero(sizeof(uint32_t) * complete); + SMARTLIST_FOREACH_BEGIN(dirreq_completed, dirreq_map_entry_t *, ent) { + uint32_t bytes_per_second; + uint32_t time_diff = (uint32_t) tv_mdiff(&ent->request_time, + &ent->completion_time); + if (time_diff == 0) + time_diff = 1; /* Avoid DIV/0; "instant" answers are impossible + * by law of nature or something, but a milisecond + * is a bit greater than "instantly" */ + bytes_per_second = (uint32_t)(1000 * ent->response_size / time_diff); + dltimes[ent_sl_idx] = bytes_per_second; + } SMARTLIST_FOREACH_END(ent); + median_uint32(dltimes, complete); /* sorts as a side effect. */ + written = tor_snprintf(result + written, bufsize - written, + ",min=%u,d1=%u,d2=%u,q1=%u,d3=%u,d4=%u,md=%u," + "d6=%u,d7=%u,q3=%u,d8=%u,d9=%u,max=%u", + dltimes[0], + dltimes[1*complete/10-1], + dltimes[2*complete/10-1], + dltimes[1*complete/4-1], + dltimes[3*complete/10-1], + dltimes[4*complete/10-1], + dltimes[5*complete/10-1], + dltimes[6*complete/10-1], + dltimes[7*complete/10-1], + dltimes[3*complete/4-1], + dltimes[8*complete/10-1], + dltimes[9*complete/10-1], + dltimes[complete-1]); + if (written<0) + tor_free(result); + tor_free(dltimes); + } + done: + SMARTLIST_FOREACH(dirreq_completed, dirreq_map_entry_t *, ent, + tor_free(ent)); + smartlist_free(dirreq_completed); + return result; +} + +/** Return a newly allocated comma-separated string containing entries for + * all the countries from which we've seen enough clients connect as a + * bridge, directory server, or entry guard. The entry format is cc=num + * where num is the number of IPs we've seen connecting from that country, + * and cc is a lowercased country code. Returns NULL if we don't want + * to export geoip data yet. */ +char * +geoip_get_client_history(geoip_client_action_t action) +{ + char *result = NULL; + unsigned granularity = IP_GRANULARITY; + smartlist_t *chunks = NULL; + smartlist_t *entries = NULL; + int n_countries = geoip_get_n_countries(); + int i; + clientmap_entry_t **ent; + unsigned *counts = NULL; + unsigned total = 0; + + if (!geoip_is_loaded()) + return NULL; + + counts = tor_malloc_zero(sizeof(unsigned)*n_countries); + HT_FOREACH(ent, clientmap, &client_history) { + int country; + if ((*ent)->action != (int)action) + continue; + country = geoip_get_country_by_ip((*ent)->ipaddr); + if (country < 0) + country = 0; /** unresolved requests are stored at index 0. */ + tor_assert(0 <= country && country < n_countries); + ++counts[country]; + ++total; + } + /* Don't record anything if we haven't seen enough IPs. */ + if (total < MIN_IPS_TO_NOTE_ANYTHING) + goto done; + /* Make a list of c_hist_t */ + entries = smartlist_create(); + for (i = 0; i < n_countries; ++i) { + unsigned c = counts[i]; + const char *countrycode; + c_hist_t *ent; + /* Only report a country if it has a minimum number of IPs. */ + if (c >= MIN_IPS_TO_NOTE_COUNTRY) { + c = round_to_next_multiple_of(c, granularity); + countrycode = geoip_get_country_name(i); + ent = tor_malloc(sizeof(c_hist_t)); + strlcpy(ent->country, countrycode, sizeof(ent->country)); + ent->total = c; + smartlist_add(entries, ent); } } + /* Sort entries. Note that we must do this _AFTER_ rounding, or else + * the sort order could leak info. */ + smartlist_sort(entries, _c_hist_compare); + + /* Build the result. */ + chunks = smartlist_create(); + SMARTLIST_FOREACH(entries, c_hist_t *, ch, { + char *buf=NULL; + tor_asprintf(&buf, "%s=%u", ch->country, ch->total); + smartlist_add(chunks, buf); + }); + result = smartlist_join_strings(chunks, ",", 0, NULL); + done: + tor_free(counts); + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, c, tor_free(c)); + smartlist_free(chunks); + } + if (entries) { + SMARTLIST_FOREACH(entries, c_hist_t *, c, tor_free(c)); + smartlist_free(entries); + } return result; } @@ -540,18 +849,12 @@ geoip_get_client_history(time_t now, geoip_client_action_t action) * for <b>action</b> in a format suitable for an extra-info document, or NULL * on failure. */ char * -geoip_get_request_history(time_t now, geoip_client_action_t action) +geoip_get_request_history(geoip_client_action_t action) { smartlist_t *entries, *strings; char *result; unsigned granularity = IP_GRANULARITY; -#ifdef ENABLE_GEOIP_STATS - if (get_options()->DirRecordUsageByCountry) - granularity = get_options()->DirRecordUsageGranularity; -#endif - if (client_history_starts >= (now - GEOIP_MIN_OBSERVATION_TIME)) - return NULL; if (action != GEOIP_CLIENT_NETWORKSTATUS && action != GEOIP_CLIENT_NETWORKSTATUS_V2) return NULL; @@ -560,13 +863,10 @@ geoip_get_request_history(time_t now, geoip_client_action_t action) entries = smartlist_create(); SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { - uint32_t *n = (action == GEOIP_CLIENT_NETWORKSTATUS) - ? c->n_v3_ns_requests : c->n_v2_ns_requests; uint32_t tot = 0; - int i; c_hist_t *ent; - for (i=0; i < REQUEST_HIST_LEN; ++i) - tot += n[i]; + tot = (action == GEOIP_CLIENT_NETWORKSTATUS) ? + c->n_v3_ns_requests : c->n_v2_ns_requests; if (!tot) continue; ent = tor_malloc_zero(sizeof(c_hist_t)); @@ -578,9 +878,9 @@ geoip_get_request_history(time_t now, geoip_client_action_t action) strings = smartlist_create(); SMARTLIST_FOREACH(entries, c_hist_t *, ent, { - char buf[32]; - tor_snprintf(buf, sizeof(buf), "%s=%u", ent->country, ent->total); - smartlist_add(strings, tor_strdup(buf)); + char *buf = NULL; + tor_asprintf(&buf, "%s=%u", ent->country, ent->total); + smartlist_add(strings, buf); }); result = smartlist_join_strings(strings, ",", 0, NULL); SMARTLIST_FOREACH(strings, char *, cp, tor_free(cp)); @@ -590,69 +890,434 @@ geoip_get_request_history(time_t now, geoip_client_action_t action) return result; } -/** Store all our geoip statistics into $DATADIR/geoip-stats. */ +/** Start time of directory request stats or 0 if we're not collecting + * directory request statistics. */ +static time_t start_of_dirreq_stats_interval; + +/** Initialize directory request stats. */ void -dump_geoip_stats(void) +geoip_dirreq_stats_init(time_t now) { -#ifdef ENABLE_GEOIP_STATS - time_t now = time(NULL); - time_t request_start; - char *filename = get_datadir_fname("geoip-stats"); + 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(). */ +void +geoip_dirreq_stats_term(void) +{ + SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { + c->n_v2_ns_requests = c->n_v3_ns_requests = 0; + }); + { + clientmap_entry_t **ent, **next, *this; + for (ent = HT_START(clientmap, &client_history); ent != NULL; + ent = next) { + if ((*ent)->action == GEOIP_CLIENT_NETWORKSTATUS || + (*ent)->action == GEOIP_CLIENT_NETWORKSTATUS_V2) { + this = *ent; + next = HT_NEXT_RMV(clientmap, &client_history, ent); + tor_free(this); + } else { + next = HT_NEXT(clientmap, &client_history, ent); + } + } + } + v2_share_times_seconds = v3_share_times_seconds = 0.0; + last_time_determined_shares = 0; + share_seconds = 0; + memset(ns_v2_responses, 0, sizeof(ns_v2_responses)); + memset(ns_v3_responses, 0, sizeof(ns_v3_responses)); + { + dirreq_map_entry_t **ent, **next, *this; + for (ent = HT_START(dirreqmap, &dirreq_map); ent != NULL; ent = next) { + this = *ent; + next = HT_NEXT_RMV(dirreqmap, &dirreq_map, ent); + tor_free(this); + } + } + start_of_dirreq_stats_interval = 0; +} + +/** 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) +{ + char *statsdir = NULL, *filename = NULL; char *data_v2 = NULL, *data_v3 = NULL; - char since[ISO_TIME_LEN+1], written[ISO_TIME_LEN+1]; + char written[ISO_TIME_LEN+1]; open_file_t *open_file = NULL; double v2_share = 0.0, v3_share = 0.0; FILE *out; + int i; + + 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); - data_v2 = geoip_get_client_history(now, GEOIP_CLIENT_NETWORKSTATUS_V2); - data_v3 = geoip_get_client_history(now, GEOIP_CLIENT_NETWORKSTATUS); - format_iso_time(since, geoip_get_history_start()); + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 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_REPLACE, + out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, 0600, &open_file); if (!out) goto done; - if (fprintf(out, "written %s\nstarted-at %s\nns-ips %s\nns-v2-ips %s\n", - written, since, + 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); - request_start = current_request_period_starts - - (n_old_request_periods * REQUEST_HIST_PERIOD); - format_iso_time(since, request_start); - data_v2 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS_V2); - data_v3 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS); - if (fprintf(out, "requests-start %s\nn-ns-reqs %s\nn-v2-ns-reqs %s\n", - since, + 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; - if (!router_get_my_share_of_directory_requests(&v2_share, &v3_share)) { - if (fprintf(out, "v2-ns-share %0.2lf%%\n", v2_share*100) < 0) + 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( + ns_v2_responses[i], RESPONSE_GRANULARITY); + ns_v3_responses[i] = round_uint32_to_next_multiple_of( + 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, "v3-ns-share %0.2lf%%\n", v3_share*100) < 0) + if (fprintf(out, "dirreq-v3-share %0.2lf%%\n", v3_share*100) < 0) goto done; } + 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; + finish_writing_to_file(open_file); open_file = NULL; + + start_of_dirreq_stats_interval = 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); -#endif + return start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL; +} + +/** Start time of bridge stats or 0 if we're not collecting bridge + * statistics. */ +static time_t start_of_bridge_stats_interval; + +/** Initialize bridge stats. */ +void +geoip_bridge_stats_init(time_t now) +{ + start_of_bridge_stats_interval = now; +} + +/** Stop collecting bridge stats in a way that we can re-start doing so in + * geoip_bridge_stats_init(). */ +void +geoip_bridge_stats_term(void) +{ + client_history_clear(); + start_of_bridge_stats_interval = 0; +} + +/** Parse the bridge statistics as they are written to extra-info + * descriptors for being returned to controller clients. Return the + * controller string if successful, or NULL otherwise. */ +static char * +parse_bridge_stats_controller(const char *stats_str, time_t now) +{ + char stats_end_str[ISO_TIME_LEN+1], stats_start_str[ISO_TIME_LEN+1], + *controller_str, *eos, *eol, *summary; + + const char *BRIDGE_STATS_END = "bridge-stats-end "; + const char *BRIDGE_IPS = "bridge-ips "; + const char *BRIDGE_IPS_EMPTY_LINE = "bridge-ips\n"; + const char *tmp; + time_t stats_end_time; + int seconds; + tor_assert(stats_str); + + /* Parse timestamp and number of seconds from + "bridge-stats-end YYYY-MM-DD HH:MM:SS (N s)" */ + tmp = find_str_at_start_of_line(stats_str, BRIDGE_STATS_END); + if (!tmp) + return NULL; + tmp += strlen(BRIDGE_STATS_END); + + if (strlen(tmp) < ISO_TIME_LEN + 6) + return NULL; + strlcpy(stats_end_str, tmp, sizeof(stats_end_str)); + if (parse_iso_time(stats_end_str, &stats_end_time) < 0) + return NULL; + if (stats_end_time < now - (25*60*60) || + stats_end_time > now + (1*60*60)) + return NULL; + seconds = (int)strtol(tmp + ISO_TIME_LEN + 2, &eos, 10); + if (!eos || seconds < 23*60*60) + return NULL; + format_iso_time(stats_start_str, stats_end_time - seconds); + + /* Parse: "bridge-ips CC=N,CC=N,..." */ + tmp = find_str_at_start_of_line(stats_str, BRIDGE_IPS); + if (tmp) { + tmp += strlen(BRIDGE_IPS); + tmp = eat_whitespace_no_nl(tmp); + eol = strchr(tmp, '\n'); + if (eol) + summary = tor_strndup(tmp, eol-tmp); + else + summary = tor_strdup(tmp); + } else { + /* Look if there is an empty "bridge-ips" line */ + tmp = find_str_at_start_of_line(stats_str, BRIDGE_IPS_EMPTY_LINE); + if (!tmp) + return NULL; + summary = tor_strdup(""); + } + + tor_asprintf(&controller_str, + "TimeStarted=\"%s\" CountrySummary=%s", + stats_start_str, summary); + tor_free(summary); + return controller_str; +} + +/** Most recent bridge statistics formatted to be written to extra-info + * descriptors. */ +static char *bridge_stats_extrainfo = NULL; + +/** Most recent bridge statistics formatted to be returned to controller + * clients. */ +static char *bridge_stats_controller = NULL; + +/** Write bridge statistics to $DATADIR/stats/bridge-stats and return + * when we should next try to write statistics. */ +time_t +geoip_bridge_stats_write(time_t now) +{ + char *statsdir = NULL, *filename = NULL, *data = NULL, + written[ISO_TIME_LEN+1], *out = NULL, *controller_str; + size_t len; + + /* Check if 24 hours have passed since starting measurements. */ + if (now < start_of_bridge_stats_interval + WRITE_STATS_INTERVAL) + return start_of_bridge_stats_interval + WRITE_STATS_INTERVAL; + + /* Discard all items in the client history that are too old. */ + geoip_remove_old_clients(start_of_bridge_stats_interval); + + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) + goto done; + filename = get_datadir_fname2("stats", "bridge-stats"); + data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + format_iso_time(written, now); + len = strlen("bridge-stats-end (999999 s)\nbridge-ips \n") + + ISO_TIME_LEN + (data ? strlen(data) : 0) + 42; + out = tor_malloc(len); + if (tor_snprintf(out, len, "bridge-stats-end %s (%u s)\nbridge-ips %s\n", + written, (unsigned) (now - start_of_bridge_stats_interval), + data ? data : "") < 0) + goto done; + write_str_to_file(filename, out, 0); + controller_str = parse_bridge_stats_controller(out, now); + if (!controller_str) + goto done; + start_of_bridge_stats_interval = now; + tor_free(bridge_stats_extrainfo); + tor_free(bridge_stats_controller); + bridge_stats_extrainfo = out; + out = NULL; + bridge_stats_controller = controller_str; + control_event_clients_seen(controller_str); + done: + tor_free(filename); + tor_free(statsdir); + tor_free(data); + tor_free(out); + return start_of_bridge_stats_interval + + WRITE_STATS_INTERVAL; +} + +/** Try to load the most recent bridge statistics from disk, unless we + * have finished a measurement interval lately. */ +static void +load_bridge_stats(time_t now) +{ + char *statsdir, *fname=NULL, *contents, *controller_str; + if (bridge_stats_extrainfo) + return; + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) + goto done; + fname = get_datadir_fname2("stats", "bridge-stats"); + contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); + if (contents) { + controller_str = parse_bridge_stats_controller(contents, now); + if (controller_str) { + bridge_stats_extrainfo = contents; + bridge_stats_controller = controller_str; + } else { + tor_free(contents); + } + } + done: + tor_free(fname); + tor_free(statsdir); +} + +/** Return most recent bridge statistics for inclusion in extra-info + * descriptors, or NULL if we don't have recent bridge statistics. */ +const char * +geoip_get_bridge_stats_extrainfo(time_t now) +{ + load_bridge_stats(now); + return bridge_stats_extrainfo; +} + +/** Return most recent bridge statistics to be returned to controller + * clients, or NULL if we don't have recent bridge statistics. */ +const char * +geoip_get_bridge_stats_controller(time_t now) +{ + load_bridge_stats(now); + return bridge_stats_controller; +} + +/** Start time of entry stats or 0 if we're not collecting entry + * statistics. */ +static time_t start_of_entry_stats_interval; + +/** Initialize entry stats. */ +void +geoip_entry_stats_init(time_t now) +{ + 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; +} + +/** Write entry statistics to $DATADIR/stats/entry-stats and return time + * when we would next 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; + + if (!start_of_entry_stats_interval) + return 0; /* Not initialized. */ + if (start_of_entry_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_entry_stats_interval); + + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) + 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, + 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; + + start_of_entry_stats_interval = 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); + return start_of_entry_stats_interval + WRITE_STATS_INTERVAL; } /** Helper used to implement GETINFO ip-to-country/... controller command. */ int getinfo_helper_geoip(control_connection_t *control_conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { (void)control_conn; - if (geoip_is_loaded() && !strcmpstart(question, "ip-to-country/")) { + if (!geoip_is_loaded()) { + *errmsg = "GeoIP data not loaded"; + return -1; + } + if (!strcmpstart(question, "ip-to-country/")) { int c; uint32_t ip; struct in_addr in; @@ -674,8 +1339,8 @@ clear_geoip_db(void) SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, tor_free(c)); smartlist_free(geoip_countries); } - if (country_idxplus1_by_lc_code) - strmap_free(country_idxplus1_by_lc_code, NULL); + + strmap_free(country_idxplus1_by_lc_code, NULL); if (geoip_entries) { SMARTLIST_FOREACH(geoip_entries, geoip_entry_t *, ent, tor_free(ent)); smartlist_free(geoip_entries); @@ -689,13 +1354,24 @@ clear_geoip_db(void) void geoip_free_all(void) { - clientmap_entry_t **ent, **next, *this; - for (ent = HT_START(clientmap, &client_history); ent != NULL; ent = next) { - this = *ent; - next = HT_NEXT_RMV(clientmap, &client_history, ent); - tor_free(this); + { + clientmap_entry_t **ent, **next, *this; + for (ent = HT_START(clientmap, &client_history); ent != NULL; ent = next) { + this = *ent; + next = HT_NEXT_RMV(clientmap, &client_history, ent); + tor_free(this); + } + HT_CLEAR(clientmap, &client_history); + } + { + dirreq_map_entry_t **ent, **next, *this; + for (ent = HT_START(dirreqmap, &dirreq_map); ent != NULL; ent = next) { + this = *ent; + next = HT_NEXT_RMV(dirreqmap, &dirreq_map, ent); + tor_free(this); + } + HT_CLEAR(dirreqmap, &dirreq_map); } - HT_CLEAR(clientmap, &client_history); clear_geoip_db(); } diff --git a/src/or/geoip.h b/src/or/geoip.h new file mode 100644 index 0000000000..68e01deecc --- /dev/null +++ b/src/or/geoip.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file geoip.h + * \brief Header file for geoip.c. + **/ + +#ifndef _TOR_GEOIP_H +#define _TOR_GEOIP_H + +#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 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); +country_t geoip_get_country(const char *countrycode); + +void geoip_note_client_seen(geoip_client_action_t action, + uint32_t addr, time_t now); +void geoip_remove_old_clients(time_t cutoff); + +void geoip_note_ns_response(geoip_client_action_t action, + geoip_ns_response_t response); +char *geoip_get_client_history(geoip_client_action_t action); +char *geoip_get_request_history(geoip_client_action_t action); +int getinfo_helper_geoip(control_connection_t *control_conn, + const char *question, char **answer, + const char **errmsg); +void geoip_free_all(void); + +void geoip_start_dirreq(uint64_t dirreq_id, size_t response_size, + geoip_client_action_t action, dirreq_type_t type); +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); +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_bridge_stats_init(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); +const char *geoip_get_bridge_stats_controller(time_t); + +#endif + diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 5ebe5b1c5a..929c1994c3 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -22,6 +22,12 @@ hibernating, phase 2: */ #include "or.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "hibernate.h" +#include "main.h" +#include "router.h" /** Possible values of hibernate_state */ typedef enum { @@ -89,6 +95,13 @@ static uint64_t n_bytes_read_in_interval = 0; static uint64_t n_bytes_written_in_interval = 0; /** How many seconds have we been running this interval? */ static uint32_t n_seconds_active_in_interval = 0; +/** How many seconds were we active in this interval before we hit our soft + * limit? */ +static int n_seconds_to_hit_soft_limit = 0; +/** When in this interval was the soft limit hit. */ +static time_t soft_limit_hit_at = 0; +/** How many bytes had we read/written when we hit the soft limit? */ +static uint64_t n_bytes_at_soft_limit = 0; /** When did this accounting interval start? */ static time_t interval_start_time = 0; /** When will this accounting interval end? */ @@ -182,6 +195,9 @@ accounting_parse_options(or_options_t *options, int validate_only) case UNIT_DAY: d = 0; break; + /* Coverity dislikes unreachable default cases; some compilers warn on + * switch statements missing a case. Tell Coverity not to worry. */ + /* coverity[dead_error_begin] */ default: tor_assert(0); } @@ -332,29 +348,57 @@ start_of_accounting_period_after(time_t now) return edge_of_accounting_period_containing(now, 1); } +/** Return the length of the accounting period containing the time + * <b>now</b>. */ +static long +length_of_accounting_period_containing(time_t now) +{ + return edge_of_accounting_period_containing(now, 1) - + edge_of_accounting_period_containing(now, 0); +} + /** Initialize the accounting subsystem. */ void configure_accounting(time_t now) { + time_t s_now; /* Try to remember our recorded usage. */ if (!interval_start_time) read_bandwidth_usage(); /* If we fail, we'll leave values at zero, and * reset below.*/ - if (!interval_start_time || - start_of_accounting_period_after(interval_start_time) <= now) { - /* We didn't have recorded usage, or we don't have recorded usage - * for this interval. Start a new interval. */ + + s_now = start_of_accounting_period_containing(now); + + if (!interval_start_time) { + /* We didn't have recorded usage; Start a new interval. */ log_info(LD_ACCT, "Starting new accounting interval."); reset_accounting(now); - } else if (interval_start_time == - start_of_accounting_period_containing(interval_start_time)) { + } else if (s_now == interval_start_time) { log_info(LD_ACCT, "Continuing accounting interval."); /* We are in the interval we thought we were in. Do nothing.*/ interval_end_time = start_of_accounting_period_after(interval_start_time); } else { - log_warn(LD_ACCT, - "Mismatched accounting interval; starting a fresh one."); - reset_accounting(now); + long duration = length_of_accounting_period_containing(now); + double delta = ((double)(s_now - interval_start_time)) / duration; + if (-0.50 <= delta && delta <= 0.50) { + /* The start of the period is now a little later or earlier than we + * remembered. That's fine; we might lose some bytes we could otherwise + * have written, but better to err on the side of obeying people's + * accounting settings. */ + log_info(LD_ACCT, "Accounting interval moved by %.02f%%; " + "that's fine.", delta*100); + interval_end_time = start_of_accounting_period_after(now); + } else if (delta >= 0.99) { + /* This is the regular time-moved-forward case; don't be too noisy + * about it or people will complain */ + log_info(LD_ACCT, "Accounting interval elapsed; starting a new one"); + reset_accounting(now); + } else { + log_warn(LD_ACCT, + "Mismatched accounting interval: moved by %.02f%%. " + "Starting a fresh one.", delta*100); + reset_accounting(now); + } } accounting_set_wakeup_time(); } @@ -365,23 +409,42 @@ configure_accounting(time_t now) static void update_expected_bandwidth(void) { - uint64_t used, expected; - uint64_t max_configured = (get_options()->BandwidthRate * 60); - - if (n_seconds_active_in_interval < 1800) { + uint64_t expected; + or_options_t *options= get_options(); + uint64_t max_configured = (options->RelayBandwidthRate > 0 ? + options->RelayBandwidthRate : + options->BandwidthRate) * 60; + +#define MIN_TIME_FOR_MEASUREMENT (1800) + + if (soft_limit_hit_at > interval_start_time && n_bytes_at_soft_limit && + (soft_limit_hit_at - interval_start_time) > MIN_TIME_FOR_MEASUREMENT) { + /* If we hit our soft limit last time, only count the bytes up to that + * time. This is a better predictor of our actual bandwidth than + * considering the entirety of the last interval, since we likely started + * using bytes very slowly once we hit our soft limit. */ + expected = n_bytes_at_soft_limit / + (soft_limit_hit_at - interval_start_time); + expected /= 60; + } else if (n_seconds_active_in_interval >= MIN_TIME_FOR_MEASUREMENT) { + /* Otherwise, we either measured enough time in the last interval but + * never hit our soft limit, or we're using a state file from a Tor that + * doesn't know to store soft-limit info. Just take rate at which + * we were reading/writing in the last interval as our expected rate. + */ + uint64_t used = MAX(n_bytes_written_in_interval, + n_bytes_read_in_interval); + expected = used / (n_seconds_active_in_interval / 60); + } else { /* If we haven't gotten enough data last interval, set 'expected' * to 0. This will set our wakeup to the start of the interval. * Next interval, we'll choose our starting time based on how much * we sent this interval. */ expected = 0; - } else { - used = n_bytes_written_in_interval < n_bytes_read_in_interval ? - n_bytes_read_in_interval : n_bytes_written_in_interval; - expected = used / (n_seconds_active_in_interval / 60); - if (expected > max_configured) - expected = max_configured; } + if (expected > max_configured) + expected = max_configured; expected_bandwidth_usage = expected; } @@ -399,6 +462,9 @@ reset_accounting(time_t now) n_bytes_read_in_interval = 0; n_bytes_written_in_interval = 0; n_seconds_active_in_interval = 0; + n_bytes_at_soft_limit = 0; + soft_limit_hit_at = 0; + n_seconds_to_hit_soft_limit = 0; } /** Return true iff we should save our bandwidth usage to disk. */ @@ -449,35 +515,39 @@ accounting_run_housekeeping(time_t now) static void accounting_set_wakeup_time(void) { - char buf[ISO_TIME_LEN+1]; char digest[DIGEST_LEN]; crypto_digest_env_t *d_env; int time_in_interval; uint64_t time_to_exhaust_bw; int time_to_consider; - if (! identity_key_is_set()) { + if (! server_identity_key_is_set()) { if (init_keys() < 0) { log_err(LD_BUG, "Error initializing keys"); tor_assert(0); } } - format_iso_time(buf, interval_start_time); - crypto_pk_get_digest(get_identity_key(), digest); + if (server_identity_key_is_set()) { + char buf[ISO_TIME_LEN+1]; + format_iso_time(buf, interval_start_time); - d_env = crypto_new_digest_env(); - crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); - crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); - crypto_digest_get_digest(d_env, digest, DIGEST_LEN); - crypto_free_digest_env(d_env); + crypto_pk_get_digest(get_server_identity_key(), digest); + + d_env = crypto_new_digest_env(); + crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); + crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); + crypto_digest_get_digest(d_env, digest, DIGEST_LEN); + crypto_free_digest_env(d_env); + } else { + crypto_rand(digest, DIGEST_LEN); + } if (!expected_bandwidth_usage) { char buf1[ISO_TIME_LEN+1]; char buf2[ISO_TIME_LEN+1]; format_local_iso_time(buf1, interval_start_time); format_local_iso_time(buf2, interval_end_time); - time_to_exhaust_bw = GUESS_TIME_TO_USE_BANDWIDTH; interval_wakeup_time = interval_start_time; log_notice(LD_ACCT, @@ -492,8 +562,8 @@ accounting_set_wakeup_time(void) time_to_exhaust_bw = (get_options()->AccountingMax/expected_bandwidth_usage)*60; - if (time_to_exhaust_bw > TIME_MAX) { - time_to_exhaust_bw = TIME_MAX; + if (time_to_exhaust_bw > INT_MAX) { + time_to_exhaust_bw = INT_MAX; time_to_consider = 0; } else { time_to_consider = time_in_interval - (int)time_to_exhaust_bw; @@ -511,8 +581,6 @@ accounting_set_wakeup_time(void) * to be chosen than the last half. */ interval_wakeup_time = interval_start_time + (get_uint32(digest) % time_to_consider); - - format_iso_time(buf, interval_wakeup_time); } { @@ -559,6 +627,10 @@ accounting_record_bandwidth_usage(time_t now, or_state_t *state) state->AccountingSecondsActive = n_seconds_active_in_interval; state->AccountingExpectedUsage = expected_bandwidth_usage; + state->AccountingSecondsToReachSoftLimit = n_seconds_to_hit_soft_limit; + state->AccountingSoftLimitHitAt = soft_limit_hit_at; + state->AccountingBytesAtSoftLimit = n_bytes_at_soft_limit; + or_state_mark_dirty(state, now+(get_options()->AvoidDiskWrites ? 7200 : 60)); @@ -582,10 +654,6 @@ read_bandwidth_usage(void) if (!state) return -1; - /* Okay; it looks like the state file is more up-to-date than the - * bw_accounting file, or the bw_accounting file is nonexistent, - * or the bw_accounting file is corrupt. - */ log_info(LD_ACCT, "Reading bandwidth accounting data from state file"); n_bytes_read_in_interval = state->AccountingBytesReadInInterval; n_bytes_written_in_interval = state->AccountingBytesWrittenInInterval; @@ -593,6 +661,21 @@ read_bandwidth_usage(void) interval_start_time = state->AccountingIntervalStart; expected_bandwidth_usage = state->AccountingExpectedUsage; + /* Older versions of Tor (before 0.2.2.17-alpha or so) didn't generate these + * fields. If you switch back and forth, you might get an + * AccountingSoftLimitHitAt value from long before the most recent + * interval_start_time. If that's so, then ignore the softlimit-related + * values. */ + if (state->AccountingSoftLimitHitAt > interval_start_time) { + soft_limit_hit_at = state->AccountingSoftLimitHitAt; + n_bytes_at_soft_limit = state->AccountingBytesAtSoftLimit; + n_seconds_to_hit_soft_limit = state->AccountingSecondsToReachSoftLimit; + } else { + soft_limit_hit_at = 0; + n_bytes_at_soft_limit = 0; + n_seconds_to_hit_soft_limit = 0; + } + { char tbuf1[ISO_TIME_LEN+1]; char tbuf2[ISO_TIME_LEN+1]; @@ -632,8 +715,27 @@ hibernate_hard_limit_reached(void) static int hibernate_soft_limit_reached(void) { - uint64_t soft_limit = DBL_TO_U64(U64_TO_DBL(get_options()->AccountingMax) - * .95); + const uint64_t acct_max = get_options()->AccountingMax; +#define SOFT_LIM_PCT (.95) +#define SOFT_LIM_BYTES (500*1024*1024) +#define SOFT_LIM_MINUTES (3*60) + /* The 'soft limit' is a fair bit more complicated now than once it was. + * We want to stop accepting connections when ALL of the following are true: + * - We expect to use up the remaining bytes in under 3 hours + * - We have used up 95% of our bytes. + * - We have less than 500MB of bytes left. + */ + uint64_t soft_limit = DBL_TO_U64(U64_TO_DBL(acct_max) * SOFT_LIM_PCT); + if (acct_max > SOFT_LIM_BYTES && acct_max - SOFT_LIM_BYTES > soft_limit) { + soft_limit = acct_max - SOFT_LIM_BYTES; + } + if (expected_bandwidth_usage) { + const uint64_t expected_usage = + expected_bandwidth_usage * SOFT_LIM_MINUTES; + if (acct_max > expected_usage && acct_max - expected_usage > soft_limit) + soft_limit = acct_max - expected_usage; + } + if (!soft_limit) return 0; return n_bytes_read_in_interval >= soft_limit @@ -658,6 +760,14 @@ hibernate_begin(hibernate_state_t new_state, time_t now) exit(0); } + if (new_state == HIBERNATE_STATE_LOWBANDWIDTH && + hibernate_state == HIBERNATE_STATE_LIVE) { + soft_limit_hit_at = now; + n_seconds_to_hit_soft_limit = n_seconds_active_in_interval; + n_bytes_at_soft_limit = MAX(n_bytes_read_in_interval, + n_bytes_written_in_interval); + } + /* 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)) || @@ -860,9 +970,11 @@ consider_hibernation(time_t now) * NULL. */ int getinfo_helper_accounting(control_connection_t *conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { (void) conn; + (void) errmsg; if (!strcmp(question, "accounting/enabled")) { *answer = tor_strdup(accounting_is_enabled(get_options()) ? "1" : "0"); } else if (!strcmp(question, "accounting/hibernating")) { diff --git a/src/or/hibernate.h b/src/or/hibernate.h new file mode 100644 index 0000000000..687fadb669 --- /dev/null +++ b/src/or/hibernate.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file hibernate.h + * \brief Header file for hibernate.c. + **/ + +#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); +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); +int accounting_record_bandwidth_usage(time_t now, or_state_t *state); +void hibernate_begin_shutdown(void); +int we_are_hibernating(void); +void consider_hibernation(time_t now); +int getinfo_helper_accounting(control_connection_t *conn, + const char *question, char **answer, + const char **errmsg); + +#endif + diff --git a/src/or/main.c b/src/or/main.c index af2bf526d4..9bdbbc17a6 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -12,12 +12,50 @@ #define MAIN_PRIVATE #include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "command.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "cpuworker.h" +#include "directory.h" +#include "dirserv.h" +#include "dirvote.h" +#include "dns.h" +#include "dnsserv.h" +#include "geoip.h" +#include "hibernate.h" +#include "main.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "ntmain.h" +#include "onion.h" +#include "policies.h" +#include "relay.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rendservice.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" #ifdef USE_DMALLOC #include <dmalloc.h> #include <openssl/crypto.h> #endif #include "memarea.h" +#ifdef HAVE_EVENT2_EVENT_H +#include <event2/event.h> +#else +#include <event.h> +#endif + void evdns_shutdown(int); /********* PROTOTYPES **********/ @@ -27,7 +65,7 @@ static void dumpstats(int severity); /* log stats */ static void conn_read_callback(int fd, short event, void *_conn); static void conn_write_callback(int fd, short event, void *_conn); static void signal_callback(int fd, short events, void *arg); -static void second_elapsed_callback(int fd, short event, void *args); +static void second_elapsed_callback(periodic_timer_t *timer, void *args); static int conn_close_if_marked(int i); static void connection_start_reading_from_linked_conn(connection_t *conn); static int connection_should_read_from_linked_conn(connection_t *conn); @@ -81,8 +119,12 @@ static smartlist_t *active_linked_connection_lst = NULL; static int called_loop_once = 0; /** We set this to 1 when we've opened a circuit, so we can print a log - * entry to inform the user that Tor is working. */ -int has_completed_circuit=0; + * entry to inform the user that Tor is working. We set it to 0 when + * we think the fact that we once opened a circuit doesn't mean we can do so + * any longer (a big time jump happened, when we notice our directory is + * heinously out-of-date, etc. + */ +int can_complete_circuit=0; /** How often do we check for router descriptors that we should download * when we have too little directory info? */ @@ -127,12 +169,10 @@ connection_add(connection_t *conn) smartlist_add(connection_array, conn); if (conn->s >= 0 || conn->linked) { - conn->read_event = tor_malloc_zero(sizeof(struct event)); - conn->write_event = tor_malloc_zero(sizeof(struct event)); - event_set(conn->read_event, conn->s, EV_READ|EV_PERSIST, - conn_read_callback, conn); - event_set(conn->write_event, conn->s, EV_WRITE|EV_PERSIST, - conn_write_callback, conn); + 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); } log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.", @@ -142,6 +182,25 @@ connection_add(connection_t *conn) return 0; } +/** Tell libevent that we don't care about <b>conn</b> any more. */ +void +connection_unregister_events(connection_t *conn) +{ + if (conn->read_event) { + if (event_del(conn->read_event)) + log_warn(LD_BUG, "Error removing read event for %d", conn->s); + tor_free(conn->read_event); + } + if (conn->write_event) { + if (event_del(conn->write_event)) + log_warn(LD_BUG, "Error removing write event for %d", conn->s); + tor_free(conn->write_event); + } + if (conn->dns_server_port) { + dnsserv_close_listener(conn); + } +} + /** Remove the connection from the global list, and remove the * corresponding poll entry. Calling this function will shift the last * connection (if any) into the position occupied by conn. @@ -246,17 +305,17 @@ get_connection_array(void) } /** Set the event mask on <b>conn</b> to <b>events</b>. (The event - * mask is a bitmask whose bits are EV_READ and EV_WRITE.) + * mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT) */ void -connection_watch_events(connection_t *conn, short events) +connection_watch_events(connection_t *conn, watchable_events_t events) { - if (events & EV_READ) + if (events & READ_EVENT) connection_start_reading(conn); else connection_stop_reading(conn); - if (events & EV_WRITE) + if (events & WRITE_EVENT) connection_start_writing(conn); else connection_stop_writing(conn); @@ -393,11 +452,11 @@ connection_start_reading_from_linked_conn(connection_t *conn) smartlist_add(active_linked_connection_lst, conn); if (!called_loop_once) { /* This is the first event on the list; we won't be in LOOP_ONCE mode, - * so we need to make sure that the event_loop() actually exits at the - * end of its run through the current connections and - * lets us activate read events for linked connections. */ + * so we need to make sure that the event_base_loop() actually exits at + * the end of its run through the current connections and lets us + * activate read events for linked connections. */ struct timeval tv = { 0, 0 }; - event_loopexit(&tv); + tor_event_base_loopexit(tor_libevent_get_base(), &tv); } } else { tor_assert(smartlist_isin(active_linked_connection_lst, conn)); @@ -540,7 +599,7 @@ conn_close_if_marked(int i) log_info(LD_NET, "Conn (addr %s, fd %d, type %s, state %d) marked, but wants " "to flush %d bytes. (Marked at %s:%d)", - escaped_safe_str(conn->address), + escaped_safe_str_client(conn->address), conn->s, conn_type_to_string(conn->type), conn->state, (int)conn->outbuf_flushlen, conn->marked_for_close_file, conn->marked_for_close); @@ -593,8 +652,8 @@ conn_close_if_marked(int i) "something is wrong with theirs. " "(fd %d, type %s, state %d, marked at %s:%d).", (int)buf_datalen(conn->outbuf), - escaped_safe_str(conn->address), conn->s, - conn_type_to_string(conn->type), conn->state, + escaped_safe_str_client(conn->address), + conn->s, conn_type_to_string(conn->type), conn->state, conn->marked_for_close_file, conn->marked_for_close); } @@ -623,7 +682,7 @@ directory_all_unreachable(time_t now) log_notice(LD_NET, "Is your network connection down? " "Failing connection to '%s:%d'.", - safe_str(edge_conn->socks_request->address), + safe_str_client(edge_conn->socks_request->address), edge_conn->socks_request->port); connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_NET_UNREACHABLE); @@ -651,7 +710,7 @@ directory_info_has_arrived(time_t now, int from_cache) /* if we have enough dir info, then update our guard status with * whatever we just learned. */ - entry_guards_compute_status(); + entry_guards_compute_status(options, now); /* Don't even bother trying to get extrainfo until the rest of our * directory info is up-to-date */ if (options->DownloadExtraInfo) @@ -659,7 +718,7 @@ directory_info_has_arrived(time_t now, int from_cache) } if (server_mode(options) && !we_are_hibernating() && !from_cache && - (has_completed_circuit || !any_predicted_circuits(now))) + (can_complete_circuit || !any_predicted_circuits(now))) consider_testing_reachability(1, 1); } @@ -722,6 +781,7 @@ run_connection_housekeeping(int i, time_t now) the connection or send a keepalive, depending. */ or_conn = TO_OR_CONN(conn); + tor_assert(conn->outbuf); 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: @@ -778,7 +838,7 @@ run_connection_housekeeping(int i, time_t now) } } -/** Honor a NEWNYM request: make future requests unlinkability to past +/** Honor a NEWNYM request: make future requests unlinkable to past * requests. */ static void signewnym_impl(time_t now) @@ -804,16 +864,18 @@ run_scheduled_events(time_t now) static time_t time_to_try_getting_descriptors = 0; static time_t time_to_reset_descriptor_failures = 0; static time_t time_to_add_entropy = 0; - static time_t time_to_write_hs_statistics = 0; static time_t time_to_write_bridge_status_file = 0; static time_t time_to_downrate_stability = 0; static time_t time_to_save_stability = 0; static time_t time_to_clean_caches = 0; static time_t time_to_recheck_bandwidth = 0; static time_t time_to_check_for_expired_networkstatus = 0; - static time_t time_to_dump_geoip_stats = 0; + static time_t time_to_write_stats_files = 0; + static time_t time_to_write_bridge_stats = 0; + static int should_init_bridge_stats = 1; static time_t time_to_retry_dns_init = 0; or_options_t *options = get_options(); + int is_server = server_mode(options); int i; int have_dir_info; @@ -835,7 +897,7 @@ run_scheduled_events(time_t now) * shut down and restart all cpuworkers, and update the directory if * necessary. */ - if (server_mode(options) && + if (is_server && get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME < now) { log_info(LD_GENERAL,"Rotating onion key."); rotate_onion_key(); @@ -851,7 +913,7 @@ run_scheduled_events(time_t now) update_router_descriptor_downloads(now); update_extrainfo_downloads(now); if (options->UseBridges) - fetch_bridge_descriptors(now); + fetch_bridge_descriptors(options, now); if (router_have_minimum_dir_info()) time_to_try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL; else @@ -869,7 +931,10 @@ run_scheduled_events(time_t now) last_rotated_x509_certificate = now; if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME < now) { log_info(LD_GENERAL,"Rotating tls context."); - if (tor_tls_context_new(get_identity_key(), MAX_SSL_KEY_LIFETIME) < 0) { + if (tor_tls_context_init(public_server_mode(options), + get_tlsclient_identity_key(), + is_server ? get_server_identity_key() : NULL, + MAX_SSL_KEY_LIFETIME) < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); /* XXX is it a bug here, that we just keep going? -RD */ } @@ -897,7 +962,7 @@ run_scheduled_events(time_t now) if (now % 10 == 0 && (authdir_mode_tests_reachability(options)) && !we_are_hibernating()) { /* try to determine reachability of the other Tor relays */ - dirserv_test_reachability(now, 0); + dirserv_test_reachability(now); } /** 1d. Periodically, we discount older stability information so that new @@ -939,11 +1004,56 @@ run_scheduled_events(time_t now) time_to_check_for_expired_networkstatus = now + CHECK_EXPIRED_NS_INTERVAL; } - if (time_to_dump_geoip_stats < now) { -#define DUMP_GEOIP_STATS_INTERVAL (60*60); - if (time_to_dump_geoip_stats) - dump_geoip_stats(); - time_to_dump_geoip_stats = now + DUMP_GEOIP_STATS_INTERVAL; + /* 1g. Check whether we should write statistics to disk. + */ + if (time_to_write_stats_files < now) { +#define CHECK_WRITE_STATS_INTERVAL (60*60) + time_t next_time_to_write_stats_files = (time_to_write_stats_files > 0 ? + time_to_write_stats_files : now) + CHECK_WRITE_STATS_INTERVAL; + if (options->CellStatistics) { + time_t next_write = + rep_hist_buffer_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->DirReqStatistics) { + time_t next_write = geoip_dirreq_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->EntryStatistics) { + time_t next_write = geoip_entry_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->ExitPortStatistics) { + time_t next_write = rep_hist_exit_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; + } + + /* 1h. Check whether we should write bridge statistics to disk. + */ + if (should_record_bridge_info(options)) { + if (time_to_write_bridge_stats < now) { + if (should_init_bridge_stats) { + /* (Re-)initialize bridge statistics. */ + geoip_bridge_stats_init(now); + time_to_write_bridge_stats = now + WRITE_STATS_INTERVAL; + should_init_bridge_stats = 0; + } else { + /* Possibly write bridge statistics to disk and ask when to write + * them next time. */ + time_to_write_bridge_stats = geoip_bridge_stats_write( + time_to_write_bridge_stats); + } + } + } else if (!should_init_bridge_stats) { + /* Bridge mode was turned off. Ensure that stats are re-initialized + * next time bridge mode is turned on. */ + should_init_bridge_stats = 1; } /* Remove old information from rephist and the rend cache. */ @@ -991,7 +1101,7 @@ run_scheduled_events(time_t now) /* also, check religiously for reachability, if it's within the first * 20 minutes of our uptime. */ if (server_mode(options) && - (has_completed_circuit || !any_predicted_circuits(now)) && + (can_complete_circuit || !any_predicted_circuits(now)) && !we_are_hibernating()) { if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) { consider_testing_reachability(1, dirport_reachability_count==0); @@ -1067,7 +1177,7 @@ run_scheduled_events(time_t now) circuit_expire_old_circuits_serverside(now); /** 5. We do housekeeping for each connection... */ - connection_or_set_bad_connections(); + connection_or_set_bad_connections(NULL, 0); for (i=0;i<smartlist_len(connection_array);i++) { run_connection_housekeeping(i, now); } @@ -1090,7 +1200,7 @@ run_scheduled_events(time_t now) circuit_close_all_marked(); /** 7. And upload service descriptors if necessary. */ - if (has_completed_circuit && !we_are_hibernating()) { + if (can_complete_circuit && !we_are_hibernating()) { rend_consider_services_upload(now); rend_consider_descriptor_republication(); } @@ -1107,7 +1217,7 @@ run_scheduled_events(time_t now) /** 9. and if we're a server, check whether our DNS is telling stories to * us. */ - if (server_mode(options) && time_to_check_for_correct_dns < now) { + if (is_server && 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 { @@ -1117,12 +1227,6 @@ run_scheduled_events(time_t now) } } - /** 10. write hidden service usage statistic to disk */ - if (options->HSAuthorityRecordStats && time_to_write_hs_statistics < now) { - hs_usage_write_statistics_to_file(now); -#define WRITE_HSUSAGE_INTERVAL (30*60) - time_to_write_hs_statistics = now+WRITE_HSUSAGE_INTERVAL; - } /** 10b. write bridge networkstatus file to disk */ if (options->BridgeAuthoritativeDir && time_to_write_bridge_status_file < now) { @@ -1132,39 +1236,30 @@ run_scheduled_events(time_t now) } } -/** Libevent timer: used to invoke second_elapsed_callback() once per - * second. */ -static struct event *timeout_event = NULL; +/** Timer: used to invoke second_elapsed_callback() once per second. */ +static periodic_timer_t *second_timer = NULL; /** Number of libevent errors in the last second: we die if we get too many. */ static int n_libevent_errors = 0; /** Libevent callback: invoked once every second. */ static void -second_elapsed_callback(int fd, short event, void *args) +second_elapsed_callback(periodic_timer_t *timer, void *arg) { /* XXXX This could be sensibly refactored into multiple callbacks, and we * could use Libevent's timers for this rather than checking the current * time against a bunch of timeouts every second. */ - static struct timeval one_second; static time_t current_second = 0; time_t now; size_t bytes_written; size_t bytes_read; int seconds_elapsed; or_options_t *options = get_options(); - (void)fd; - (void)event; - (void)args; - if (!timeout_event) { - timeout_event = tor_malloc_zero(sizeof(struct event)); - evtimer_set(timeout_event, second_elapsed_callback, NULL); - one_second.tv_sec = 1; - one_second.tv_usec = 0; - } + (void)timer; + (void)arg; n_libevent_errors = 0; - /* log_fn(LOG_NOTICE, "Tick."); */ + /* log_notice(LD_GENERAL, "Tick."); */ now = time(NULL); update_approx_time(now); @@ -1187,7 +1282,7 @@ second_elapsed_callback(int fd, short event, void *args) if (server_mode(options) && !we_are_hibernating() && seconds_elapsed > 0 && - has_completed_circuit && + can_complete_circuit && stats_n_seconds_working / TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT != (stats_n_seconds_working+seconds_elapsed) / TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) { @@ -1229,18 +1324,6 @@ second_elapsed_callback(int fd, short event, void *args) run_scheduled_events(now); current_second = now; /* remember which second it is, for next time */ - -#if 0 - if (current_second % 300 == 0) { - rep_history_clean(current_second - options->RephistTrackTime); - dumpmemusage(get_min_log_level()<LOG_INFO ? - get_min_log_level() : LOG_INFO); - } -#endif - - if (evtimer_add(timeout_event, &one_second)) - log_err(LD_NET, - "Error from libevent when setting one-second timeout event"); } #ifndef MS_WINDOWS @@ -1383,7 +1466,7 @@ do_main_loop(void) /* load the private keys, if we're supposed to have them, and set up the * TLS context. */ - if (! identity_key_is_set()) { + if (! client_identity_key_is_set()) { if (init_keys() < 0) { log_err(LD_BUG,"Error initializing keys; exiting"); return -1; @@ -1401,8 +1484,10 @@ do_main_loop(void) /* initialize the bootstrap status events to know we're starting up */ control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0); - if (trusted_dirs_reload_certs()) - return -1; + if (trusted_dirs_reload_certs()) { + log_warn(LD_DIR, + "Couldn't load all cached v3 certificates. Starting anyway."); + } if (router_reload_v2_networkstatus()) { return -1; } @@ -1419,18 +1504,23 @@ do_main_loop(void) now = time(NULL); directory_info_has_arrived(now, 1); - if (authdir_mode_tests_reachability(get_options())) { - /* the directory is already here, run startup things */ - dirserv_test_reachability(now, 1); - } - if (server_mode(get_options())) { /* launch cpuworkers. Need to do this *after* we've read the onion key. */ cpu_init(); } /* set up once-a-second callback. */ - second_elapsed_callback(0,0,NULL); + if (! second_timer) { + struct timeval one_second; + one_second.tv_sec = 1; + one_second.tv_usec = 0; + + second_timer = periodic_timer_new(tor_libevent_get_base(), + &one_second, + second_elapsed_callback, + NULL); + tor_assert(second_timer); + } for (;;) { if (nt_service_is_stopping()) @@ -1449,20 +1539,16 @@ do_main_loop(void) /* poll until we have an event, or the second ends, or until we have * some active linked connections to trigger events for. */ - loop_result = event_loop(called_loop_once ? EVLOOP_ONCE : 0); + loop_result = event_base_loop(tor_libevent_get_base(), + called_loop_once ? EVLOOP_ONCE : 0); /* let catch() handle things like ^c, and otherwise don't worry about it */ if (loop_result < 0) { int e = tor_socket_errno(-1); /* let the program survive things like ^z */ if (e != EINTR && !ERRNO_IS_EINPROGRESS(e)) { -#ifdef HAVE_EVENT_GET_METHOD log_err(LD_NET,"libevent call with %s failed: %s [%d]", - event_get_method(), tor_socket_strerror(e), e); -#else - log_err(LD_NET,"libevent call failed: %s [%d]", - tor_socket_strerror(e), e); -#endif + tor_libevent_get_method(), tor_socket_strerror(e), e); return -1; #ifndef MS_WINDOWS } else if (e == EINVAL) { @@ -1605,6 +1691,7 @@ dumpmemusage(int severity) U64_PRINTF_ARG(rephist_total_alloc), rephist_total_num); dump_routerlist_mem_usage(severity); dump_cell_pool_usage(severity); + dump_dns_mem_usage(severity); buf_dump_freelist_sizes(severity); tor_log_mallinfo(severity); } @@ -1631,7 +1718,8 @@ dumpstats(int severity) if (!connection_is_listener(conn)) { log(severity,LD_GENERAL, "Conn %d is to %s:%d.", i, - safe_str(conn->address), conn->port); + safe_str_client(conn->address), + conn->port); log(severity,LD_GENERAL, "Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)", i, @@ -1728,7 +1816,7 @@ handle_signals(int is_parent) { #ifndef MS_WINDOWS /* do signal stuff only on Unix */ int i; - static int signals[] = { + static const int signals[] = { SIGINT, /* do a controlled slow shutdown */ SIGTERM, /* to terminate now */ SIGPIPE, /* otherwise SIGPIPE kills us */ @@ -1740,12 +1828,13 @@ handle_signals(int is_parent) #endif SIGCHLD, /* handle dns/cpu workers that exit */ -1 }; - static struct event signal_events[16]; /* bigger than it has to be. */ + static struct event *signal_events[16]; /* bigger than it has to be. */ if (is_parent) { for (i = 0; signals[i] >= 0; ++i) { - signal_set(&signal_events[i], signals[i], signal_callback, - (void*)(uintptr_t)signals[i]); - if (signal_add(&signal_events[i], NULL)) + signal_events[i] = tor_evsignal_new( + tor_libevent_get_base(), signals[i], signal_callback, + (void*)(uintptr_t)signals[i]); + if (event_add(signal_events[i], NULL)) log_warn(LD_BUG, "Error from libevent when adding event for signal %d", signals[i]); } @@ -1834,7 +1923,9 @@ tor_init(int argc, char *argv[]) "and you probably shouldn't."); #endif - if (crypto_global_init(get_options()->HardwareAccel)) { + if (crypto_global_init(get_options()->HardwareAccel, + get_options()->AccelName, + get_options()->AccelDir)) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } @@ -1928,7 +2019,6 @@ tor_free_all(int postfork) rend_cache_free_all(); rend_service_authorization_free_all(); rep_hist_free_all(); - hs_usage_free_all(); dns_free_all(); clear_pending_onions(); circuit_free_all(); @@ -1936,6 +2026,7 @@ tor_free_all(int postfork) connection_free_all(); buf_shrink_freelists(1); memarea_clear_freelist(); + microdesc_free_all(); if (!postfork) { config_free_all(); router_free_all(); @@ -1946,13 +2037,11 @@ tor_free_all(int postfork) tor_tls_free_all(); } /* stuff in main.c */ - if (connection_array) - smartlist_free(connection_array); - if (closeable_connection_lst) - smartlist_free(closeable_connection_lst); - if (active_linked_connection_lst) - smartlist_free(active_linked_connection_lst); - tor_free(timeout_event); + + smartlist_free(connection_array); + smartlist_free(closeable_connection_lst); + smartlist_free(active_linked_connection_lst); + periodic_timer_free(second_timer); if (!postfork) { release_lockfile(); } @@ -2013,7 +2102,7 @@ do_list_fingerprint(void) log_err(LD_BUG,"Error initializing keys; can't display fingerprint"); return -1; } - if (!(k = get_identity_key())) { + if (!(k = get_server_identity_key())) { log_err(LD_GENERAL,"Error: missing identity key."); return -1; } @@ -2043,6 +2132,31 @@ do_hash_password(void) printf("16:%s\n",output); } +#if defined (WINCE) +int +find_flashcard_path(PWCHAR path, size_t size) +{ + WIN32_FIND_DATA d = {0}; + HANDLE h = NULL; + + if (!path) + return -1; + + h = FindFirstFlashCard(&d); + if (h == INVALID_HANDLE_VALUE) + return -1; + + if (wcslen(d.cFileName) == 0) { + FindClose(h); + return -1; + } + + wcsncpy(path,d.cFileName,size); + FindClose(h); + return 0; +} +#endif + /** Main entry point for the Tor process. Called from main(). */ /* This function is distinct from main() only so we can link main.c into * the unittest binary without conflicting with the unittests' main. */ @@ -2050,6 +2164,33 @@ int tor_main(int argc, char *argv[]) { int result = 0; +#if defined (WINCE) + WCHAR path [MAX_PATH] = {0}; + WCHAR fullpath [MAX_PATH] = {0}; + PWCHAR p = NULL; + FILE* redir = NULL; + FILE* redirdbg = NULL; + + // this is to facilitate debugging by opening + // a file on a folder shared by the wm emulator. + // if no flashcard (real or emulated) is present, + // log files will be written in the root folder + if (find_flashcard_path(path,MAX_PATH) == -1) + { + redir = _wfreopen( L"\\stdout.log", L"w", stdout ); + redirdbg = _wfreopen( L"\\stderr.log", L"w", stderr ); + } else { + swprintf(fullpath,L"\\%s\\tor",path); + CreateDirectory(fullpath,NULL); + + swprintf(fullpath,L"\\%s\\tor\\stdout.log",path); + redir = _wfreopen( fullpath, L"w", stdout ); + + swprintf(fullpath,L"\\%s\\tor\\stderr.log",path); + redirdbg = _wfreopen( fullpath, L"w", stderr ); + } +#endif + update_approx_time(time(NULL)); tor_threads_init(); init_logging(); diff --git a/src/or/main.h b/src/or/main.h new file mode 100644 index 0000000000..ef38dc9351 --- /dev/null +++ b/src/or/main.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file main.h + * \brief Header file for main.c. + **/ + +#ifndef _TOR_MAIN_H +#define _TOR_MAIN_H + +extern int can_complete_circuit; + +int connection_add(connection_t *conn); +int connection_remove(connection_t *conn); +void connection_unregister_events(connection_t *conn); +int connection_in_array(connection_t *conn); +void add_connection_to_closeable_list(connection_t *conn); +int connection_is_on_closeable_list(connection_t *conn); + +smartlist_t *get_connection_array(void); + +typedef enum watchable_events { + READ_EVENT=0x02, + WRITE_EVENT=0x04 +} watchable_events_t; +void connection_watch_events(connection_t *conn, watchable_events_t events); +int connection_is_reading(connection_t *conn); +void connection_stop_reading(connection_t *conn); +void connection_start_reading(connection_t *conn); + +int connection_is_writing(connection_t *conn); +void connection_stop_writing(connection_t *conn); +void connection_start_writing(connection_t *conn); + +void connection_stop_reading_from_linked_conn(connection_t *conn); + +void directory_all_unreachable(time_t now); +void directory_info_has_arrived(time_t now, int from_cache); + +void ip_address_changed(int at_interface); +void dns_servers_relaunch_checks(void); + +void control_signal_act(int the_signal); +void handle_signals(int is_parent); + +int try_locking(or_options_t *options, int err_if_locked); +int have_lockfile(void); +void release_lockfile(void); + +void tor_cleanup(void); +void tor_free_all(int postfork); + +int tor_main(int argc, char *argv[]); + +#ifdef MAIN_PRIVATE +int do_main_loop(void); +int do_list_fingerprint(void); +void do_hash_password(void); +int tor_init(int argc, char **argv); +#endif + +#endif + diff --git a/src/or/microdesc.c b/src/or/microdesc.c new file mode 100644 index 0000000000..e8f3e7c59f --- /dev/null +++ b/src/or/microdesc.c @@ -0,0 +1,414 @@ +/* Copyright (c) 2009-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "config.h" +#include "microdesc.h" +#include "routerparse.h" + +/** A data structure to hold a bunch of cached microdescriptors. There are + * two active files in the cache: a "cache file" that we mmap, and a "journal + * file" that we append to. Periodically, we rebuild the cache file to hold + * only the microdescriptors that we want to keep */ +struct microdesc_cache_t { + /** Map from sha256-digest to microdesc_t for every microdesc_t in the + * cache. */ + HT_HEAD(microdesc_map, microdesc_t) map; + + /** Name of the cache file. */ + char *cache_fname; + /** Name of the journal file. */ + char *journal_fname; + /** Mmap'd contents of the cache file, or NULL if there is none. */ + tor_mmap_t *cache_content; + /** Number of bytes used in the journal file. */ + size_t journal_len; + + /** Total bytes of microdescriptor bodies we have added to this cache */ + uint64_t total_len_seen; + /** Total number of microdescriptors we have added to this cache */ + unsigned n_seen; +}; + +/** Helper: computes a hash of <b>md</b> to place it in a hash table. */ +static INLINE unsigned int +_microdesc_hash(microdesc_t *md) +{ + unsigned *d = (unsigned*)md->digest; +#if SIZEOF_INT == 4 + return d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7]; +#else + return d[0] ^ d[1] ^ d[2] ^ d[3]; +#endif +} + +/** Helper: compares <b>a</b> and </b> for equality for hash-table purposes. */ +static INLINE int +_microdesc_eq(microdesc_t *a, microdesc_t *b) +{ + return !memcmp(a->digest, b->digest, DIGEST256_LEN); +} + +HT_PROTOTYPE(microdesc_map, microdesc_t, node, + _microdesc_hash, _microdesc_eq); +HT_GENERATE(microdesc_map, microdesc_t, node, + _microdesc_hash, _microdesc_eq, 0.6, + malloc, realloc, free); + +/** Write the body of <b>md</b> into <b>f</b>, with appropriate annotations. + * On success, return the total number of bytes written, and set + * *<b>annotation_len_out</b> to the number of bytes written as + * annotations. */ +static ssize_t +dump_microdescriptor(FILE *f, microdesc_t *md, size_t *annotation_len_out) +{ + ssize_t r = 0; + size_t written; + /* XXXX drops unkown annotations. */ + if (md->last_listed) { + char buf[ISO_TIME_LEN+1]; + char annotation[ISO_TIME_LEN+32]; + format_iso_time(buf, md->last_listed); + tor_snprintf(annotation, sizeof(annotation), "@last-listed %s\n", buf); + fputs(annotation, f); + r += strlen(annotation); + *annotation_len_out = r; + } else { + *annotation_len_out = 0; + } + + md->off = (off_t) ftell(f); + written = fwrite(md->body, 1, md->bodylen, f); + if (written != md->bodylen) { + log_warn(LD_DIR, + "Couldn't dump microdescriptor (wrote %lu out of %lu): %s", + (unsigned long)written, (unsigned long)md->bodylen, + strerror(ferror(f))); + return -1; + } + r += md->bodylen; + return r; +} + +/** Holds a pointer to the current microdesc_cache_t object, or NULL if no + * such object has been allocated. */ +static microdesc_cache_t *the_microdesc_cache = NULL; + +/** Return a pointer to the microdescriptor cache, loading it if necessary. */ +microdesc_cache_t * +get_microdesc_cache(void) +{ + if (PREDICT_UNLIKELY(the_microdesc_cache==NULL)) { + microdesc_cache_t *cache = tor_malloc_zero(sizeof(microdesc_cache_t)); + HT_INIT(microdesc_map, &cache->map); + cache->cache_fname = get_datadir_fname("cached-microdescs"); + cache->journal_fname = get_datadir_fname("cached-microdescs.new"); + microdesc_cache_reload(cache); + the_microdesc_cache = cache; + } + return the_microdesc_cache; +} + +/* There are three sources of microdescriptors: + 1) Generated by us while acting as a directory authority. + 2) Loaded from the cache on disk. + 3) Downloaded. +*/ + +/** Decode the microdescriptors from the string starting at <b>s</b> and + * 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. */ +smartlist_t * +microdescs_add_to_cache(microdesc_cache_t *cache, + const char *s, const char *eos, saved_location_t where, + int no_save) +{ + /*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); + + descriptors = microdescs_parse_from_string(s, eos, + allow_annotations, + copy_body); + + added = microdescs_add_list_to_cache(cache, descriptors, where, no_save); + smartlist_free(descriptors); + return added; +} + +/* 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 + * not add. */ +smartlist_t * +microdescs_add_list_to_cache(microdesc_cache_t *cache, + smartlist_t *descriptors, saved_location_t where, + int no_save) +{ + smartlist_t *added; + open_file_t *open_file = NULL; + FILE *f = NULL; + // int n_added = 0; + ssize_t size = 0; + + if (where == SAVED_NOWHERE && !no_save) { + f = start_writing_to_stdio_file(cache->journal_fname, + OPEN_FLAGS_APPEND|O_BINARY, + 0600, &open_file); + if (!f) { + log_warn(LD_DIR, "Couldn't append to journal in %s: %s", + cache->journal_fname, strerror(errno)); + return NULL; + } + } + + added = smartlist_create(); + SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) { + microdesc_t *md2; + md2 = HT_FIND(microdesc_map, &cache->map, md); + if (md2) { + /* We already had this one. */ + if (md2->last_listed < md->last_listed) + md2->last_listed = md->last_listed; + microdesc_free(md); + continue; + } + + /* Okay, it's a new one. */ + if (f) { + size_t annotation_len; + size = dump_microdescriptor(f, md, &annotation_len); + if (size < 0) { + /* XXX handle errors from dump_microdescriptor() */ + /* log? return -1? die? coredump the universe? */ + continue; + } + md->saved_location = SAVED_IN_JOURNAL; + cache->journal_len += size; + } else { + md->saved_location = where; + } + + md->no_save = no_save; + + HT_INSERT(microdesc_map, &cache->map, md); + smartlist_add(added, md); + ++cache->n_seen; + cache->total_len_seen += md->bodylen; + } SMARTLIST_FOREACH_END(md); + + if (f) + finish_writing_to_file(open_file); /*XXX Check me.*/ + + { + size_t old_content_len = + cache->cache_content ? cache->cache_content->size : 0; + if (cache->journal_len > 16384 + old_content_len && + cache->journal_len > old_content_len * 2) { + microdesc_cache_rebuild(cache); + } + } + + return added; +} + +/** Remove every microdescriptor in <b>cache</b>. */ +void +microdesc_cache_clear(microdesc_cache_t *cache) +{ + microdesc_t **entry, **next; + for (entry = HT_START(microdesc_map, &cache->map); entry; entry = next) { + microdesc_t *md = *entry; + next = HT_NEXT_RMV(microdesc_map, &cache->map, entry); + microdesc_free(md); + } + HT_CLEAR(microdesc_map, &cache->map); + if (cache->cache_content) { + tor_munmap_file(cache->cache_content); + cache->cache_content = NULL; + } + cache->total_len_seen = 0; + cache->n_seen = 0; +} + +/** Reload the contents of <b>cache</b> from disk. If it is empty, load it + * for the first time. Return 0 on success, -1 on failure. */ +int +microdesc_cache_reload(microdesc_cache_t *cache) +{ + struct stat st; + char *journal_content; + smartlist_t *added; + tor_mmap_t *mm; + int total = 0; + + microdesc_cache_clear(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); + if (added) { + total += smartlist_len(added); + smartlist_free(added); + } + } + + journal_content = read_file_to_str(cache->journal_fname, + RFTS_IGNORE_MISSING, &st); + if (journal_content) { + added = microdescs_add_to_cache(cache, journal_content, + journal_content+st.st_size, + SAVED_IN_JOURNAL, 0); + if (added) { + total += smartlist_len(added); + smartlist_free(added); + } + tor_free(journal_content); + } + log_notice(LD_DIR, "Reloaded microdescriptor cache. Found %d descriptors.", + total); + return 0; +} + +/** Regenerate the main cache file for <b>cache</b>, clear the journal file, + * and update every microdesc_t in the cache with pointers to its new + * location. */ +int +microdesc_cache_rebuild(microdesc_cache_t *cache) +{ + open_file_t *open_file; + FILE *f; + microdesc_t **mdp; + smartlist_t *wrote; + ssize_t size; + off_t off = 0; + int orig_size, new_size; + + log_info(LD_DIR, "Rebuilding the microdescriptor cache..."); + orig_size = (int)(cache->cache_content ? cache->cache_content->size : 0); + orig_size += (int)cache->journal_len; + + f = start_writing_to_stdio_file(cache->cache_fname, + OPEN_FLAGS_REPLACE|O_BINARY, + 0600, &open_file); + if (!f) + return -1; + + wrote = smartlist_create(); + + HT_FOREACH(mdp, microdesc_map, &cache->map) { + microdesc_t *md = *mdp; + size_t annotation_len; + if (md->no_save) + continue; + + size = dump_microdescriptor(f, md, &annotation_len); + if (size < 0) { + /* XXX handle errors from dump_microdescriptor() */ + /* log? return -1? die? coredump the universe? */ + continue; + } + md->off = off + annotation_len; + off += size; + if (md->saved_location != SAVED_IN_CACHE) { + tor_free(md->body); + md->saved_location = SAVED_IN_CACHE; + } + smartlist_add(wrote, md); + } + + finish_writing_to_file(open_file); /*XXX Check me.*/ + + if (cache->cache_content) + tor_munmap_file(cache->cache_content); + cache->cache_content = tor_mmap_file(cache->cache_fname); + + if (!cache->cache_content && smartlist_len(wrote)) { + log_err(LD_DIR, "Couldn't map file that we just wrote to %s!", + cache->cache_fname); + smartlist_free(wrote); + return -1; + } + 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(!memcmp(md->body, "onion-key", 9)); + } SMARTLIST_FOREACH_END(md); + + smartlist_free(wrote); + + write_str_to_file(cache->journal_fname, "", 1); + cache->journal_len = 0; + + new_size = (int)cache->cache_content->size; + log_info(LD_DIR, "Done rebuilding microdesc cache. " + "Saved %d bytes; %d still used.", + orig_size-new_size, new_size); + + return 0; +} + +/** Deallocate a single microdescriptor. Note: the microdescriptor MUST have + * previously been removed from the cache if it had ever been inserted. */ +void +microdesc_free(microdesc_t *md) +{ + if (!md) + return; + /* Must be removed from hash table! */ + if (md->onion_pkey) + crypto_free_pk_env(md->onion_pkey); + if (md->body && md->saved_location != SAVED_IN_CACHE) + tor_free(md->body); + + if (md->family) { + SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp)); + smartlist_free(md->family); + } + tor_free(md->exitsummary); + + tor_free(md); +} + +/** Free all storage held in the microdesc.c module. */ +void +microdesc_free_all(void) +{ + if (the_microdesc_cache) { + microdesc_cache_clear(the_microdesc_cache); + tor_free(the_microdesc_cache->cache_fname); + tor_free(the_microdesc_cache->journal_fname); + tor_free(the_microdesc_cache); + } +} + +/** If there is a microdescriptor in <b>cache</b> whose sha256 digest is + * <b>d</b>, return it. Otherwise return NULL. */ +microdesc_t * +microdesc_cache_lookup_by_digest256(microdesc_cache_t *cache, const char *d) +{ + microdesc_t *md, search; + if (!cache) + cache = get_microdesc_cache(); + memcpy(search.digest, d, DIGEST256_LEN); + md = HT_FIND(microdesc_map, &cache->map, &search); + return md; +} + +/** Return the mean size of decriptors added to <b>cache</b> since it was last + * cleared. Used to estimate the size of large downloads. */ +size_t +microdesc_average_size(microdesc_cache_t *cache) +{ + if (!cache) + cache = get_microdesc_cache(); + if (!cache->n_seen) + return 512; + return (size_t)(cache->total_len_seen / cache->n_seen); +} + diff --git a/src/or/microdesc.h b/src/or/microdesc.h new file mode 100644 index 0000000000..2d1a60ad0a --- /dev/null +++ b/src/or/microdesc.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file microdesc.h + * \brief Header file for microdesc.c. + **/ + +#ifndef _TOR_MICRODESC_H +#define _TOR_MICRODESC_H + +microdesc_cache_t *get_microdesc_cache(void); + +smartlist_t *microdescs_add_to_cache(microdesc_cache_t *cache, + const char *s, const char *eos, saved_location_t where, + int no_save); +smartlist_t *microdescs_add_list_to_cache(microdesc_cache_t *cache, + smartlist_t *descriptors, saved_location_t where, + int no_save); + +int microdesc_cache_rebuild(microdesc_cache_t *cache); +int microdesc_cache_reload(microdesc_cache_t *cache); +void microdesc_cache_clear(microdesc_cache_t *cache); + +microdesc_t *microdesc_cache_lookup_by_digest256(microdesc_cache_t *cache, + const char *d); + +size_t microdesc_average_size(microdesc_cache_t *cache); + +void microdesc_free(microdesc_t *md); +void microdesc_free_all(void); + +#endif + diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 4721420bbd..d645ee2b40 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -11,6 +11,20 @@ */ #include "or.h" +#include "circuitbuild.h" +#include "config.h" +#include "connection.h" +#include "connection_or.h" +#include "control.h" +#include "directory.h" +#include "dirserv.h" +#include "dirvote.h" +#include "main.h" +#include "networkstatus.h" +#include "relay.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" /* For tracking v2 networkstatus documents. Only caches do this now. */ @@ -35,16 +49,22 @@ static networkstatus_t *current_consensus = NULL; /** A v3 consensus networkstatus that we've received, but which we don't * have enough certificates to be happy about. */ -static networkstatus_t *consensus_waiting_for_certs = NULL; -/** The encoded version of consensus_waiting_for_certs. */ -static char *consensus_waiting_for_certs_body = NULL; -/** When did we set the current value of consensus_waiting_for_certs? If this - * is too recent, we shouldn't try to fetch a new consensus for a little while, - * to give ourselves time to get certificates for this one. */ -static time_t consensus_waiting_for_certs_set_at = 0; -/** Set to 1 if we've been holding on to consensus_waiting_for_certs so long - * that we should treat it as maybe being bad. */ -static int consensus_waiting_for_certs_dl_failed = 0; +typedef struct consensus_waiting_for_certs_t { + /** The consensus itself. */ + networkstatus_t *consensus; + /** The encoded version of the consensus, nul-terminated. */ + char *body; + /** When did we set the current value of consensus_waiting_for_certs? If + * this is too recent, we shouldn't try to fetch a new consensus for a + * little while, to give ourselves time to get certificates for this one. */ + time_t set_at; + /** Set to 1 if we've been holding on to it for so long we should maybe + * treat it as being bad. */ + int dl_failed; +} consensus_waiting_for_certs_t; + +static consensus_waiting_for_certs_t + consensus_waiting_for_certs[N_CONSENSUS_FLAVORS]; /** The last time we tried to download a networkstatus, or 0 for "never". We * use this to rate-limit download attempts for directory caches (including @@ -56,7 +76,7 @@ static time_t last_networkstatus_download_attempted = 0; * before the current consensus becomes invalid. */ static time_t time_to_download_next_consensus = 0; /** Download status for the current consensus networkstatus. */ -static download_status_t consensus_dl_status = { 0, 0, DL_SCHED_CONSENSUS }; +static download_status_t consensus_dl_status[N_CONSENSUS_FLAVORS]; /** True iff we have logged a warning about this OR's version being older than * listed by the authorities. */ @@ -89,6 +109,7 @@ networkstatus_reset_warnings(void) void networkstatus_reset_download_failures(void) { + int i; const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list(); SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs, @@ -97,7 +118,8 @@ networkstatus_reset_download_failures(void) rs->need_to_mirror = 1; }));; - download_status_reset(&consensus_dl_status); + for (i=0; i < N_CONSENSUS_FLAVORS; ++i) + download_status_reset(&consensus_dl_status[i]); if (v2_download_status_map) { digestmap_iter_t *iter; digestmap_t *map = v2_download_status_map; @@ -170,7 +192,7 @@ router_reload_v2_networkstatus(void) return 0; } -/** Read the cached v3 consensus networkstatus from the disk. */ +/** Read every cached v3 consensus networkstatus from the disk. */ int router_reload_consensus_networkstatus(void) { @@ -179,31 +201,46 @@ router_reload_consensus_networkstatus(void) struct stat st; or_options_t *options = get_options(); const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS; + int flav; /* FFFF Suppress warnings if cached consensus is bad? */ + for (flav = 0; flav < N_CONSENSUS_FLAVORS; ++flav) { + char buf[128]; + const char *flavor = networkstatus_get_flavor_name(flav); + if (flav == FLAV_NS) { + filename = get_datadir_fname("cached-consensus"); + } else { + tor_snprintf(buf, sizeof(buf), "cached-%s-consensus", flavor); + filename = get_datadir_fname(buf); + } + s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL); + if (s) { + if (networkstatus_set_current_consensus(s, flavor, flags) < -1) { + log_warn(LD_FS, "Couldn't load consensus %s networkstatus from \"%s\"", + flavor, filename); + } + tor_free(s); + } + tor_free(filename); - filename = get_datadir_fname("cached-consensus"); - s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL); - if (s) { - if (networkstatus_set_current_consensus(s, flags) < -1) { - log_warn(LD_FS, "Couldn't load consensus networkstatus from \"%s\"", - filename); + if (flav == FLAV_NS) { + filename = get_datadir_fname("unverified-consensus"); + } else { + tor_snprintf(buf, sizeof(buf), "unverified-%s-consensus", flavor); + filename = get_datadir_fname(buf); } - tor_free(s); - } - tor_free(filename); - filename = get_datadir_fname("unverified-consensus"); - s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL); - if (s) { - if (networkstatus_set_current_consensus(s, + s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL); + if (s) { + if (networkstatus_set_current_consensus(s, flavor, flags|NSSET_WAS_WAITING_FOR_CERTS)) { - log_info(LD_FS, "Couldn't load consensus networkstatus from \"%s\"", - filename); + log_info(LD_FS, "Couldn't load consensus %s networkstatus from \"%s\"", + flavor, filename); } - tor_free(s); + tor_free(s); + } + tor_free(filename); } - tor_free(filename); if (!current_consensus || (stat(options->FallbackNetworkstatusFile, &st)==0 && @@ -211,7 +248,7 @@ router_reload_consensus_networkstatus(void) s = read_file_to_str(options->FallbackNetworkstatusFile, RFTS_IGNORE_MISSING, NULL); if (s) { - if (networkstatus_set_current_consensus(s, + if (networkstatus_set_current_consensus(s, "ns", flags|NSSET_ACCEPT_OBSOLETE)) { log_info(LD_FS, "Couldn't load consensus networkstatus from \"%s\"", options->FallbackNetworkstatusFile); @@ -242,8 +279,16 @@ router_reload_consensus_networkstatus(void) static void vote_routerstatus_free(vote_routerstatus_t *rs) { + vote_microdesc_hash_t *h, *next; + if (!rs) + return; tor_free(rs->version); tor_free(rs->status.exitsummary); + for (h = rs->microdesc; h; h = next) { + tor_free(h->microdesc_hash_line); + next = h->next; + tor_free(h); + } tor_free(rs); } @@ -251,6 +296,8 @@ vote_routerstatus_free(vote_routerstatus_t *rs) void routerstatus_free(routerstatus_t *rs) { + if (!rs) + return; tor_free(rs->exitsummary); tor_free(rs); } @@ -259,6 +306,8 @@ routerstatus_free(routerstatus_t *rs) void networkstatus_v2_free(networkstatus_v2_t *ns) { + if (!ns) + return; tor_free(ns->source_address); tor_free(ns->contact); if (ns->signing_key) @@ -273,7 +322,25 @@ networkstatus_v2_free(networkstatus_v2_t *ns) tor_free(ns); } -/** Clear all storage held in <b>ns</b>. */ +/** Free all storage held in <b>sig</b> */ +void +document_signature_free(document_signature_t *sig) +{ + tor_free(sig->signature); + tor_free(sig); +} + +/** Return a newly allocated copy of <b>sig</b> */ +document_signature_t * +document_signature_dup(const document_signature_t *sig) +{ + document_signature_t *r = tor_memdup(sig, sizeof(document_signature_t)); + if (r->signature) + r->signature = tor_memdup(sig->signature, sig->signature_len); + return r; +} + +/** Free all storage held in <b>ns</b>. */ void networkstatus_vote_free(networkstatus_t *ns) { @@ -286,6 +353,10 @@ networkstatus_vote_free(networkstatus_t *ns) SMARTLIST_FOREACH(ns->known_flags, char *, c, tor_free(c)); smartlist_free(ns->known_flags); } + if (ns->weight_params) { + SMARTLIST_FOREACH(ns->weight_params, char *, c, tor_free(c)); + smartlist_free(ns->weight_params); + } if (ns->net_params) { SMARTLIST_FOREACH(ns->net_params, char *, c, tor_free(c)); smartlist_free(ns->net_params); @@ -295,18 +366,20 @@ networkstatus_vote_free(networkstatus_t *ns) smartlist_free(ns->supported_methods); } if (ns->voters) { - SMARTLIST_FOREACH(ns->voters, networkstatus_voter_info_t *, voter, - { + SMARTLIST_FOREACH_BEGIN(ns->voters, networkstatus_voter_info_t *, voter) { tor_free(voter->nickname); tor_free(voter->address); tor_free(voter->contact); - tor_free(voter->signature); + if (voter->sigs) { + SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig, + document_signature_free(sig)); + smartlist_free(voter->sigs); + } tor_free(voter); - }); + } SMARTLIST_FOREACH_END(voter); smartlist_free(ns->voters); } - if (ns->cert) - authority_cert_free(ns->cert); + authority_cert_free(ns->cert); if (ns->routerstatus_list) { if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) { @@ -319,8 +392,8 @@ networkstatus_vote_free(networkstatus_t *ns) smartlist_free(ns->routerstatus_list); } - if (ns->desc_digest_map) - digestmap_free(ns->desc_digest_map, NULL); + + digestmap_free(ns->desc_digest_map, NULL); memset(ns, 11, sizeof(*ns)); tor_free(ns); @@ -341,34 +414,38 @@ networkstatus_get_voter_by_id(networkstatus_t *vote, return NULL; } -/** Check whether the signature on <b>voter</b> is correctly signed by - * the signing key of <b>cert</b>. Return -1 if <b>cert</b> doesn't match the +/** Check whether the signature <b>sig</b> is correctly signed with the + * signing key in <b>cert</b>. Return -1 if <b>cert</b> doesn't match the * signing key; otherwise set the good_signature or bad_signature flag on * <b>voter</b>, and return 0. */ -/* (private; exposed for testing.) */ int -networkstatus_check_voter_signature(networkstatus_t *consensus, - networkstatus_voter_info_t *voter, - authority_cert_t *cert) +networkstatus_check_document_signature(const networkstatus_t *consensus, + document_signature_t *sig, + const authority_cert_t *cert) { - char d[DIGEST_LEN]; + char key_digest[DIGEST_LEN]; + const int dlen = sig->alg == DIGEST_SHA1 ? DIGEST_LEN : DIGEST256_LEN; char *signed_digest; size_t signed_digest_len; - if (crypto_pk_get_digest(cert->signing_key, d)<0) + + if (crypto_pk_get_digest(cert->signing_key, key_digest)<0) return -1; - if (memcmp(voter->signing_key_digest, d, DIGEST_LEN)) + if (memcmp(sig->signing_key_digest, key_digest, DIGEST_LEN) || + memcmp(sig->identity_digest, cert->cache_info.identity_digest, + DIGEST_LEN)) return -1; + signed_digest_len = crypto_pk_keysize(cert->signing_key); signed_digest = tor_malloc(signed_digest_len); if (crypto_pk_public_checksig(cert->signing_key, signed_digest, - voter->signature, - voter->signature_len) != DIGEST_LEN || - memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { + sig->signature, + sig->signature_len) < dlen || + memcmp(signed_digest, consensus->digests.d[sig->alg], dlen)) { log_warn(LD_DIR, "Got a bad signature on a networkstatus vote"); - voter->bad_signature = 1; + sig->bad_signature = 1; } else { - voter->good_signature = 1; + sig->good_signature = 1; } tor_free(signed_digest); return 0; @@ -387,7 +464,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, int warn) { int n_good = 0; - int n_missing_key = 0; + int n_missing_key = 0, n_dl_failed_key = 0; int n_bad = 0; int n_unknown = 0; int n_no_signature = 0; @@ -401,37 +478,62 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, tor_assert(consensus->type == NS_TYPE_CONSENSUS); - SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, voter, - { - if (!voter->good_signature && !voter->bad_signature && voter->signature) { - /* we can try to check the signature. */ - int is_v3_auth = trusteddirserver_get_by_v3_auth_digest( - voter->identity_digest) != NULL; - authority_cert_t *cert = - authority_cert_get_by_digests(voter->identity_digest, - voter->signing_key_digest); - if (!is_v3_auth) { - smartlist_add(unrecognized, voter); - ++n_unknown; - continue; - } else if (!cert || cert->expires < now) { - smartlist_add(need_certs_from, voter); - ++n_missing_key; - continue; - } - if (networkstatus_check_voter_signature(consensus, voter, cert) < 0) { - smartlist_add(need_certs_from, voter); - ++n_missing_key; - continue; + SMARTLIST_FOREACH_BEGIN(consensus->voters, networkstatus_voter_info_t *, + voter) { + int good_here = 0; + int bad_here = 0; + int unknown_here = 0; + int missing_key_here = 0, dl_failed_key_here = 0; + SMARTLIST_FOREACH_BEGIN(voter->sigs, document_signature_t *, sig) { + if (!sig->good_signature && !sig->bad_signature && + sig->signature) { + /* we can try to check the signature. */ + int is_v3_auth = trusteddirserver_get_by_v3_auth_digest( + sig->identity_digest) != NULL; + authority_cert_t *cert = + authority_cert_get_by_digests(sig->identity_digest, + sig->signing_key_digest); + tor_assert(!memcmp(sig->identity_digest, voter->identity_digest, + DIGEST_LEN)); + + if (!is_v3_auth) { + smartlist_add(unrecognized, voter); + ++unknown_here; + continue; + } else if (!cert || cert->expires < now) { + smartlist_add(need_certs_from, voter); + ++missing_key_here; + if (authority_cert_dl_looks_uncertain(sig->identity_digest)) + ++dl_failed_key_here; + continue; + } + if (networkstatus_check_document_signature(consensus, sig, cert) < 0) { + smartlist_add(need_certs_from, voter); + ++missing_key_here; + if (authority_cert_dl_looks_uncertain(sig->identity_digest)) + ++dl_failed_key_here; + continue; + } } - } - if (voter->good_signature) + if (sig->good_signature) + ++good_here; + else if (sig->bad_signature) + ++bad_here; + } SMARTLIST_FOREACH_END(sig); + if (good_here) ++n_good; - else if (voter->bad_signature) + else if (bad_here) ++n_bad; - else + else if (missing_key_here) { + ++n_missing_key; + if (dl_failed_key_here) + ++n_dl_failed_key; + } else if (unknown_here) { + ++n_unknown; + } else { ++n_no_signature; - }); + } + } SMARTLIST_FOREACH_END(voter); /* Now see whether we're missing any voters entirely. */ SMARTLIST_FOREACH(router_get_trusted_dir_servers(), @@ -442,39 +544,71 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, smartlist_add(missing_authorities, ds); }); - if (warn > 1 || (warn >= 0 && n_good < n_required)) + if (warn > 1 || (warn >= 0 && + (n_good + n_missing_key - n_dl_failed_key < n_required))) { severity = LOG_WARN; - else + } else { severity = LOG_INFO; + } if (warn >= 0) { SMARTLIST_FOREACH(unrecognized, networkstatus_voter_info_t *, voter, { - log_info(LD_DIR, "Consensus includes unrecognized authority '%s' " - "at %s:%d (contact %s; identity %s)", + log(severity, LD_DIR, "Consensus includes unrecognized authority " + "'%s' at %s:%d (contact %s; identity %s)", voter->nickname, voter->address, (int)voter->dir_port, voter->contact?voter->contact:"n/a", hex_str(voter->identity_digest, DIGEST_LEN)); }); SMARTLIST_FOREACH(need_certs_from, networkstatus_voter_info_t *, voter, { - log_info(LD_DIR, "Looks like we need to download a new certificate " - "from authority '%s' at %s:%d (contact %s; identity %s)", + log(severity, LD_DIR, "Looks like we need to download a new " + "certificate from authority '%s' at %s:%d (contact %s; " + "identity %s)", voter->nickname, voter->address, (int)voter->dir_port, voter->contact?voter->contact:"n/a", hex_str(voter->identity_digest, DIGEST_LEN)); }); SMARTLIST_FOREACH(missing_authorities, trusted_dir_server_t *, ds, { - log_info(LD_DIR, "Consensus does not include configured " + log(severity, LD_DIR, "Consensus does not include configured " "authority '%s' at %s:%d (identity %s)", ds->nickname, ds->address, (int)ds->dir_port, hex_str(ds->v3_identity_digest, DIGEST_LEN)); }); - log(severity, LD_DIR, - "%d unknown, %d missing key, %d good, %d bad, %d no signature, " - "%d required", n_unknown, n_missing_key, n_good, n_bad, - n_no_signature, n_required); + { + smartlist_t *sl = smartlist_create(); + char *cp; + tor_asprintf(&cp, "A consensus needs %d good signatures from recognized " + "authorities for us to accept it. This one has %d.", + n_required, n_good); + smartlist_add(sl,cp); + if (n_no_signature) { + tor_asprintf(&cp, "%d of the authorities we know didn't sign it.", + n_no_signature); + smartlist_add(sl,cp); + } + if (n_unknown) { + tor_asprintf(&cp, "It has %d signatures from authorities we don't " + "recognize.", n_unknown); + smartlist_add(sl,cp); + } + if (n_bad) { + tor_asprintf(&cp, "%d of the signatures on it didn't verify " + "correctly.", n_bad); + smartlist_add(sl,cp); + } + if (n_missing_key) { + tor_asprintf(&cp, "We were unable to check %d of the signatures, " + "because we were missing the keys.", n_missing_key); + smartlist_add(sl,cp); + } + cp = smartlist_join_strings(sl, " ", 0, NULL); + log(severity, LD_DIR, "%s", cp); + tor_free(cp); + SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); + smartlist_free(sl); + } } smartlist_free(unrecognized); @@ -784,8 +918,8 @@ networkstatus_v2_list_clean(time_t now) /** Helper for bsearching a list of routerstatus_t pointers: compare a * digest in the key to the identity digest of a routerstatus_t. */ -static int -_compare_digest_to_routerstatus_entry(const void *_key, const void **_member) +int +compare_digest_to_routerstatus_entry(const void *_key, const void **_member) { const char *key = _key; const routerstatus_t *rs = *_member; @@ -798,7 +932,7 @@ routerstatus_t * networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest) { return smartlist_bsearch(ns->entries, digest, - _compare_digest_to_routerstatus_entry); + compare_digest_to_routerstatus_entry); } /** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or @@ -807,7 +941,7 @@ routerstatus_t * networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest) { return smartlist_bsearch(ns->routerstatus_list, digest, - _compare_digest_to_routerstatus_entry); + compare_digest_to_routerstatus_entry); } /*XXXX make this static once functions are moved into this file. */ @@ -819,7 +953,7 @@ networkstatus_vote_find_entry_idx(networkstatus_t *ns, const char *digest, int *found_out) { return smartlist_bsearch_idx(ns->routerstatus_list, digest, - _compare_digest_to_routerstatus_entry, + compare_digest_to_routerstatus_entry, found_out); } @@ -872,7 +1006,7 @@ router_get_consensus_status_by_id(const char *digest) if (!current_consensus) return NULL; return smartlist_bsearch(current_consensus->routerstatus_list, digest, - _compare_digest_to_routerstatus_entry); + compare_digest_to_routerstatus_entry); } /** Given a nickname (possibly verbose, possibly a hexadecimal digest), return @@ -1076,28 +1210,30 @@ update_v2_networkstatus_cache_downloads(time_t now) static void update_consensus_networkstatus_downloads(time_t now) { - or_options_t *options = get_options(); + int i; 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. */ - if (authdir_mode_v3(options)) - return; /* Authorities never fetch a consensus */ - if (!download_status_is_ready(&consensus_dl_status, now, + /* 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.*/ - if (consensus_waiting_for_certs) { - /* XXXX make sure this doesn't delay sane downloads. */ - if (consensus_waiting_for_certs_set_at + DELAY_WHILE_FETCHING_CERTS > now) - return; /* We're still getting certs for this one. */ - else { - if (!consensus_waiting_for_certs_dl_failed) { - download_status_failed(&consensus_dl_status, 0); - consensus_waiting_for_certs_dl_failed=1; + for (i=0; i < N_CONSENSUS_FLAVORS; ++i) { + consensus_waiting_for_certs_t *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->dl_failed) { + download_status_failed(&consensus_dl_status[FLAV_NS], 0); + waiting->dl_failed=1; + } } } } @@ -1113,7 +1249,8 @@ update_consensus_networkstatus_downloads(time_t now) void networkstatus_consensus_download_failed(int status_code) { - download_status_failed(&consensus_dl_status, status_code); + /* 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)); } @@ -1147,8 +1284,15 @@ update_consensus_networkstatus_fetch_time(time_t now) /* We want to cache the next one at some point after this one * is no longer fresh... */ start = c->fresh_until + min_sec_before_caching; - /* But only in the first half-interval after that. */ - dl_interval = interval/2; + /* Some clients may need the consensus sooner than others. */ + if (options->FetchDirInfoExtraEarly || authdir_mode_v3(options)) { + dl_interval = 60; + if (min_sec_before_caching + dl_interval > interval) + dl_interval = interval/2; + } else { + /* But only in the first half-interval after that. */ + dl_interval = interval/2; + } } else { /* We're an ordinary client or a bridge. Give all the caches enough * time to download the consensus. */ @@ -1167,7 +1311,7 @@ update_consensus_networkstatus_fetch_time(time_t now) } if (dl_interval < 1) dl_interval = 1; - /* We must not try to replace c while it's still the most valid: */ + /* We must not try to replace c while it's still fresh: */ tor_assert(c->fresh_until < start); /* We must download the next one before c is invalid: */ tor_assert(start+dl_interval < c->valid_until); @@ -1188,7 +1332,6 @@ update_consensus_networkstatus_fetch_time(time_t now) time_to_download_next_consensus = now; log_info(LD_DIR, "No live consensus; we should fetch one immediately."); } - } /** Return 1 if there's a reason we shouldn't try any directory @@ -1223,10 +1366,14 @@ update_networkstatus_downloads(time_t now) void update_certificate_downloads(time_t now) { - if (consensus_waiting_for_certs) - authority_certs_fetch_missing(consensus_waiting_for_certs, now); - else - authority_certs_fetch_missing(current_consensus, now); + int i; + for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) { + if (consensus_waiting_for_certs[i].consensus) + authority_certs_fetch_missing(consensus_waiting_for_certs[i].consensus, + now); + } + + authority_certs_fetch_missing(current_consensus, now); } /** Return 1 if we have a consensus but we don't have enough certificates @@ -1234,7 +1381,8 @@ update_certificate_downloads(time_t now) int consensus_is_waiting_for_certs(void) { - return consensus_waiting_for_certs ? 1 : 0; + return consensus_waiting_for_certs[USABLE_CONSENSUS_FLAVOR].consensus + ? 1 : 0; } /** Return the network status with a given identity digest. */ @@ -1403,16 +1551,31 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c, * user, and -2 for more serious problems. */ int -networkstatus_set_current_consensus(const char *consensus, unsigned flags) +networkstatus_set_current_consensus(const char *consensus, + const char *flavor, + unsigned flags) { - networkstatus_t *c; + networkstatus_t *c=NULL; int r, result = -1; time_t now = time(NULL); + 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; const unsigned was_waiting_for_certs = flags & NSSET_WAS_WAITING_FOR_CERTS; const unsigned dl_certs = !(flags & NSSET_DONT_DOWNLOAD_CERTS); const unsigned accept_obsolete = flags & NSSET_ACCEPT_OBSOLETE; + const unsigned require_flavor = flags & NSSET_REQUIRE_FLAVOR; + const digests_t *current_digests = NULL; + consensus_waiting_for_certs_t *waiting = NULL; + time_t current_valid_after = 0; + int free_consensus = 1; /* Free 'c' at the end of the function */ + + if (flav < 0) { + /* XXXX we don't handle unrecognized flavors yet. */ + log_warn(LD_BUG, "Unrecognized consensus flavor %s", flavor); + return -2; + } /* Make sure it's parseable. */ c = networkstatus_parse_vote_from_string(consensus, NULL, NS_TYPE_CONSENSUS); @@ -1422,33 +1585,69 @@ networkstatus_set_current_consensus(const char *consensus, unsigned flags) goto done; } + if ((int)c->flavor != flav) { + /* This wasn't the flavor we thought we were getting. */ + if (require_flavor) { + log_warn(LD_DIR, "Got consensus with unexpected flavor %s (wanted %s)", + networkstatus_get_flavor_name(c->flavor), flavor); + goto done; + } + flav = c->flavor; + flavor = networkstatus_get_flavor_name(flav); + } + + 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. */ + goto done; + } + if (from_cache && !accept_obsolete && c->valid_until < now-OLD_ROUTER_DESC_MAX_AGE) { /* XXX022 when we try to make fallbackconsensus work again, we should * consider taking this out. Until then, believing obsolete consensuses * is causing more harm than good. See also bug 887. */ - log_info(LD_DIR, "Loaded an obsolete consensus. Discarding."); + log_info(LD_DIR, "Loaded an expired consensus. Discarding."); goto done; } - if (current_consensus && - !memcmp(c->networkstatus_digest, current_consensus->networkstatus_digest, - DIGEST_LEN)) { + 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; + } + } else { + cached_dir_t *cur; + char buf[128]; + tor_snprintf(buf, sizeof(buf), "cached-%s-consensus", flavor); + consensus_fname = get_datadir_fname(buf); + tor_snprintf(buf, sizeof(buf), "unverified-%s-consensus", flavor); + unverified_fname = get_datadir_fname(buf); + cur = dirserv_get_consensus(flavor); + if (cur) { + current_digests = &cur->digests; + current_valid_after = cur->published; + } + } + + if (current_digests && + !memcmp(&c->digests, current_digests, sizeof(c->digests))) { /* We already have this one. That's a failure. */ - log_info(LD_DIR, "Got a consensus we already have"); + log_info(LD_DIR, "Got a %s consensus we already have", flavor); goto done; } - if (current_consensus && c->valid_after <= current_consensus->valid_after) { + if (current_valid_after && c->valid_after <= current_valid_after) { /* We have a newer one. There's no point in accepting this one, * even if it's great. */ - log_info(LD_DIR, "Got a consensus at least as old as the one we have"); + log_info(LD_DIR, "Got a %s consensus at least as old as the one we have", + flavor); goto done; } - consensus_fname = get_datadir_fname("cached-consensus"); - unverified_fname = get_datadir_fname("unverified-consensus"); - /* Make sure it's signed enough. */ if ((r=networkstatus_check_consensus_signature(c, 1))<0) { if (r == -1) { @@ -1457,16 +1656,16 @@ networkstatus_set_current_consensus(const char *consensus, unsigned flags) log_info(LD_DIR, "Not enough certificates to check networkstatus consensus"); } - if (!current_consensus || - c->valid_after > current_consensus->valid_after) { - if (consensus_waiting_for_certs) - networkstatus_vote_free(consensus_waiting_for_certs); - tor_free(consensus_waiting_for_certs_body); - consensus_waiting_for_certs = c; - c = NULL; /* Prevent free. */ - consensus_waiting_for_certs_body = tor_strdup(consensus); - consensus_waiting_for_certs_set_at = now; - consensus_waiting_for_certs_dl_failed = 0; + if (!current_valid_after || + c->valid_after > current_valid_after) { + waiting = &consensus_waiting_for_certs[flav]; + networkstatus_vote_free(waiting->consensus); + tor_free(waiting->body); + waiting->consensus = c; + free_consensus = 0; + waiting->body = tor_strdup(consensus); + waiting->set_at = now; + waiting->dl_failed = 0; if (!from_cache) { write_str_to_file(unverified_fname, consensus, 0); } @@ -1495,56 +1694,75 @@ networkstatus_set_current_consensus(const char *consensus, unsigned flags) } } - if (!from_cache) + 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); - notify_control_networkstatus_changed(current_consensus, c); + 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 (current_consensus) { + networkstatus_copy_old_consensus_info(c, current_consensus); + networkstatus_vote_free(current_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; + } } - if (consensus_waiting_for_certs && - consensus_waiting_for_certs->valid_after <= c->valid_after) { - networkstatus_vote_free(consensus_waiting_for_certs); - consensus_waiting_for_certs = NULL; - if (consensus != consensus_waiting_for_certs_body) - tor_free(consensus_waiting_for_certs_body); + waiting = &consensus_waiting_for_certs[flav]; + if (waiting->consensus && + waiting->consensus->valid_after <= c->valid_after) { + networkstatus_vote_free(waiting->consensus); + waiting->consensus = NULL; + if (consensus != waiting->body) + tor_free(waiting->body); else - consensus_waiting_for_certs_body = NULL; - consensus_waiting_for_certs_set_at = 0; - consensus_waiting_for_certs_dl_failed = 0; + waiting->body = NULL; + waiting->set_at = 0; + waiting->dl_failed = 0; unlink(unverified_fname); } /* Reset the failure count only if this consensus is actually valid. */ if (c->valid_after <= now && now <= c->valid_until) { - download_status_reset(&consensus_dl_status); + download_status_reset(&consensus_dl_status[flav]); } else { if (!from_cache) - download_status_failed(&consensus_dl_status, 0); + download_status_failed(&consensus_dl_status[flav], 0); } - current_consensus = c; - c = NULL; /* Prevent free. */ + if (flav == USABLE_CONSENSUS_FLAVOR) { + current_consensus = c; + free_consensus = 0; /* Prevent free. */ + + /* XXXXNM Microdescs: needs a non-ns variant. */ + update_consensus_networkstatus_fetch_time(now); + dirvote_recalculate_timing(options, now); + routerstatus_list_update_named_server_map(); + cell_ewma_set_scale_factor(options, current_consensus); + + /* XXX022 where is the right place to put this call? */ + connection_or_update_token_buckets(get_connection_array(), options); - update_consensus_networkstatus_fetch_time(now); - dirvote_recalculate_timing(get_options(), now); - routerstatus_list_update_named_server_map(); + circuit_build_times_new_consensus_params(&circ_times, current_consensus); + } + + if (directory_caches_dir_info(options)) { + dirserv_set_cached_consensus_networkstatus(consensus, + flavor, + &c->digests, + c->valid_after); + } if (!from_cache) { write_str_to_file(consensus_fname, consensus, 0); } - if (directory_caches_dir_info(get_options())) - dirserv_set_cached_networkstatus_v3(consensus, - current_consensus->valid_after); - if (ftime_definitely_before(now, current_consensus->valid_after)) { char tbuf[ISO_TIME_LEN+1]; char dbuf[64]; @@ -1563,7 +1781,7 @@ networkstatus_set_current_consensus(const char *consensus, unsigned flags) result = 0; done: - if (c) + if (free_consensus) networkstatus_vote_free(c); tor_free(consensus_fname); tor_free(unverified_fname); @@ -1575,13 +1793,17 @@ networkstatus_set_current_consensus(const char *consensus, unsigned flags) void networkstatus_note_certs_arrived(void) { - if (consensus_waiting_for_certs) { - if (networkstatus_check_consensus_signature( - consensus_waiting_for_certs, 0)>=0) { + int i; + for (i=0; i<N_CONSENSUS_FLAVORS; ++i) { + consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i]; + if (!waiting->consensus) + continue; + if (networkstatus_check_consensus_signature(waiting->consensus, 0)>=0) { if (!networkstatus_set_current_consensus( - consensus_waiting_for_certs_body, + waiting->body, + networkstatus_get_flavor_name(i), NSSET_WAS_WAITING_FOR_CERTS)) { - tor_free(consensus_waiting_for_certs_body); + tor_free(waiting->body); } } } @@ -1667,10 +1889,8 @@ download_status_map_update_from_v2_networkstatus(void) v2_download_status_map = digestmap_new(); dl_status = digestmap_new(); - SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, - { - SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs, - { + SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) { + SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) { const char *d = rs->descriptor_digest; download_status_t *s; if (digestmap_get(dl_status, d)) @@ -1679,8 +1899,8 @@ download_status_map_update_from_v2_networkstatus(void) s = tor_malloc_zero(sizeof(download_status_t)); } digestmap_set(dl_status, d, s); - }); - }); + } SMARTLIST_FOREACH_END(rs); + } SMARTLIST_FOREACH_END(ns); digestmap_free(v2_download_status_map, _tor_free); v2_download_status_map = dl_status; networkstatus_v2_list_has_changed = 0; @@ -1694,11 +1914,9 @@ routerstatus_list_update_named_server_map(void) if (!current_consensus) return; - if (named_server_map) - strmap_free(named_server_map, _tor_free); + strmap_free(named_server_map, _tor_free); named_server_map = strmap_new(); - if (unnamed_server_map) - strmap_free(unnamed_server_map, NULL); + strmap_free(unnamed_server_map, NULL); unnamed_server_map = strmap_new(); SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs, { @@ -1773,6 +1991,15 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, 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 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); + if (old_router != router) { + router->needs_retest_if_added = + dirserv_should_launch_reachability_test(router, old_router); + } } if (router->is_running && ds) { download_status_reset(&ds->v2_ns_dl_status); @@ -1835,7 +2062,7 @@ char * networkstatus_getinfo_helper_single(routerstatus_t *rs) { char buf[RS_ENTRY_LEN+1]; - routerstatus_format_entry(buf, sizeof(buf), rs, NULL, 0, 1); + routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT); return tor_strdup(buf); } @@ -1872,7 +2099,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, ri, now, 0, 0, 0); smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs)); }); @@ -1897,6 +2124,25 @@ networkstatus_dump_bridge_status_to_file(time_t now) tor_free(status); } +int32_t +get_net_param_from_list(smartlist_t *net_params, const char *param_name, + int default_val) +{ + size_t name_len = strlen(param_name); + + SMARTLIST_FOREACH_BEGIN(net_params, const char *, p) { + if (!strcmpstart(p, param_name) && p[name_len] == '=') { + int ok=0; + long v = tor_parse_long(p+name_len+1, 10, INT32_MIN, + INT32_MAX, &ok, NULL); + if (ok) + return (int32_t) v; + } + } SMARTLIST_FOREACH_END(p); + + return default_val; +} + /** Return the value of a integer parameter from the networkstatus <b>ns</b> * whose name is <b>param_name</b>. If <b>ns</b> is NULL, try loading the * latest consensus ourselves. Return <b>default_val</b> if no latest @@ -1905,27 +2151,59 @@ int32_t networkstatus_get_param(networkstatus_t *ns, const char *param_name, int32_t default_val) { - size_t name_len; - if (!ns) /* if they pass in null, go find it ourselves */ ns = networkstatus_get_latest_consensus(); if (!ns || !ns->net_params) return default_val; - name_len = strlen(param_name); + return get_net_param_from_list(ns->net_params, param_name, default_val); +} - SMARTLIST_FOREACH_BEGIN(ns->net_params, const char *, p) { - if (!strcmpstart(p, param_name) && p[name_len] == '=') { - int ok=0; - long v = tor_parse_long(p+name_len+1, 10, INT32_MIN, INT32_MAX, &ok, - NULL); - if (ok) - return (int32_t) v; - } - } SMARTLIST_FOREACH_END(p); +/** Return the value of a integer bw weight parameter from the networkstatus + * <b>ns</b> whose name is <b>weight_name</b>. If <b>ns</b> is NULL, try + * loading the latest consensus ourselves. Return <b>default_val</b> if no + * latest consensus, or if it has no parameter called <b>param_name</b>. */ +int32_t +networkstatus_get_bw_weight(networkstatus_t *ns, const char *weight_name, + int32_t default_val) +{ + if (!ns) /* if they pass in null, go find it ourselves */ + ns = networkstatus_get_latest_consensus(); - return default_val; + if (!ns || !ns->weight_params) + return default_val; + + return get_net_param_from_list(ns->weight_params, weight_name, default_val); +} + +/** Return the name of the consensus flavor <b>flav</b> as used to identify + * the flavor in directory documents. */ +const char * +networkstatus_get_flavor_name(consensus_flavor_t flav) +{ + switch (flav) { + case FLAV_NS: + return "ns"; + case FLAV_MICRODESC: + return "microdesc"; + default: + tor_fragile_assert(); + return "??"; + } +} + +/** Return the consensus_flavor_t value for the flavor called <b>flavname</b>, + * or -1 if the flavor is not recognized. */ +int +networkstatus_parse_flavor_name(const char *flavname) +{ + if (!strcmp(flavname, "ns")) + return FLAV_NS; + else if (!strcmp(flavname, "microdesc")) + return FLAV_MICRODESC; + else + return -1; } /** If <b>question</b> is a string beginning with "ns/" in a format the @@ -1934,7 +2212,8 @@ networkstatus_get_param(networkstatus_t *ns, const char *param_name, * ORs. Return 0 on success, -1 on unrecognized question format. */ int getinfo_helper_networkstatus(control_connection_t *conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { routerstatus_t *status; (void) conn; @@ -1958,8 +2237,10 @@ getinfo_helper_networkstatus(control_connection_t *conn, } else if (!strcmpstart(question, "ns/id/")) { char d[DIGEST_LEN]; - if (base16_decode(d, DIGEST_LEN, question+6, strlen(question+6))) + if (base16_decode(d, DIGEST_LEN, question+6, strlen(question+6))) { + *errmsg = "Data not decodeable as hex"; return -1; + } status = router_get_consensus_status_by_id(d); } else if (!strcmpstart(question, "ns/name/")) { status = router_get_consensus_status_by_nickname(question+8, 0); @@ -1967,7 +2248,7 @@ getinfo_helper_networkstatus(control_connection_t *conn, *answer = networkstatus_getinfo_by_purpose(question+11, time(NULL)); return *answer ? 0 : -1; } else { - return -1; + return 0; } if (status) @@ -1979,30 +2260,29 @@ getinfo_helper_networkstatus(control_connection_t *conn, void networkstatus_free_all(void) { + int i; if (networkstatus_v2_list) { SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, networkstatus_v2_free(ns)); smartlist_free(networkstatus_v2_list); networkstatus_v2_list = NULL; } - if (v2_download_status_map) { - digestmap_free(v2_download_status_map, _tor_free); - v2_download_status_map = NULL; - } - if (current_consensus) { - networkstatus_vote_free(current_consensus); - current_consensus = NULL; - } - if (consensus_waiting_for_certs) { - networkstatus_vote_free(consensus_waiting_for_certs); - consensus_waiting_for_certs = NULL; - } - tor_free(consensus_waiting_for_certs_body); - if (named_server_map) { - strmap_free(named_server_map, _tor_free); - } - if (unnamed_server_map) { - strmap_free(unnamed_server_map, NULL); + + digestmap_free(v2_download_status_map, _tor_free); + v2_download_status_map = NULL; + networkstatus_vote_free(current_consensus); + current_consensus = NULL; + + for (i=0; i < N_CONSENSUS_FLAVORS; ++i) { + consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i]; + if (waiting->consensus) { + networkstatus_vote_free(waiting->consensus); + waiting->consensus = NULL; + } + tor_free(waiting->body); } + + strmap_free(named_server_map, _tor_free); + strmap_free(unnamed_server_map, NULL); } diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h new file mode 100644 index 0000000000..32b71a9ceb --- /dev/null +++ b/src/or/networkstatus.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file networkstatus.h + * \brief Header file for networkstatus.c. + **/ + +#ifndef _TOR_NETWORKSTATUS_H +#define _TOR_NETWORKSTATUS_H + +/** How old do we allow a v2 network-status to get before removing it + * completely? */ +#define MAX_NETWORKSTATUS_AGE (10*24*60*60) + +void networkstatus_reset_warnings(void); +void networkstatus_reset_download_failures(void); +int router_reload_v2_networkstatus(void); +int router_reload_consensus_networkstatus(void); +void routerstatus_free(routerstatus_t *rs); +void networkstatus_v2_free(networkstatus_v2_t *ns); +void networkstatus_vote_free(networkstatus_t *ns); +networkstatus_voter_info_t *networkstatus_get_voter_by_id( + networkstatus_t *vote, + const char *identity); +int networkstatus_check_consensus_signature(networkstatus_t *consensus, + int warn); +int networkstatus_check_document_signature(const networkstatus_t *consensus, + document_signature_t *sig, + const authority_cert_t *cert); +char *networkstatus_get_cache_filename(const char *identity_digest); +int router_set_networkstatus_v2(const char *s, time_t arrived_at, + v2_networkstatus_source_t source, + smartlist_t *requested_fingerprints); +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 char *digest); +routerstatus_t *networkstatus_vote_find_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 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 update_consensus_networkstatus_fetch_time(time_t now); +int should_delay_dir_fetches(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_live_consensus(time_t now); +networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now); +#define NSSET_FROM_CACHE 1 +#define NSSET_WAS_WAITING_FOR_CERTS 2 +#define NSSET_DONT_DOWNLOAD_CERTS 4 +#define NSSET_ACCEPT_OBSOLETE 8 +#define NSSET_REQUIRE_FLAVOR 16 +int networkstatus_set_current_consensus(const char *consensus, + const char *flavor, + unsigned flags); +void networkstatus_note_certs_arrived(void); +void routers_update_all_from_networkstatus(time_t now, int dir_version); +void routers_update_status_from_consensus_networkstatus(smartlist_t *routers, + int reset_failures); +void signed_descs_update_status_from_consensus_networkstatus( + smartlist_t *descs); + +char *networkstatus_getinfo_helper_single(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 get_net_param_from_list(smartlist_t *net_params, const char *name, + int default_val); +int32_t networkstatus_get_param(networkstatus_t *ns, const char *param_name, + int32_t default_val); +int getinfo_helper_networkstatus(control_connection_t *conn, + const char *question, char **answer, + const char **errmsg); +int32_t networkstatus_get_bw_weight(networkstatus_t *ns, const char *weight, + int32_t default_val); +const char *networkstatus_get_flavor_name(consensus_flavor_t flav); +int networkstatus_parse_flavor_name(const char *flavname); +void document_signature_free(document_signature_t *sig); +document_signature_t *document_signature_dup(const document_signature_t *sig); +void networkstatus_free_all(void); + +#endif + diff --git a/src/or/ntmain.c b/src/or/ntmain.c index ad6698e722..46e7afb78b 100644 --- a/src/or/ntmain.c +++ b/src/or/ntmain.c @@ -5,13 +5,22 @@ #define MAIN_PRIVATE #include "or.h" - -#include <tchar.h> -#define GENSRV_SERVICENAME TEXT("tor") -#define GENSRV_DISPLAYNAME TEXT("Tor Win32 Service") +#include "config.h" +#include "main.h" +#include "ntmain.h" + +#ifdef HAVE_EVENT2_EVENT_H +#include <event2/event.h> +#else +#include <event.h> +#endif + +#include <windows.h> +#define GENSRV_SERVICENAME "tor" +#define GENSRV_DISPLAYNAME "Tor Win32 Service" #define GENSRV_DESCRIPTION \ - TEXT("Provides an anonymous Internet communication system") -#define GENSRV_USERACCT TEXT("NT AUTHORITY\\LocalService") + "Provides an anonymous Internet communication system" +#define GENSRV_USERACCT "NT AUTHORITY\\LocalService" // Cheating: using the pre-defined error codes, tricks Windows into displaying // a semi-related human-readable error message if startup fails as @@ -27,7 +36,6 @@ static SERVICE_STATUS_HANDLE hStatus; * to the NT service functions. */ static char **backup_argv; static int backup_argc; -static char* nt_strerror(uint32_t errnum); static void nt_service_control(DWORD request); static void nt_service_body(int argc, char **argv); @@ -61,30 +69,30 @@ struct service_fns { SC_HANDLE (WINAPI *CreateServiceA_fn)( SC_HANDLE hSCManager, - LPCTSTR lpServiceName, - LPCTSTR lpDisplayName, + LPCSTR lpServiceName, + LPCSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, - LPCTSTR lpBinaryPathName, - LPCTSTR lpLoadOrderGroup, + LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, - LPCTSTR lpDependencies, - LPCTSTR lpServiceStartName, - LPCTSTR lpPassword); + LPCSTR lpDependencies, + LPCSTR lpServiceStartName, + LPCSTR lpPassword); BOOL (WINAPI *DeleteService_fn)( SC_HANDLE hService); SC_HANDLE (WINAPI *OpenSCManagerA_fn)( - LPCTSTR lpMachineName, - LPCTSTR lpDatabaseName, + LPCSTR lpMachineName, + LPCSTR lpDatabaseName, DWORD dwDesiredAccess); SC_HANDLE (WINAPI *OpenServiceA_fn)( SC_HANDLE hSCManager, - LPCTSTR lpServiceName, + LPCSTR lpServiceName, DWORD dwDesiredAccess); BOOL (WINAPI *QueryServiceStatus_fn)( @@ -92,23 +100,23 @@ struct service_fns { LPSERVICE_STATUS lpServiceStatus); SERVICE_STATUS_HANDLE (WINAPI *RegisterServiceCtrlHandlerA_fn)( - LPCTSTR lpServiceName, + LPCSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc); BOOL (WINAPI *SetServiceStatus_fn)(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS); BOOL (WINAPI *StartServiceCtrlDispatcherA_fn)( - const SERVICE_TABLE_ENTRY* lpServiceTable); + const SERVICE_TABLE_ENTRYA* lpServiceTable); BOOL (WINAPI *StartServiceA_fn)( SC_HANDLE hService, DWORD dwNumServiceArgs, - LPCTSTR* lpServiceArgVectors); + LPCSTR* lpServiceArgVectors); BOOL (WINAPI *LookupAccountNameA_fn)( - LPCTSTR lpSystemName, - LPCTSTR lpAccountName, + LPCSTR lpSystemName, + LPCSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPTSTR ReferencedDomainName, @@ -130,8 +138,7 @@ nt_service_loadlibrary(void) if (service_fns.loaded) return; - /* XXXX Possibly, we should hardcode the location of this DLL. */ - if (!(library = LoadLibrary("advapi32.dll"))) { + if (!(library = load_windows_system_library(TEXT("advapi32.dll")))) { log_err(LD_GENERAL, "Couldn't open advapi32.dll. Are you trying to use " "NT services on Windows 98? That doesn't work."); goto err; @@ -218,7 +225,7 @@ nt_service_control(DWORD request) log_notice(LD_GENERAL, "Got stop/shutdown request; shutting down cleanly."); service_status.dwCurrentState = SERVICE_STOP_PENDING; - event_loopexit(&exit_now); + event_base_loopexit(tor_libevent_get_base(), &exit_now); return; } service_fns.SetServiceStatus_fn(hStatus, &service_status); @@ -275,20 +282,20 @@ nt_service_body(int argc, char **argv) static void nt_service_main(void) { - SERVICE_TABLE_ENTRY table[2]; + SERVICE_TABLE_ENTRYA table[2]; DWORD result = 0; char *errmsg; nt_service_loadlibrary(); table[0].lpServiceName = (char*)GENSRV_SERVICENAME; - table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body; + table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)nt_service_body; table[1].lpServiceName = NULL; table[1].lpServiceProc = NULL; if (!service_fns.StartServiceCtrlDispatcherA_fn(table)) { result = GetLastError(); - errmsg = nt_strerror(result); + errmsg = format_win32_error(result); printf("Service error %d : %s\n", (int) result, errmsg); - LocalFree(errmsg); + tor_free(errmsg); if (result == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { if (tor_init(backup_argc, backup_argv) < 0) return; @@ -323,9 +330,9 @@ nt_service_open_scm(void) nt_service_loadlibrary(); if ((hSCManager = service_fns.OpenSCManagerA_fn( NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) { - errmsg = nt_strerror(GetLastError()); + errmsg = format_win32_error(GetLastError()); printf("OpenSCManager() failed : %s\n", errmsg); - LocalFree(errmsg); + tor_free(errmsg); } return hSCManager; } @@ -340,9 +347,9 @@ nt_service_open(SC_HANDLE hSCManager) nt_service_loadlibrary(); if ((hService = service_fns.OpenServiceA_fn(hSCManager, GENSRV_SERVICENAME, SERVICE_ALL_ACCESS)) == NULL) { - errmsg = nt_strerror(GetLastError()); + errmsg = format_win32_error(GetLastError()); printf("OpenService() failed : %s\n", errmsg); - LocalFree(errmsg); + tor_free(errmsg); } return hService; } @@ -374,14 +381,14 @@ nt_service_start(SC_HANDLE hService) printf("Service started successfully\n"); return 0; } else { - errmsg = nt_strerror(service_status.dwWin32ExitCode); + errmsg = format_win32_error(service_status.dwWin32ExitCode); printf("Service failed to start : %s\n", errmsg); - LocalFree(errmsg); + tor_free(errmsg); } } else { - errmsg = nt_strerror(GetLastError()); + errmsg = format_win32_error(GetLastError()); printf("StartService() failed : %s\n", errmsg); - LocalFree(errmsg); + tor_free(errmsg); } return -1; } @@ -418,14 +425,14 @@ nt_service_stop(SC_HANDLE hService) } else if (wait_time == MAX_SERVICE_WAIT_TIME) { printf("Service did not stop within %d seconds.\n", wait_time); } else { - errmsg = nt_strerror(GetLastError()); + errmsg = format_win32_error(GetLastError()); printf("QueryServiceStatus() failed : %s\n",errmsg); - LocalFree(errmsg); + tor_free(errmsg); } } else { - errmsg = nt_strerror(GetLastError()); + errmsg = format_win32_error(GetLastError()); printf("ControlService() failed : %s\n", errmsg); - LocalFree(errmsg); + tor_free(errmsg); } return -1; } @@ -439,6 +446,7 @@ static char * nt_service_command_line(int *using_default_torrc) { TCHAR tor_exe[MAX_PATH+1]; + char tor_exe_ascii[MAX_PATH+1]; char *command, *options=NULL; smartlist_t *sl; int i, cmdlen; @@ -464,18 +472,25 @@ nt_service_command_line(int *using_default_torrc) options = smartlist_join_strings(sl,"\" \"",0,NULL); smartlist_free(sl); +#ifdef UNICODE + wcstombs(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii)); +#else + strlcpy(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii)); +#endif + /* Allocate a string for the NT service command line */ - cmdlen = strlen(tor_exe) + (options?strlen(options):0) + 32; + cmdlen = strlen(tor_exe_ascii) + (options?strlen(options):0) + 32; command = tor_malloc(cmdlen); /* Format the service command */ if (options) { if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service \"%s\"", - tor_exe, options)<0) { + tor_exe_ascii, options)<0) { tor_free(command); /* sets command to NULL. */ } } else { /* ! options */ - if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service", tor_exe)<0) { + if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service", + tor_exe_ascii)<0) { tor_free(command); /* sets command to NULL. */ } } @@ -500,7 +515,7 @@ nt_service_install(int argc, char **argv) SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; - SERVICE_DESCRIPTION sdBuff; + SERVICE_DESCRIPTIONA sdBuff; char *command; char *errmsg; const char *user_acct = GENSRV_USERACCT; @@ -590,10 +605,10 @@ nt_service_install(int argc, char **argv) SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, command, NULL, NULL, NULL, user_acct, password)) == NULL) { - errmsg = nt_strerror(GetLastError()); + errmsg = format_win32_error(GetLastError()); printf("CreateService() failed : %s\n", errmsg); service_fns.CloseServiceHandle_fn(hSCManager); - LocalFree(errmsg); + tor_free(errmsg); tor_free(command); return -1; } @@ -634,9 +649,9 @@ nt_service_remove(void) nt_service_stop(hService); if (service_fns.DeleteService_fn(hService) == FALSE) { - errmsg = nt_strerror(GetLastError()); + errmsg = format_win32_error(GetLastError()); printf("DeleteService() failed : %s\n", errmsg); - LocalFree(errmsg); + tor_free(errmsg); service_fns.CloseServiceHandle_fn(hService); service_fns.CloseServiceHandle_fn(hSCManager); return -1; @@ -693,20 +708,6 @@ nt_service_cmd_stop(void) return stop; } -/** Given a Win32 error code, this attempts to make Windows - * return a human-readable error message. The char* returned - * is allocated by Windows, but should be freed with LocalFree() - * when finished with it. */ -static char* -nt_strerror(uint32_t errnum) -{ - char *msgbuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&msgbuf, 0, NULL); - return msgbuf; -} - int nt_service_parse_options(int argc, char **argv, int *should_exit) { diff --git a/src/or/ntmain.h b/src/or/ntmain.h new file mode 100644 index 0000000000..2cfa653c3d --- /dev/null +++ b/src/or/ntmain.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file ntmain.h + * \brief Header file for ntmain.c. + **/ + +#ifndef _TOR_NTMAIN_H +#define _TOR_NTMAIN_H + +#ifdef MS_WINDOWS +#if !defined (WINCE) +#define NT_SERVICE +#endif +#endif + +#ifdef NT_SERVICE +int nt_service_parse_options(int argc, char **argv, int *should_exit); +int nt_service_is_stopping(void); +void nt_service_set_state(DWORD state); +#else +#define nt_service_is_stopping() 0 +#endif + +#endif + diff --git a/src/or/onion.c b/src/or/onion.c index 42e02c690c..4d14f9095b 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -11,6 +11,10 @@ **/ #include "or.h" +#include "circuitlist.h" +#include "config.h" +#include "onion.h" +#include "rephist.h" /** Type for a linked list of circuits that are waiting for a free CPU worker * to process a waiting onion handshake. */ @@ -58,11 +62,18 @@ onion_pending_add(or_circuit_t *circ, char *onionskin) tor_assert(!ol_tail->next); if (ol_length >= get_options()->MaxOnionsPending) { - log_warn(LD_GENERAL, - "Your computer is too slow to handle this many circuit " - "creation requests! Please consider using the " - "MaxAdvertisedBandwidth config option or choosing a more " - "restricted exit policy."); +#define WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL (60) + static ratelim_t last_warned = + RATELIM_INIT(WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL); + char *m; + if ((m = rate_limit_log(&last_warned, approx_time()))) { + log_warn(LD_GENERAL, + "Your computer is too slow to handle this many circuit " + "creation requests! Please consider using the " + "MaxAdvertisedBandwidth config option or choosing a more " + "restricted exit policy.%s",m); + tor_free(m); + } tor_free(tmp); return -1; } @@ -253,8 +264,9 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/ key_material_len = DIGEST_LEN+key_out_len; key_material = tor_malloc(key_material_len); - len = crypto_dh_compute_secret(dh, challenge, DH_KEY_LEN, - key_material, key_material_len); + len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge, + DH_KEY_LEN, key_material, + key_material_len); if (len < 0) { log_info(LD_GENERAL, "crypto_dh_compute_secret failed."); goto err; @@ -304,8 +316,9 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state, key_material_len = DIGEST_LEN + key_out_len; key_material = tor_malloc(key_material_len); - len = crypto_dh_compute_secret(handshake_state, handshake_reply, DH_KEY_LEN, - key_material, key_material_len); + len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state, + handshake_reply, DH_KEY_LEN, key_material, + key_material_len); if (len < 0) goto err; diff --git a/src/or/onion.h b/src/or/onion.h new file mode 100644 index 0000000000..e097dcdbb3 --- /dev/null +++ b/src/or/onion.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file onion.h + * \brief Header file for onion.c. + **/ + +#ifndef _TOR_ONION_H +#define _TOR_ONION_H + +int onion_pending_add(or_circuit_t *circ, char *onionskin); +or_circuit_t *onion_next_task(char **onionskin_out); +void onion_pending_remove(or_circuit_t *circ); + +int onion_skin_create(crypto_pk_env_t *router_key, + crypto_dh_env_t **handshake_state_out, + char *onion_skin_out); + +int onion_skin_server_handshake(const char *onion_skin, + crypto_pk_env_t *private_key, + crypto_pk_env_t *prev_private_key, + char *handshake_reply_out, + char *key_out, + size_t key_out_len); + +int onion_skin_client_handshake(crypto_dh_env_t *handshake_state, + const char *handshake_reply, + char *key_out, + size_t key_out_len); + +int fast_server_handshake(const uint8_t *key_in, + uint8_t *handshake_reply_out, + uint8_t *key_out, + size_t key_out_len); + +int fast_client_handshake(const uint8_t *handshake_state, + const uint8_t *handshake_reply_out, + uint8_t *key_out, + size_t key_out_len); + +void clear_pending_onions(void); + +#endif + diff --git a/src/or/or.h b/src/or/or.h index 2a251187fa..07b73ec9b7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -20,9 +20,6 @@ #ifndef INSTRUMENT_DOWNLOADS #define INSTRUMENT_DOWNLOADS 1 #endif -#ifndef ENABLE_GEOIP_STATS -#define ENABLE_GEOIP_STATS 1 -#endif #endif #ifdef MS_WINDOWS @@ -62,6 +59,9 @@ #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif @@ -83,16 +83,13 @@ #define snprintf _snprintf #endif -#include "crypto.h" #include "tortls.h" -#include "log.h" -#include "compat.h" +#include "../common/torlog.h" #include "container.h" -#include "util.h" #include "torgzip.h" #include "address.h" - -#include <event.h> +#include "compat_libevent.h" +#include "ht.h" /* These signals are defined to help control_signal_act work. */ @@ -161,7 +158,7 @@ #define MAX_DNS_TTL (3*60*60) /** How small can a TTL be before we stop believing it? Provides rudimentary * pinning. */ -#define MIN_DNS_TTL (60) +#define MIN_DNS_TTL 60 /** How often do we rotate onion keys? */ #define MIN_ONION_KEY_LIFETIME (7*24*60*60) @@ -221,6 +218,21 @@ typedef enum { /* !!!! If _CONN_TYPE_MAX is ever over 15, we must grow the type field in * connection_t. */ +/* Proxy client types */ +#define PROXY_NONE 0 +#define PROXY_CONNECT 1 +#define PROXY_SOCKS4 2 +#define PROXY_SOCKS5 3 + +/* 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 + /** True iff <b>x</b> is an edge connection. */ #define CONN_IS_EDGE(x) \ ((x)->type == CONN_TYPE_EXIT || (x)->type == CONN_TYPE_AP) @@ -241,26 +253,24 @@ typedef enum { #define _OR_CONN_STATE_MIN 1 /** State for a connection to an OR: waiting for connect() to finish. */ #define OR_CONN_STATE_CONNECTING 1 -/** State for a connection to an OR: waiting for proxy command to flush. */ -#define OR_CONN_STATE_PROXY_FLUSHING 2 -/** State for a connection to an OR: waiting for proxy response. */ -#define OR_CONN_STATE_PROXY_READING 3 +/** 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 * yet. */ -#define OR_CONN_STATE_TLS_HANDSHAKING 4 +#define OR_CONN_STATE_TLS_HANDSHAKING 3 /** State for a connection to an OR: We're doing a second SSL handshake for * renegotiation purposes. */ -#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 5 +#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4 /** State for a connection at an OR: We're waiting for the client to * renegotiate. */ -#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 6 +#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 7 +#define OR_CONN_STATE_OR_HANDSHAKING 6 /** State for a connection to an OR: Ready to send/receive cells. */ -#define OR_CONN_STATE_OPEN 8 -#define _OR_CONN_STATE_MAX 8 +#define OR_CONN_STATE_OPEN 7 +#define _OR_CONN_STATE_MAX 7 #define _EXIT_CONN_STATE_MIN 1 /** State for an exit connection: waiting for response from DNS farm. */ @@ -457,23 +467,23 @@ typedef enum { #define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 11 /** Client-side circuit purpose: at Alice, rendezvous established. */ #define CIRCUIT_PURPOSE_C_REND_JOINED 12 - -#define _CIRCUIT_PURPOSE_C_MAX 12 - +/** This circuit is used for build time measurement only */ +#define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 13 +#define _CIRCUIT_PURPOSE_C_MAX 13 /** Hidden-service-side circuit purpose: at Bob, waiting for introductions. */ -#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 13 +#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 14 /** Hidden-service-side circuit purpose: at Bob, successfully established * intro. */ -#define CIRCUIT_PURPOSE_S_INTRO 14 +#define CIRCUIT_PURPOSE_S_INTRO 15 /** Hidden-service-side circuit purpose: at Bob, connecting to rend point. */ -#define CIRCUIT_PURPOSE_S_CONNECT_REND 15 +#define CIRCUIT_PURPOSE_S_CONNECT_REND 16 /** Hidden-service-side circuit purpose: at Bob, rendezvous established. */ -#define CIRCUIT_PURPOSE_S_REND_JOINED 16 +#define CIRCUIT_PURPOSE_S_REND_JOINED 17 /** A testing circuit; not meant to be used for actual traffic. */ -#define CIRCUIT_PURPOSE_TESTING 17 +#define CIRCUIT_PURPOSE_TESTING 18 /** A controller made this circuit and Tor should not use it. */ -#define CIRCUIT_PURPOSE_CONTROLLER 18 -#define _CIRCUIT_PURPOSE_MAX 18 +#define CIRCUIT_PURPOSE_CONTROLLER 19 +#define _CIRCUIT_PURPOSE_MAX 19 /** A catch-all for unrecognized purposes. Currently we don't expect * to make or see any circuits with this purpose. */ #define CIRCUIT_PURPOSE_UNKNOWN 255 @@ -483,7 +493,7 @@ typedef enum { #define CIRCUIT_PURPOSE_IS_ORIGIN(p) ((p)>_CIRCUIT_PURPOSE_OR_MAX) /** True iff the circuit purpose <b>p</b> is for a circuit that originated * here to serve as a client. (Hidden services don't count here.) */ -#define CIRCUIT_PURPOSE_IS_CLIENT(p) \ +#define CIRCUIT_PURPOSE_IS_CLIENT(p) \ ((p)> _CIRCUIT_PURPOSE_OR_MAX && \ (p)<=_CIRCUIT_PURPOSE_C_MAX) /** True iff the circuit_t <b>c</b> is actually an origin_circuit_t. */ @@ -604,6 +614,10 @@ typedef enum { /* Negative reasons are internal: we never send them in a DESTROY or TRUNCATE * call; they only go to the controller for tracking */ +/** Our post-timeout circuit time measurement period expired. + * We must give up now */ +#define END_CIRC_REASON_MEASUREMENT_EXPIRED -3 + /** We couldn't build a path for this circuit. */ #define END_CIRC_REASON_NOPATH -2 /** Catch-all "other" reason for closing origin circuits. */ @@ -641,10 +655,6 @@ typedef enum { /** Length of a binary-encoded rendezvous service ID. */ #define REND_SERVICE_ID_LEN 10 -/** How long after we receive a hidden service descriptor do we consider - * it fresh? */ -#define NUM_SECONDS_BEFORE_HS_REFETCH (60*15) - /** Time period for which a v2 descriptor will be valid. */ #define REND_TIME_PERIOD_V2_DESC_VALIDITY (24*60*60) @@ -739,12 +749,6 @@ typedef struct rend_data_t { /** Rendezvous cookie used by both, client and service. */ char rend_cookie[REND_COOKIE_LEN]; - - /** Rendezvous descriptor version that is used by a service. Used to - * distinguish introduction and rendezvous points belonging to the same - * rendezvous service ID, but different descriptor versions. - */ - uint8_t rend_desc_version; } rend_data_t; /** Time interval for tracking possible replays of INTRODUCE2 cells. @@ -851,12 +855,28 @@ typedef struct packed_cell_t { char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */ } packed_cell_t; +/** Number of cells added to a circuit queue including their insertion + * time on 10 millisecond detail; used for buffer statistics. */ +typedef struct insertion_time_elem_t { + struct insertion_time_elem_t *next; /**< Next element in queue. */ + uint32_t insertion_time; /**< When were cells inserted (in 10 ms steps + * starting at 0:00 of the current day)? */ + unsigned counter; /**< How many cells were inserted? */ +} insertion_time_elem_t; + +/** Queue of insertion times. */ +typedef struct insertion_time_queue_t { + struct insertion_time_elem_t *first; /**< First element in queue. */ + struct insertion_time_elem_t *last; /**< Last element in queue. */ +} insertion_time_queue_t; + /** A queue of cells on a circuit, waiting to be added to the * or_connection_t's outbuf. */ typedef struct cell_queue_t { packed_cell_t *head; /**< The first cell, or NULL if the queue is empty. */ packed_cell_t *tail; /**< The last cell, or NULL if the queue is empty. */ int n; /**< The number of cells in the queue. */ + insertion_time_queue_t *insertion_times; /**< Insertion times of cells. */ } cell_queue_t; /** Beginning of a RELAY cell payload. */ @@ -912,7 +932,7 @@ typedef struct connection_t { * again once the bandwidth throttler allows it? */ unsigned int write_blocked_on_bw:1; /**< Boolean: should we start writing * again once the bandwidth throttler allows - * reads? */ + * writes? */ unsigned int hold_open_until_flushed:1; /**< Despite this connection's being * marked for close, do we flush it * before closing it? */ @@ -937,8 +957,11 @@ typedef struct connection_t { * connection. */ unsigned int linked_conn_is_closed:1; - int s; /**< Our socket; -1 if this connection is closed, or has no - * socket. */ + /** CONNECT/SOCKS proxy client handshake state (for outgoing connections). */ + unsigned int proxy_state:4; + + /** Our socket; -1 if this connection is closed, or has no socket. */ + evutil_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. */ @@ -980,6 +1003,8 @@ typedef struct connection_t { * to the evdns_server_port is 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; /** Stores flags and information related to the portion of a v2 Tor OR @@ -1026,7 +1051,10 @@ typedef struct or_connection_t { * NETINFO cell listed the address we're connected to as recognized. */ unsigned int is_canonical:1; /** True iff this connection shouldn't get any new circs attached to it, - * because the connection is too old, or because there's a better one, etc. + * because the connection is too old, or because there's a better one. + * More generally, this flag is used to note an unhealthy connection; + * for example, if a bad connection fails we shouldn't assume that the + * router itself has a problem. */ unsigned int is_bad_for_new_circs:1; uint8_t link_proto; /**< What protocol version are we using? 0 for @@ -1041,12 +1069,13 @@ typedef struct or_connection_t { time_t timestamp_last_added_nonpadding; /** When did we last add a * non-padding cell to the outbuf? */ - /* bandwidth* and read_bucket only used by ORs in OPEN state: */ + /* 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.) */ 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. */ int n_circuits; /**< How many circuits use this connection as p_conn or * n_conn ? */ @@ -1054,6 +1083,17 @@ typedef struct or_connection_t { * free up on this connection's outbuf. Every time we pull cells from a * circuit, we advance this pointer to the next circuit in the ring. */ struct circuit_t *active_circuits; + /** Priority queue of cell_ewma_t for circuits with queued cells waiting for + * room to free up on this connection's outbuf. Kept in heap order + * according to EWMA. + * + * This is redundant with active_circuits; if we ever decide only to use the + * cell_ewma algorithm for choosing circuits, we can remove active_circuits. + */ + smartlist_t *active_circuit_pqueue; + /** The tick on which the cell_ewma_ts in active_circuit_pqueue last had + * their ewma values rescaled. */ + unsigned active_circuit_pqueue_last_recalibrated; struct or_connection_t *next_with_same_id; /**< Next connection with same * identity digest as this one. */ } or_connection_t; @@ -1150,7 +1190,8 @@ typedef struct dir_connection_t { enum { DIR_SPOOL_NONE=0, DIR_SPOOL_SERVER_BY_DIGEST, DIR_SPOOL_SERVER_BY_FP, DIR_SPOOL_EXTRA_BY_DIGEST, DIR_SPOOL_EXTRA_BY_FP, - DIR_SPOOL_CACHED_DIR, DIR_SPOOL_NETWORKSTATUS + DIR_SPOOL_CACHED_DIR, DIR_SPOOL_NETWORKSTATUS, + DIR_SPOOL_MICRODESC, /* NOTE: if we add another entry, add another bit. */ } dir_spool_src : 3; /** If we're fetching descriptors, what router purpose shall we assign * to them? */ @@ -1178,12 +1219,6 @@ typedef struct control_connection_t { uint32_t event_mask; /**< Bitfield: which events does this controller * care about? */ - unsigned int use_long_names:1; /**< True if we should use long nicknames - * on this (v1) connection. Only settable - * via v1 controllers. */ - /** For control connections only. If set, we send extended info with control - * events as appropriate. */ - unsigned int use_extended_events:1; /** True if we have sent a protocolinfo reply on this connection. */ unsigned int have_sent_protocolinfo:1; @@ -1267,6 +1302,7 @@ typedef struct cached_dir_t { size_t dir_len; /**< Length of <b>dir</b> (not counting its NUL). */ size_t dir_z_len; /**< Length of <b>dir_z</b>. */ time_t published; /**< When was this object published. */ + digests_t digests; /**< Digests of this object (networkstatus only) */ int refcnt; /**< Reference count for this cached_dir_t. */ } cached_dir_t; @@ -1427,6 +1463,9 @@ typedef struct { * 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. */ #define ROUTER_PURPOSE_GENERAL 0 @@ -1516,6 +1555,9 @@ typedef struct routerstatus_t { unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */ unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */ + unsigned int has_measured_bw:1; /**< The vote/consensus had a measured bw */ + + uint32_t measured_bw; /**< Measured bandwidth (capacity) of the router */ uint32_t bandwidth; /**< Bandwidth (capacity) of the router as reported in * the vote/consensus, in kilobytes/sec. */ @@ -1540,6 +1582,52 @@ typedef struct routerstatus_t { } routerstatus_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 + * self-signed, but are rather authenticated by having their hash in a signed + * networkstatus document. */ +typedef struct microdesc_t { + /** Hashtable node, used to look up the microdesc by its digest. */ + HT_ENTRY(microdesc_t) node; + + /* Cache information */ + + /** When was this microdescriptor last listed in a consensus document? + * Once a microdesc has been unlisted long enough, we can drop it. + */ + time_t last_listed; + /** Where is this microdescriptor currently stored? */ + saved_location_t saved_location : 3; + /** If true, do not attempt to cache this microdescriptor on disk. */ + unsigned int no_save : 1; + /** If saved_location == SAVED_IN_CACHE, this field holds the offset of the + * microdescriptor in the cache. */ + off_t off; + + /* The string containing the microdesc. */ + + /** A pointer to the encoded body of the microdescriptor. If the + * saved_location is SAVED_IN_CACHE, then the body is a pointer into an + * mmap'd region. Otherwise, it is a malloc'd string. The string might not + * be NUL-terminated; take the length from <b>bodylen</b>. */ + char *body; + /** The length of the microdescriptor in <b>body</b>. */ + size_t bodylen; + /** A SHA256-digest of the microdescriptor. */ + char digest[DIGEST256_LEN]; + + /* Fields in the microdescriptor. */ + + /** As routerinfo_t.onion_pkey */ + 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. */ +} microdesc_t; + /** How many times will we try to download a router's descriptor before giving * up? */ #define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8 @@ -1582,6 +1670,11 @@ typedef struct networkstatus_v2_t { * sorted by identity_digest. */ } networkstatus_v2_t; +typedef struct vote_microdesc_hash_t { + struct vote_microdesc_hash_t *next; + char *microdesc_hash_line; +} vote_microdesc_hash_t; + /** The claim about a single router, made in a vote. */ typedef struct vote_routerstatus_t { routerstatus_t status; /**< Underlying 'status' object for this router. @@ -1590,31 +1683,45 @@ typedef struct vote_routerstatus_t { * networkstatus_t.known_flags. */ char *version; /**< The version that the authority says this router is * running. */ + vote_microdesc_hash_t *microdesc; } vote_routerstatus_t; +/** A signature of some document by an authority. */ +typedef struct document_signature_t { + /** Declared SHA-1 digest of this voter's identity key */ + char identity_digest[DIGEST_LEN]; + /** Declared SHA-1 digest of signing key used by this voter. */ + char signing_key_digest[DIGEST_LEN]; + /** Algorithm used to compute the digest of the document. */ + digest_algorithm_t alg; + /** Signature of the signed thing. */ + char *signature; + /** Length of <b>signature</b> */ + int signature_len; + unsigned int bad_signature : 1; /**< Set to true if we've tried to verify + * the sig, and we know it's bad. */ + unsigned int good_signature : 1; /**< Set to true if we've verified the sig + * as good. */ +} document_signature_t; + /** Information about a single voter in a vote or a consensus. */ typedef struct networkstatus_voter_info_t { + /** Declared SHA-1 digest of this voter's identity key */ + char identity_digest[DIGEST_LEN]; char *nickname; /**< Nickname of this voter */ - char identity_digest[DIGEST_LEN]; /**< Digest of this voter's identity key */ + /** Digest of this voter's "legacy" identity key, if any. In vote only; for + * consensuses, we treat legacy keys as additional signers. */ + char legacy_id_digest[DIGEST_LEN]; char *address; /**< Address of this voter, in string format. */ uint32_t addr; /**< Address of this voter, in IPv4, in host order. */ uint16_t dir_port; /**< Directory port of this voter */ uint16_t or_port; /**< OR port of this voter */ char *contact; /**< Contact information for this voter. */ char vote_digest[DIGEST_LEN]; /**< Digest of this voter's vote, as signed. */ - /** Digest of this voter's "legacy" identity key, if any. In vote only; for - * consensuses, we treat legacy keys as additional signers. */ - char legacy_id_digest[DIGEST_LEN]; /* Nothing from here on is signed. */ - char signing_key_digest[DIGEST_LEN]; /**< Declared digest of signing key - * used by this voter. */ - char *signature; /**< Signature from this voter. */ - int signature_len; /**< Length of <b>signature</b> */ - unsigned int bad_signature : 1; /**< Set to true if we've tried to verify - * the sig, and we know it's bad. */ - unsigned int good_signature : 1; /**< Set to true if we've verified the sig - * as good. */ + /** The signature of the document and the signature's status. */ + smartlist_t *sigs; } networkstatus_voter_info_t; /** Enumerates the possible seriousness values of a networkstatus document. */ @@ -1624,10 +1731,25 @@ typedef enum { NS_TYPE_OPINION, } networkstatus_type_t; +/** Enumerates recognized flavors of a consensus networkstatus document. All + * flavors of a consensus are generated from the same set of votes, but they + * present different types information to different versions of Tor. */ +typedef enum { + FLAV_NS = 0, + 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) + /** A common structure to hold a v3 network status vote, or a v3 network * status consensus. */ typedef struct networkstatus_t { - networkstatus_type_t type; /**< Vote, consensus, or opinion? */ + networkstatus_type_t type : 8; /**< Vote, consensus, or opinion? */ + consensus_flavor_t flavor : 8; /**< If a consensus, what kind? */ time_t published; /**< Vote only: Time when vote was written. */ time_t valid_after; /**< Time after which this vote or consensus applies. */ time_t fresh_until; /**< Time before which this is the most recent vote or @@ -1659,6 +1781,10 @@ typedef struct networkstatus_t { * consensus, sorted by key. */ smartlist_t *net_params; + /** List of key=value strings for the bw weight parameters in the + * consensus. */ + smartlist_t *weight_params; + /** List of networkstatus_voter_info_t. For a vote, only one element * is included. For a consensus, one element is included for every voter * whose vote contributed to the consensus. */ @@ -1666,8 +1792,8 @@ typedef struct networkstatus_t { struct authority_cert_t *cert; /**< Vote only: the voter's certificate. */ - /** Digest of this document, as signed. */ - char networkstatus_digest[DIGEST_LEN]; + /** Digests of this document, as signed. */ + digests_t digests; /** List of router statuses, sorted by identity digest. For a vote, * the elements are vote_routerstatus_t; for a consensus, the elements @@ -1679,14 +1805,15 @@ typedef struct networkstatus_t { digestmap_t *desc_digest_map; } networkstatus_t; -/** A set of signatures for a networkstatus consensus. All fields are as for - * networkstatus_t. */ +/** A set of signatures for a networkstatus consensus. Unless otherwise + * noted, all fields are as for networkstatus_t. */ typedef struct ns_detached_signatures_t { time_t valid_after; time_t fresh_until; time_t valid_until; - char networkstatus_digest[DIGEST_LEN]; - smartlist_t *signatures; /* list of networkstatus_voter_info_t */ + strmap_t *digests; /**< Map from flavor name to digestset_t */ + strmap_t *signatures; /**< Map from flavor name to list of + * document_signature_t */ } ns_detached_signatures_t; /** Allowable types of desc_store_t. */ @@ -1891,6 +2018,29 @@ typedef struct { time_t expiry_time; } cpath_build_state_t; +/** + * The cell_ewma_t structure keeps track of how many cells a circuit has + * transferred recently. It keeps an EWMA (exponentially weighted moving + * average) of the number of cells flushed from the circuit queue onto a + * connection in connection_or_flush_from_first_active_circuit(). + */ +typedef struct { + /** The last 'tick' at which we recalibrated cell_count. + * + * A cell sent at exactly the start of this tick has weight 1.0. Cells sent + * since the start of this tick have weight greater than 1.0; ones sent + * earlier have less weight. */ + unsigned last_adjusted_tick; + /** The EWMA of the cell count. */ + double cell_count; + /** True iff this is the cell count for a circuit's previous + * connection. */ + unsigned int is_for_p_conn : 1; + /** The position of the circuit within the OR connection's priority + * queue. */ + int heap_index; +} cell_ewma_t; + #define ORIGIN_CIRCUIT_MAGIC 0x35315243u #define OR_CIRCUIT_MAGIC 0x98ABC04Fu @@ -1960,6 +2110,7 @@ typedef struct circuit_t { time_t timestamp_created; /**< When was this circuit created? */ time_t timestamp_dirty; /**< When the circuit was first used, or 0 if the * circuit is clean. */ + struct timeval highres_created; /**< When exactly was the circuit created? */ uint16_t marked_for_close; /**< Should we close this circuit at the end of * the main loop? (If true, holds the line number @@ -1976,6 +2127,14 @@ typedef struct circuit_t { * linked to an OR connection. */ struct circuit_t *prev_active_on_n_conn; struct circuit_t *next; /**< Next circuit in linked list of all circuits. */ + + /** Unique ID for measuring tunneled network status requests. */ + uint64_t dirreq_id; + + /** The EWMA count for the number of cells flushed from the + * n_conn_cells queue. Used to determine which circuit to flush from next. + */ + cell_ewma_t n_cell_ewma; } circuit_t; /** Largest number of relay_early cells that we can send on a given @@ -2008,6 +2167,13 @@ typedef struct origin_circuit_t { * to the specification? */ unsigned int remaining_relay_early_cells : 4; + /** Set if this circuit is insanely old and we already informed the user */ + unsigned int is_ancient : 1; + + /** Set if this circuit has already been opened. Used to detect + * cannibalized circuits. */ + unsigned int has_opened : 1; + /** What commands were sent over this circuit that decremented the * RELAY_EARLY counter? This is for debugging task 878. */ uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT]; @@ -2098,6 +2264,19 @@ typedef struct or_circuit_t { /** True iff this circuit was made with a CREATE_FAST cell. */ unsigned int is_first_hop : 1; + + /** Number of cells that were removed from circuit queue; reset every + * time when writing buffer stats to disk. */ + uint32_t processed_cells; + + /** Total time in milliseconds that cells spent in both app-ward and + * exit-ward queues of this circuit; reset every time when writing + * buffer stats to disk. */ + uint64_t total_cell_waiting_time; + + /** The EWMA count for the number of cells flushed from the + * p_conn_cells queue. */ + cell_ewma_t p_cell_ewma; } or_circuit_t; /** Convert a circuit subtype to a circuit_t.*/ @@ -2169,13 +2348,13 @@ typedef struct { routerset_t *EntryNodes;/**< Structure containing nicknames, digests, * country codes and IP address patterns of ORs to * consider as entry points. */ - int StrictExitNodes; /**< Boolean: When none of our ExitNodes are up, do we - * stop building circuits? */ - int StrictEntryNodes; /**< Boolean: When none of our EntryNodes are up, do we - * stop building circuits? */ + int StrictNodes; /**< Boolean: When none of our EntryNodes or ExitNodes + * are up, or we need to access a node in ExcludeNodes, + * do we just fail instead? */ routerset_t *ExcludeNodes;/**< Structure containing nicknames, digests, * country codes and IP address patterns of ORs - * not to use in circuits. */ + * not to use in circuits. But see StrictNodes + * above. */ routerset_t *ExcludeExitNodes;/**< Structure containing nicknames, digests, * country codes and IP address patterns of * ORs not to consider as exits. */ @@ -2183,6 +2362,9 @@ typedef struct { /** Union of ExcludeNodes and ExcludeExitNodes */ struct routerset_t *_ExcludeExitNodesUnion; + int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our + * process for all current and future memory. */ + /** List of "entry", "middle", "exit", "introduction", "rendezvous". */ smartlist_t *AllowInvalidNodes; /** Bitmask; derived from AllowInvalidNodes. */ @@ -2197,7 +2379,7 @@ typedef struct { * connections. */ config_line_t *TransListenAddress; /** Addresses to bind for listening for transparent natd connections */ - config_line_t *NatdListenAddress; + config_line_t *NATDListenAddress; /** Addresses to bind for listening for SOCKS connections. */ config_line_t *DNSListenAddress; /** Addresses to bind for listening for OR connections. */ @@ -2221,7 +2403,7 @@ typedef struct { 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. */ + int NATDPort; /**< Port 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. */ @@ -2237,8 +2419,6 @@ typedef struct { * for version 3 directories? */ int HSAuthoritativeDir; /**< Boolean: does this an authoritative directory * handle hidden service requests? */ - int HSAuthorityRecordStats; /**< Boolean: does this HS authoritative - * directory record statistics? */ int NamingAuthoritativeDir; /**< Boolean: is this an authoritative directory * that's willing to bind names? */ int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative @@ -2267,8 +2447,6 @@ typedef struct { int AvoidDiskWrites; /**< Boolean: should we never cache things to disk? * Not used yet. */ int ClientOnly; /**< Boolean: should we never evolve into a server role? */ - /** Boolean: should we never publish a descriptor? Deprecated. */ - int NoPublish; /** To what authority types do we publish our descriptor? Choices are * "v1", "v2", "v3", "bridge", or "". */ smartlist_t *PublishServerDescriptor; @@ -2299,6 +2477,14 @@ typedef struct { int ConstrainedSockets; /**< Shrink xmit and recv socket buffers. */ 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 + * what the consensus says, defaulting to 'refuse' if the consensus says + * nothing). */ + char *RefuseUnknownExits; + /** Parsed version of RefuseUnknownExits. -1 for auto. */ + int RefuseUnknownExits_; + /** Application ports that require all nodes in circ to have sufficient * uptime. */ smartlist_t *LongLivedPorts; @@ -2328,10 +2514,18 @@ typedef struct { * connections alive? */ int SocksTimeout; /**< How long do we let a socks connection wait * unattached before we fail it? */ - int CircuitBuildTimeout; /**< Cull non-open circuits that were born - * at least this many seconds ago. */ + int LearnCircuitBuildTimeout; /**< If non-zero, we attempt to learn a value + * for CircuitBuildTimeout based on timeout + * history */ + int CircuitBuildTimeout; /**< Cull non-open circuits that were born at + * least this many seconds ago. Used until + * adaptive algorithm learns a new value. */ int CircuitIdleTimeout; /**< Cull open clean circuits that were born * at least this many seconds ago. */ + int CircuitStreamTimeout; /**< If non-zero, detach streams from circuits + * and try a new circuit if the stream has been + * waiting for this many seconds. If zero, use + * our default internal timeout schedule. */ int MaxOnionsPending; /**< How many circuit CREATE requests do we allow * to wait simultaneously before we start dropping * them? */ @@ -2349,24 +2543,36 @@ typedef struct { * willing to use for all relayed conns? */ uint64_t RelayBandwidthBurst; /**< How much bandwidth, at maximum, will we * use in a second for all relayed conns? */ - int NumCpus; /**< How many CPUs should we try to use? */ - int RunTesting; /**< If true, create testing circuits to measure how well the - * other ORs are running. */ + uint64_t PerConnBWRate; /**< Long-term bw on a single TLS conn, if set. */ + uint64_t PerConnBWBurst; /**< Allowed burst on a single TLS conn, if set. */ + int NumCPUs; /**< How many CPUs should we try to use? */ +//int RunTesting; /**< If true, create testing circuits to measure how well the +// * other ORs are running. */ config_line_t *RendConfigLines; /**< List of configuration lines * for rendezvous services. */ config_line_t *HidServAuth; /**< List of configuration lines for client-side * authorizations for hidden services */ char *ContactInfo; /**< Contact info to be published in the directory. */ - char *HttpProxy; /**< hostname[:port] to use as http proxy, if any. */ - uint32_t HttpProxyAddr; /**< Parsed IPv4 addr for http proxy, if any. */ - uint16_t HttpProxyPort; /**< Parsed port for http proxy, if any. */ - char *HttpProxyAuthenticator; /**< username:password string, if any. */ + 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. */ + char *HTTPProxyAuthenticator; /**< username:password string, if any. */ + + char *HTTPSProxy; /**< hostname[:port] to use as https proxy, if any. */ + tor_addr_t HTTPSProxyAddr; /**< Parsed addr for https proxy, if any. */ + uint16_t HTTPSProxyPort; /**< Parsed port for https proxy, if any. */ + char *HTTPSProxyAuthenticator; /**< username:password string, if any. */ - char *HttpsProxy; /**< hostname[:port] to use as https proxy, if any. */ - uint32_t HttpsProxyAddr; /**< Parsed IPv4 addr for https proxy, if any. */ - uint16_t HttpsProxyPort; /**< Parsed port for https proxy, if any. */ - char *HttpsProxyAuthenticator; /**< username:password string, if any. */ + char *Socks4Proxy; /**< hostname:port to use as a SOCKS4 proxy, if any. */ + tor_addr_t Socks4ProxyAddr; /**< Derived from Socks4Proxy. */ + uint16_t Socks4ProxyPort; /**< Derived from Socks4Proxy. */ + + char *Socks5Proxy; /**< hostname:port to use as a SOCKS5 proxy, if any. */ + tor_addr_t Socks5ProxyAddr; /**< Derived from Sock5Proxy. */ + uint16_t Socks5ProxyPort; /**< Derived from Socks5Proxy. */ + char *Socks5ProxyUsername; /**< Username for SOCKS5 authentication, if any */ + char *Socks5ProxyPassword; /**< Password for SOCKS5 authentication, if any */ /** List of configuration lines for replacement directory authorities. * If you just want to replace one class of authority at a time, @@ -2429,8 +2635,13 @@ typedef struct { * or not (1)? */ int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how * long do we wait before exiting? */ - int SafeLogging; /**< Boolean: are we allowed to log sensitive strings - * such as addresses (0), or do we scrub them first (1)? */ + char *SafeLogging; /**< Contains "relay", "1", "0" (meaning no scrubbing). */ + + /* Derived from SafeLogging */ + enum { + SAFELOG_SCRUB_ALL, SAFELOG_SCRUB_RELAY, SAFELOG_SCRUB_NONE + } _SafeLogging; + int SafeSocks; /**< Boolean: should we outright refuse application * connections that use socks4 or socks5-with-local-dns? */ #define LOG_PROTOCOL_WARN (get_options()->ProtocolWarnings ? \ @@ -2441,6 +2652,8 @@ typedef struct { * log whether it was DNS-leaking or not? */ int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware * acceleration where available? */ + 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 * of fixed nodes? */ int NumEntryGuards; /**< How many entry guards do we try to establish? */ @@ -2451,6 +2664,9 @@ typedef struct { * means directly from the authorities) no matter our other config? */ int FetchDirInfoEarly; + /** Should we fetch our dir info at the start of the consensus period? */ + int FetchDirInfoExtraEarly; + char *VirtualAddrNetwork; /**< Address and mask to hand out for virtual * MAPADDRESS requests. */ int ServerDNSSearchDomains; /**< Boolean: If set, we don't force exit @@ -2499,6 +2715,33 @@ typedef struct { * exit allows it, we use it. */ int AllowSingleHopCircuits; + /** If true, we convert "www.google.com.foo.exit" addresses on the + * socks/trans/natd ports into "www.google.com" addresses that + * exit from the node "foo". Disabled by default since attacking + * websites and exit relays can use it to manipulate your path + * selection. */ + int AllowDotExit; + + /** If true, we will warn if a user gives us only an IP address + * instead of a hostname. */ + int WarnUnsafeSocks; + + /** If true, the user wants us to collect statistics on clients + * requesting network statuses from us as directory. */ + int DirReqStatistics; + + /** If true, the user wants us to collect statistics on port usage. */ + int ExitPortStatistics; + + /** If true, the user wants us to collect cell statistics. */ + int CellStatistics; + + /** If true, the user wants us to collect statistics as entry node. */ + int EntryStatistics; + + /** If true, include statistics file contents in extra-info documents. */ + int ExtraInfoStatistics; + /** If true, do not believe anybody who tells us that a domain resolves * to an internal address, or that an internal address has a PTR mapping. * Helps avoid some cross-site attacks. */ @@ -2517,6 +2760,13 @@ typedef struct { * migration purposes? */ int V3AuthUseLegacyKey; + /** Location of bandwidth measurement file */ + char *V3BandwidthsFile; + + /** Authority only: key=value pairs that we add to our networkstatus + * consensus vote on the 'params' line. */ + char *ConsensusParams; + /** The length of time that we think an initial consensus should be fresh. * Only altered on testing networks. */ int TestingV3AuthInitialVotingInterval; @@ -2553,19 +2803,6 @@ typedef struct { * the bridge authority guess which countries have blocked access to us. */ int BridgeRecordUsageByCountry; -#ifdef ENABLE_GEOIP_STATS - /** If true, and Tor is built with GEOIP_STATS support, and we're a - * directory, record how many directory requests we get from each country. */ - int DirRecordUsageByCountry; - /** Round all GeoIP results to the next multiple of this value, to avoid - * leaking information. */ - int DirRecordUsageGranularity; - /** Time interval: purge geoip stats after this long. */ - int DirRecordUsageRetainIPs; - /** Time interval: Flush geoip data to disk this often. */ - int DirRecordUsageSaveInterval; -#endif - /** Optionally, a file with GeoIP data. */ char *GeoIPFile; @@ -2573,6 +2810,21 @@ typedef struct { * to make this false. */ int ReloadTorrcOnSIGHUP; + /* The main parameter for picking circuits within a connection. + * + * If this value is positive, when picking a cell to relay on a connection, + * we always relay from the circuit whose weighted cell count is lowest. + * Cells are weighted exponentially such that if one cell is sent + * 'CircuitPriorityHalflife' seconds before another, it counts for half as + * much. + * + * If this value is zero, we're disabling the cell-EWMA algorithm. + * + * If this value is negative, we're using the default approach + * according to either Tor or a parameter set in the consensus. + */ + double CircuitPriorityHalflife; + } or_options_t; /** Persistent state for an onion router, as saved to disk. */ @@ -2591,6 +2843,9 @@ typedef struct { uint64_t AccountingBytesReadInInterval; uint64_t AccountingBytesWrittenInInterval; int AccountingSecondsActive; + int AccountingSecondsToReachSoftLimit; + time_t AccountingSoftLimitHitAt; + uint64_t AccountingBytesAtSoftLimit; uint64_t AccountingExpectedUsage; /** A list of Entry Guard-related configuration lines. */ @@ -2608,6 +2863,17 @@ typedef struct { time_t BWHistoryWriteEnds; int BWHistoryWriteInterval; smartlist_t *BWHistoryWriteValues; + time_t BWHistoryDirReadEnds; + int BWHistoryDirReadInterval; + smartlist_t *BWHistoryDirReadValues; + time_t BWHistoryDirWriteEnds; + int BWHistoryDirWriteInterval; + smartlist_t *BWHistoryDirWriteValues; + + /** Build time histogram */ + config_line_t * BuildtimeHistogram; + unsigned int TotalBuildTimes; + unsigned int CircuitBuildAbandonedCount; /** What version of Tor wrote this state file? */ char *TorVersion; @@ -2669,209 +2935,120 @@ struct socks_request_t { /* all the function prototypes go here */ -/********************************* buffers.c ***************************/ - -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); -void buf_shrink(buf_t *buf); -void buf_shrink_freelists(int free_all); -void buf_dump_freelist_sizes(int severity); - -size_t buf_datalen(const buf_t *buf); -size_t buf_allocation(const buf_t *buf); -size_t buf_slack(const buf_t *buf); -const char *_buf_peek_raw_buffer(const buf_t *buf); - -int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof, - int *socket_error); -int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf); - -int flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen); -int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen); - -int write_to_buf(const char *string, size_t string_len, buf_t *buf); -int write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state, - const char *data, size_t data_len, int done); -int move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen); -int fetch_from_buf(char *string, size_t string_len, buf_t *buf); -int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto); -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); -int fetch_from_buf_socks(buf_t *buf, socks_request_t *req, - int log_sockstype, int safe_socks); -int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len); - -int peek_buf_has_control0_command(buf_t *buf); - -void assert_buf_ok(buf_t *buf); - -#ifdef BUFFERS_PRIVATE -int buf_find_string_offset(const buf_t *buf, const char *s, size_t n); -#endif - /********************************* circuitbuild.c **********************/ -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, - origin_circuit_t *circ); -void circuit_rep_hist_note_result(origin_circuit_t *circ); -origin_circuit_t *origin_circuit_init(uint8_t purpose, int flags); -origin_circuit_t *circuit_establish_circuit(uint8_t purpose, - extend_info_t *exit, - int flags); -int circuit_handle_first_hop(origin_circuit_t *circ); -void circuit_n_conn_done(or_connection_t *or_conn, int status); -int inform_testing_reachability(void); -int circuit_send_next_onion_skin(origin_circuit_t *circ); -void circuit_note_clock_jumped(int seconds_elapsed); -int circuit_extend(cell_t *cell, circuit_t *circ); -int circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data, - int reverse); -int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type, - const uint8_t *reply); -int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer); -int onionskin_answer(or_circuit_t *circ, uint8_t cell_type, - const char *payload, const char *keys); -int circuit_all_predicted_ports_handled(time_t now, int *need_uptime, - int *need_capacity); - -int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info); -int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info); -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_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 char *build_state_get_exit_nickname(cpath_build_state_t *state); - -void entry_guards_compute_status(void); -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_can_grow(or_options_t *options); -routerinfo_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, - const char *question, char **answer); - -void clear_bridge_list(void); -int routerinfo_is_a_configured_bridge(routerinfo_t *ri); -void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, - char *digest); -void retry_bridge_descriptor_fetch_directly(const char *digest); -void fetch_bridge_descriptors(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 bridges_known_but_down(void); -void bridges_retry_all(void); - -void entry_guards_free_all(void); - -/********************************* circuitlist.c ***********************/ - -circuit_t * _circuit_get_global_list(void); -const char *circuit_state_to_string(int state); -const char *circuit_purpose_to_controller_string(uint8_t purpose); -void circuit_dump_by_conn(connection_t *conn, int severity); -void circuit_set_p_circid_orconn(or_circuit_t *circ, circid_t id, - or_connection_t *conn); -void circuit_set_n_circid_orconn(circuit_t *circ, circid_t id, - or_connection_t *conn); -void circuit_set_state(circuit_t *circ, uint8_t state); -void circuit_close_all_marked(void); -int32_t circuit_initial_package_window(void); -origin_circuit_t *origin_circuit_new(void); -or_circuit_t *or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn); -circuit_t *circuit_get_by_circid_orconn(circid_t circ_id, - or_connection_t *conn); -int circuit_id_in_use_on_orconn(circid_t circ_id, or_connection_t *conn); -circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn); -void circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason); -origin_circuit_t *circuit_get_by_global_id(uint32_t id); -origin_circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, - uint8_t purpose); -origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, - const char *digest, uint8_t purpose); -or_circuit_t *circuit_get_rendezvous(const char *cookie); -or_circuit_t *circuit_get_intro_point(const char *digest); -origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose, - extend_info_t *info, int flags); -void circuit_mark_all_unused_circs(void); -void circuit_expire_all_dirty_circs(void); -void _circuit_mark_for_close(circuit_t *circ, int reason, - int line, const char *file); -int circuit_get_cpath_len(origin_circuit_t *circ); -crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum); -void circuit_get_all_pending_on_or_conn(smartlist_t *out, - or_connection_t *or_conn); -int circuit_count_pending_on_or_conn(or_connection_t *or_conn); - -#define circuit_mark_for_close(c, reason) \ - _circuit_mark_for_close((c), (reason), __LINE__, _SHORT_FILE_) - -void assert_cpath_layer_ok(const crypt_path_t *cp); -void assert_circuit_ok(const circuit_t *c); -void circuit_free_all(void); - -/********************************* circuituse.c ************************/ - -void circuit_expire_building(time_t now); -void circuit_remove_handled_ports(smartlist_t *needed_ports); -int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, - int min); -int circuit_conforms_to_options(const origin_circuit_t *circ, - const or_options_t *options); -void circuit_build_needed_circs(time_t now); -void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn); - -void circuit_expire_old_circuits_serverside(time_t now); - -void reset_bandwidth_test(void); -int circuit_enough_testing_circs(void); - -void circuit_has_opened(origin_circuit_t *circ); -void circuit_build_failed(origin_circuit_t *circ); - -/** Flag to set when a circuit should have only a single hop. */ -#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0) -/** Flag to set when a circuit needs to be built of high-uptime nodes */ -#define CIRCLAUNCH_NEED_UPTIME (1<<1) -/** Flag to set when a circuit needs to be built of high-capacity nodes */ -#define CIRCLAUNCH_NEED_CAPACITY (1<<2) -/** Flag to set when the last hop of a circuit doesn't need to be an - * exit node. */ -#define CIRCLAUNCH_IS_INTERNAL (1<<3) -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); -void circuit_reset_failure_count(int timeout); -int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, - origin_circuit_t *circ, - crypt_path_t *cpath); -int connection_ap_handshake_attach_circuit(edge_connection_t *conn); - -/********************************* command.c ***************************/ - -void command_process_cell(cell_t *cell, or_connection_t *conn); -void command_process_var_cell(var_cell_t *cell, or_connection_t *conn); - -extern uint64_t stats_n_padding_cells_processed; -extern uint64_t stats_n_create_cells_processed; -extern uint64_t stats_n_created_cells_processed; -extern uint64_t stats_n_relay_cells_processed; -extern uint64_t stats_n_destroy_cells_processed; +/** How many hops does a general-purpose circuit have by default? */ +#define DEFAULT_ROUTE_LEN 3 + +/* Circuit Build Timeout "public" structures. */ + +/** Total size of the circuit timeout history to accumulate. + * 1000 is approx 2.5 days worth of continual-use circuits. */ +#define CBT_NCIRCUITS_TO_OBSERVE 1000 + +/** Width of the histogram bins in milliseconds */ +#define CBT_BIN_WIDTH ((build_time_t)50) + +/** Number of modes to use in the weighted-avg computation of Xm */ +#define CBT_DEFAULT_NUM_XM_MODES 3 + +/** A build_time_t is milliseconds */ +typedef uint32_t build_time_t; + +/** + * CBT_BUILD_ABANDONED is our flag value to represent a force-closed + * circuit (Aka a 'right-censored' pareto value). + */ +#define CBT_BUILD_ABANDONED ((build_time_t)(INT32_MAX-1)) +#define CBT_BUILD_TIME_MAX ((build_time_t)(INT32_MAX)) + +/** Save state every 10 circuits */ +#define CBT_SAVE_STATE_EVERY 10 + +/* Circuit build times consensus parameters */ + +/** + * How long to wait before actually closing circuits that take too long to + * build in terms of CDF quantile. + */ +#define CBT_DEFAULT_CLOSE_QUANTILE 95 + +/** + * How many circuits count as recent when considering if the + * connection has gone gimpy or changed. + */ +#define CBT_DEFAULT_RECENT_CIRCUITS 20 + +/** + * Maximum count of timeouts that finish the first hop in the past + * RECENT_CIRCUITS before calculating a new timeout. + * + * This tells us whether to abandon timeout history and set + * the timeout back to whatever circuit_build_times_get_initial_timeout() + * gives us. + */ +#define CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT (CBT_DEFAULT_RECENT_CIRCUITS*9/10) + +/** Minimum circuits before estimating a timeout */ +#define CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE 100 + +/** Cutoff percentile on the CDF for our timeout estimation. */ +#define CBT_DEFAULT_QUANTILE_CUTOFF 80 +double circuit_build_times_quantile_cutoff(void); + +/** How often in seconds should we build a test circuit */ +#define CBT_DEFAULT_TEST_FREQUENCY 60 + +/** Lowest allowable value for CircuitBuildTimeout in milliseconds */ +#define CBT_DEFAULT_TIMEOUT_MIN_VALUE (1500) + +/** Initial circuit build timeout in milliseconds */ +#define CBT_DEFAULT_TIMEOUT_INITIAL_VALUE (60*1000) +int32_t circuit_build_times_initial_timeout(void); + +#if CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT < 1 +#error "RECENT_CIRCUITS is set too low." +#endif + +/** Information about the state of our local network connection */ +typedef struct { + /** The timestamp we last completed a TLS handshake or received a cell */ + time_t network_last_live; + /** If the network is not live, how many timeouts has this caused? */ + int nonlive_timeouts; + /** Circular array of circuits that have made it to the first hop. Slot is + * 1 if circuit timed out, 0 if circuit succeeded */ + int8_t *timeouts_after_firsthop; + /** Number of elements allocated for the above array */ + int num_recent_circs; + /** Index into circular array. */ + int after_firsthop_idx; +} network_liveness_t; + +/** Structure for circuit build times history */ +typedef struct { + /** The circular array of recorded build times in milliseconds */ + build_time_t circuit_build_times[CBT_NCIRCUITS_TO_OBSERVE]; + /** Current index in the circuit_build_times circular array */ + int build_times_idx; + /** Total number of build times accumulated. Max CBT_NCIRCUITS_TO_OBSERVE */ + int total_build_times; + /** Information about the state of our local network connection */ + network_liveness_t liveness; + /** Last time we built a circuit. Used to decide to build new test circs */ + time_t last_circ_at; + /** "Minimum" value of our pareto distribution (actually mode) */ + build_time_t Xm; + /** alpha exponent for pareto dist. */ + double alpha; + /** Have we computed a timeout? */ + int have_computed_timeout; + /** The exact value for that timeout in milliseconds. Stored as a double + * to maintain precision from calculations to and from quantile value. */ + double timeout_ms; + /** How long we wait before actually closing the circuit. */ + double close_ms; +} circuit_build_times_t; /********************************* config.c ***************************/ @@ -2884,203 +3061,8 @@ typedef enum setopt_err_t { SETOPT_ERR_SETTING = -4, } setopt_err_t; -const char *get_dirportfrontpage(void); -or_options_t *get_options(void); -int set_options(or_options_t *new_val, char **msg); -void config_free_all(void); -const char *safe_str(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); -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, - uint32_t *addr, char **hostname_out); -int is_local_addr(const tor_addr_t *addr) ATTR_PURE; -void options_init(or_options_t *options); -int options_init_from_torrc(int argc, char **argv); -setopt_err_t options_init_from_string(const char *cf, - int command, const char *command_arg, char **msg); -int option_is_recognized(const char *key); -const char *option_get_canonical_name(const char *key); -config_line_t *option_get_assignment(or_options_t *options, - 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 *sub1, const char *sub2, - const char *suffix); -#define get_datadir_fname2_suffix(sub1, sub2, suffix) \ - options_get_datadir_fname2_suffix(get_options(), (sub1), (sub2), (suffix)) -/** Return a newly allocated string containing datadir/sub1. See - * get_datadir_fname2_suffix. */ -#define get_datadir_fname(sub1) get_datadir_fname2_suffix((sub1), NULL, NULL) -/** Return a newly allocated string containing datadir/sub1/sub2. See - * get_datadir_fname2_suffix. */ -#define get_datadir_fname2(sub1,sub2) \ - get_datadir_fname2_suffix((sub1), (sub2), NULL) -/** Return a newly allocated string containing datadir/sub1suffix. See - * get_datadir_fname2_suffix. */ -#define get_datadir_fname_suffix(sub1, suffix) \ - get_datadir_fname2_suffix((sub1), NULL, (suffix)) - -or_state_t *get_or_state(void); -int or_state_save(time_t now); - -int options_need_geoip_info(or_options_t *options, const char **reason_out); -int getinfo_helper_config(control_connection_t *conn, - const char *question, char **answer); - -uint32_t get_effective_bwrate(or_options_t *options); -uint32_t get_effective_bwburst(or_options_t *options); - -#ifdef CONFIG_PRIVATE -/* Used only by config.c and test.c */ -or_options_t *options_new(void); -#endif - -/********************************* connection.c ***************************/ - -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); -control_connection_t *control_connection_new(int socket_family); -connection_t *connection_new(int type, int socket_family); - -void connection_link_connections(connection_t *conn_a, connection_t *conn_b); -void connection_unregister_events(connection_t *conn); -void connection_free(connection_t *conn); -void connection_free_all(void); -void connection_about_to_close_connection(connection_t *conn); -void connection_close_immediate(connection_t *conn); -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_) - -void connection_expire_held_open(void); - -int connection_connect(connection_t *conn, const char *address, - const tor_addr_t *addr, - uint16_t port, int *socket_error); -int retry_all_listeners(smartlist_t *replaced_conns, - smartlist_t *new_conns); - -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); -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_wants_to_flush(connection_t *conn); -int connection_outbuf_too_full(connection_t *conn); -int connection_handle_write(connection_t *conn, int force); -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, - connection_t *conn); -static void connection_write_to_buf_zlib(const char *string, size_t len, - dir_connection_t *conn, int done); -static INLINE void -connection_write_to_buf(const char *string, size_t len, connection_t *conn) -{ - _connection_write_to_buf_impl(string, len, conn, 0); -} -static INLINE void -connection_write_to_buf_zlib(const char *string, size_t len, - dir_connection_t *conn, int done) -{ - _connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1); -} - -connection_t *connection_get_by_global_id(uint64_t id); - -connection_t *connection_get_by_type(int type); -connection_t *connection_get_by_type_purpose(int type, int purpose); -connection_t *connection_get_by_type_addr_port_purpose(int type, - const tor_addr_t *addr, - uint16_t port, int purpose); -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, - int rendversion); - -#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR) -int connection_is_listener(connection_t *conn); -int connection_state_is_open(connection_t *conn); -int connection_state_is_connecting(connection_t *conn); - -char *alloc_http_authenticator(const char *authenticator); - -void assert_connection_ok(connection_t *conn, time_t now); -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); - /********************************* connection_edge.c *************************/ -#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, - int line, const char *file); -int connection_edge_reached_eof(edge_connection_t *conn); -int connection_edge_process_inbuf(edge_connection_t *conn, - int package_partial); -int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn); -int connection_edge_end(edge_connection_t *conn, uint8_t reason); -int connection_edge_end_errno(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); - -edge_connection_t *connection_ap_make_link(char *address, uint16_t port, - const char *digest, - int use_begindir, int want_onehop); -void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, - size_t replylen, - int endreason); -void connection_ap_handshake_socks_resolved(edge_connection_t *conn, - int answer_type, - size_t answer_len, - const uint8_t *answer, - int ttl, - time_t expires); - -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); -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, - origin_circuit_t *circ, - int reason); -int connection_ap_process_transparent(edge_connection_t *conn); - -int address_is_invalid_destination(const char *address, int client); - -void addressmap_init(void); -void addressmap_clean(time_t now); -void addressmap_clear_configured(void); -void addressmap_clear_transient(void); -void addressmap_free_all(void); -int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out); -int addressmap_have_mapping(const char *address, int update_timeout); /** Enumerates possible origins of a client-side address mapping. */ typedef enum { /** We're remapping this address because the controller told us to. */ @@ -3095,75 +3077,6 @@ typedef enum { * Tor server that told us what its value was. */ ADDRMAPSRC_DNS, } addressmap_entry_source_t; -void addressmap_register(const char *address, char *new_address, - time_t expires, addressmap_entry_source_t source); -int parse_virtual_addr_network(const char *val, int validate_only, - char **msg); -int client_dns_incr_failures(const char *address); -void client_dns_clear_failures(const char *address); -void client_dns_set_addressmap(const char *address, uint32_t val, - const char *exitname, int ttl); -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_handshake_rewrite_and_attach(edge_connection_t *conn, - origin_circuit_t *circ, - crypt_path_t *cpath); -int hostname_is_noconnect_address(const char *address); - -/** Possible return values for parse_extended_hostname. */ -typedef enum hostname_type_t { - NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME, BAD_HOSTNAME -} hostname_type_t; -hostname_type_t parse_extended_hostname(char *address); - -#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) -int get_pf_socket(void); -#endif - -/********************************* connection_or.c ***************************/ - -void connection_or_remove_from_identity_map(or_connection_t *conn); -void connection_or_clear_identity_map(void); -or_connection_t *connection_or_get_for_extend(const char *digest, - const tor_addr_t *target_addr, - const char **msg_out, - int *launch_out); -void connection_or_set_bad_connections(void); - -int connection_or_reached_eof(or_connection_t *conn); -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_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); - -int connection_tls_start_handshake(or_connection_t *conn, int receiving); -int connection_tls_continue_handshake(or_connection_t *conn); - -void or_handshake_state_free(or_handshake_state_t *state); -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); -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_netinfo(or_connection_t *conn); -int connection_or_send_cert(or_connection_t *conn); -int connection_or_send_link_auth(or_connection_t *conn); -int connection_or_compute_link_auth_hmac(or_connection_t *conn, - char *hmac_out); -int is_or_protocol_version_known(uint16_t version); - -void cell_pack(packed_cell_t *dest, const cell_t *src); -void var_cell_pack_header(const var_cell_t *cell, char *hdr_out); -var_cell_t *var_cell_new(uint16_t payload_len); -void var_cell_free(var_cell_t *cell); /********************************* control.c ***************************/ @@ -3201,8 +3114,14 @@ typedef enum or_conn_status_event_t { OR_CONN_EVENT_NEW = 4, } or_conn_status_event_t; -void control_update_global_event_mask(void); -void control_adjust_event_log_severity(void); +/** Used to indicate the type of a buildtime event */ +typedef enum buildtimeout_set_event_t { + BUILDTIMEOUT_SET_EVENT_COMPUTED = 0, + BUILDTIMEOUT_SET_EVENT_RESET = 1, + BUILDTIMEOUT_SET_EVENT_SUSPENDED = 2, + BUILDTIMEOUT_SET_EVENT_DISCARD = 3, + BUILDTIMEOUT_SET_EVENT_RESUME = 4 +} buildtimeout_set_event_t; /** Execute the statement <b>stmt</b>, which may log events concerning the * connection <b>conn</b>. To prevent infinite loops, disable log messages @@ -3220,58 +3139,6 @@ void control_adjust_event_log_severity(void); enable_control_logging(); \ STMT_END -/** Log information about the connection <b>conn</b>, protecting it as with - * CONN_LOG_PROTECT. Example: - * - * LOG_FN_CONN(conn, (LOG_DEBUG, "Socket %d wants to write", conn->s)); - **/ -#define LOG_FN_CONN(conn, args) \ - CONN_LOG_PROTECT(conn, log_fn args) - -int connection_control_finished_flushing(control_connection_t *conn); -int connection_control_reached_eof(control_connection_t *conn); -int connection_control_process_inbuf(control_connection_t *conn); - -#define EVENT_AUTHDIR_NEWDESCS 0x000D -#define EVENT_NS 0x000F -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, - stream_status_event_t e, - int reason); -int control_event_or_conn_status(or_connection_t *conn, - or_conn_status_event_t e, int reason); -int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written); -int control_event_stream_bandwidth(edge_connection_t *edge_conn); -int control_event_stream_bandwidth_used(void); -void control_event_logmsg(int severity, unsigned int domain, const char *msg); -int control_event_descriptors_changed(smartlist_t *routers); -int control_event_address_mapped(const char *from, const char *to, - time_t expires, const char *error); -int control_event_or_authdir_new_descriptor(const char *action, - const char *desc, - size_t desclen, - const char *msg); -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_general_status(int severity, const char *format, ...) - CHECK_PRINTF(2,3); -int control_event_client_status(int severity, const char *format, ...) - CHECK_PRINTF(2,3); -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 init_cookie_authentication(int enabled); -smartlist_t *decode_hashed_passwords(config_line_t *passwords); -void disable_control_logging(void); -void enable_control_logging(void); - /** Enum describing various stages of bootstrapping, for use with controller * bootstrap status events. The values range from 0 to 100. */ typedef enum { @@ -3292,252 +3159,30 @@ typedef enum { BOOTSTRAP_STATUS_DONE=100 } bootstrap_status_t; -void control_event_bootstrap(bootstrap_status_t status, int progress); -void control_event_bootstrap_problem(const char *warn, int reason); - -void control_event_clients_seen(const char *timestarted, - const char *countries); - -#ifdef CONTROL_PRIVATE -/* Used only by control.c and test.c */ -size_t write_escaped_data(const char *data, size_t len, char **out); -size_t read_escaped_data(const char *data, size_t len, char **out); -#endif - -/********************************* cpuworker.c *****************************/ - -void cpu_init(void); -void cpuworkers_rotate(void); -int connection_cpu_finished_flushing(connection_t *conn); -int connection_cpu_reached_eof(connection_t *conn); -int connection_cpu_process_inbuf(connection_t *conn); -int assign_onionskin_to_cpuworker(connection_t *cpuworker, - or_circuit_t *circ, - char *onionskin); - /********************************* directory.c ***************************/ -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, - size_t payload_len, size_t extrainfo_len); -void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, - const char *resource, - int pds_flags); -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, - uint8_t dir_purpose, - uint8_t router_purpose, - int anonymized_connection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since); -void directory_initiate_command_routerstatus_rend(routerstatus_t *status, - uint8_t dir_purpose, - uint8_t router_purpose, - int anonymized_connection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since, - const rend_data_t *rend_query); - -int parse_http_response(const char *headers, int *code, time_t *date, - compress_method_t *compression, char **response); - -int connection_dir_is_encrypted(dir_connection_t *conn); -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 directory_initiate_command(const char *address, const tor_addr_t *addr, - uint16_t or_port, uint16_t dir_port, - int supports_conditional_consensus, - int supports_begindir, const char *digest, - uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, - const char *resource, - const char *payload, size_t payload_len, - time_t if_modified_since); - -int dir_split_resource_into_fingerprints(const char *resource, - smartlist_t *fp_out, int *compresseed_out, - int decode_hex, int sort_uniq); /** A pair of digests created by dir_split_resource_info_fingerprint_pairs() */ typedef struct { char first[DIGEST_LEN]; char second[DIGEST_LEN]; } fp_pair_t; -int dir_split_resource_into_fingerprint_pairs(const char *res, - smartlist_t *pairs_out); -char *directory_dump_request_log(void); -void note_request(const char *key, size_t bytes); -int router_supports_extrainfo(const char *identity_digest, int is_authority); - -time_t download_status_increment_failure(download_status_t *dls, - int status_code, const char *item, - int server, time_t now); -/** Increment the failure count of the download_status_t <b>dls</b>, with - * the optional status code <b>sc</b>. */ -#define download_status_failed(dls, sc) \ - download_status_increment_failure((dls), (sc), NULL, \ - get_options()->DirPort, time(NULL)) - -void download_status_reset(download_status_t *dls); -static int download_status_is_ready(download_status_t *dls, time_t now, - int max_failures); -/** Return true iff, as of <b>now</b>, the resource tracked by <b>dls</b> is - * ready to get its download reattempted. */ -static INLINE int -download_status_is_ready(download_status_t *dls, time_t now, - int max_failures) -{ - return (dls->n_download_failures <= max_failures - && dls->next_attempt_at <= now); -} - -static void download_status_mark_impossible(download_status_t *dl); -/** Mark <b>dl</b> as never downloadable. */ -static INLINE void -download_status_mark_impossible(download_status_t *dl) -{ - dl->n_download_failures = IMPOSSIBLE_TO_DOWNLOAD; -} /********************************* dirserv.c ***************************/ -/** Maximum length of an exit policy summary. */ -#define MAX_EXITPOLICY_SUMMARY_LEN (1000) - -/** Maximum allowable length of a version line in a networkstatus. */ -#define MAX_V_LINE_LEN 128 -/** Length of "r Authority BadDirectory BadExit Exit Fast Guard HSDir Named - * Running Stable Unnamed V2Dir Valid\n". */ -#define MAX_FLAG_LINE_LEN 96 -/** Length of "w" line for weighting. Currently at most - * "w Bandwidth=<uint32t>\n" */ -#define MAX_WEIGHT_LINE_LEN (13+10) -/** Maximum length of an exit policy summary line. */ -#define MAX_POLICY_LINE_LEN (3+MAX_EXITPOLICY_SUMMARY_LEN) -/** Amount of space to allocate for each entry: r, s, and v lines. */ -#define RS_ENTRY_LEN \ - ( /* first line */ \ - MAX_NICKNAME_LEN+BASE64_DIGEST_LEN*2+ISO_TIME_LEN+INET_NTOA_BUF_LEN+ \ - 5*2 /* ports */ + 10 /* punctuation */ + \ - /* second line */ \ - MAX_FLAG_LINE_LEN + \ - /* weight line */ \ - MAX_WEIGHT_LINE_LEN + \ - /* p line. */ \ - MAX_POLICY_LINE_LEN + \ - /* v line. */ \ - 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); -int dirserv_load_fingerprint_file(void); -void dirserv_free_fingerprint_list(void); -const char *dirserv_get_nickname_by_digest(const char *digest); -enum was_router_added_t dirserv_add_multiple_descriptors( - const char *desc, uint8_t purpose, - const char *source, - const char **msg); -enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri, - const char **msg, - const char *source); -int getinfo_helper_dirserv_unregistered(control_connection_t *conn, - const char *question, char **answer); -void dirserv_free_descriptors(void); -void dirserv_set_router_is_running(routerinfo_t *router, time_t now); -int list_server_status_v1(smartlist_t *routers, char **router_status_out, - int for_controller); -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); -#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); - -void directory_set_dirty(void); -cached_dir_t *dirserv_get_directory(void); -cached_dir_t *dirserv_get_runningrouters(void); -cached_dir_t *dirserv_get_consensus(void); -void dirserv_set_cached_directory(const char *directory, time_t when, - int is_running_routers); -void dirserv_set_cached_networkstatus_v2(const char *directory, - const char *identity, - time_t published); -void dirserv_set_cached_networkstatus_v3(const char *consensus, - time_t published); -void dirserv_clear_old_networkstatuses(time_t cutoff); -void dirserv_clear_old_v1_info(time_t now); -void dirserv_get_networkstatus_v2(smartlist_t *result, const char *key); -void dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, - const char *key); -int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, - const char **msg, - int for_unencrypted_conn, - int is_extrainfo); -int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, - const char **msg); -void dirserv_orconn_tls_done(const char *address, - uint16_t or_port, - const char *digest_rcvd, - int as_advertised); -void dirserv_test_reachability(time_t now, int try_all); -int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, - int complain); -int dirserv_would_reject_router(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); -size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs, - int compressed); -int routerstatus_format_entry(char *buf, size_t buf_len, - routerstatus_t *rs, const char *platform, - int first_line_only, int v2_format); -void dirserv_free_all(void); -void cached_dir_decref(cached_dir_t *d); -cached_dir_t *new_cached_dir(char *s, time_t published); +typedef enum { + NS_V2, NS_V3_CONSENSUS, NS_V3_VOTE, NS_CONTROL_PORT, + NS_V3_CONSENSUS_MICRODESC +} routerstatus_format_type_t; -/********************************* dirvote.c ************************/ +#ifdef DIRSERV_PRIVATE +typedef struct measured_bw_line_t { + char node_id[DIGEST_LEN]; + char node_hex[MAX_HEX_NICKNAME_LEN+1]; + long int bw; +} measured_bw_line_t; + +#endif -/** Lowest allowable value for VoteSeconds. */ -#define MIN_VOTE_SECONDS 20 -/** Lowest allowable value for DistSeconds. */ -#define MIN_DIST_SECONDS 20 -/** Smallest allowable voting interval. */ -#define MIN_VOTE_INTERVAL 300 - -void dirvote_free_all(void); - -/* vote manipulation */ -char *networkstatus_compute_consensus(smartlist_t *votes, - int total_authorities, - crypto_pk_env_t *identity_key, - crypto_pk_env_t *signing_key, - const char *legacy_identity_key_digest, - crypto_pk_env_t *legacy_signing_key); -int networkstatus_add_detached_signatures(networkstatus_t *target, - ns_detached_signatures_t *sigs, - const char **msg_out); -char *networkstatus_get_detached_signatures(networkstatus_t *consensus); -void ns_detached_signatures_free(ns_detached_signatures_t *s); - -/* cert manipulation */ -authority_cert_t *authority_cert_dup(authority_cert_t *cert); +/********************************* dirvote.c ************************/ /** Describes the schedule by which votes should be generated. */ typedef struct vote_timing_t { @@ -3546,173 +3191,85 @@ typedef struct vote_timing_t { int vote_delay; int dist_delay; } vote_timing_t; -/* 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); - -/* invoked on timers and by outside triggers. */ -struct pending_vote_t * dirvote_add_vote(const char *vote_body, - const char **msg_out, - int *status_out); -int dirvote_add_signatures(const char *detached_signatures_body, - const char *source, - const char **msg_out); - -/* Item access */ -const char *dirvote_get_pending_consensus(void); -const char *dirvote_get_pending_detached_signatures(void); -#define DGV_BY_ID 1 -#define DGV_INCLUDE_PENDING 2 -#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, - routerinfo_t *ri, time_t now, - int naming, int exits_can_be_guards, - int listbadexits, int listbaddirs); -void router_clear_status_flags(routerinfo_t *ri); -networkstatus_t * -dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, - authority_cert_t *cert); - -#ifdef DIRVOTE_PRIVATE -char *format_networkstatus_vote(crypto_pk_env_t *private_key, - networkstatus_t *v3_ns); -char *dirvote_compute_params(smartlist_t *votes); -#endif - -/********************************* dns.c ***************************/ - -int dns_init(void); -int has_dns_init_failed(void); -void dns_free_all(void); -uint32_t dns_clip_ttl(uint32_t ttl); -int dns_reset(void); -void connection_dns_remove(edge_connection_t *conn); -void assert_connection_edge_not_dns_pending(edge_connection_t *conn); -void assert_all_pending_dns_resolves_ok(void); -void dns_cancel_pending_resolve(const char *question); -int dns_resolve(edge_connection_t *exitconn); -void dns_launch_correctness_checks(void); -int dns_seems_to_be_broken(void); -void dns_reset_correctness_checks(void); - -/********************************* dnsserv.c ************************/ - -void dnsserv_configure_listener(connection_t *conn); -void dnsserv_close_listener(connection_t *conn); -void dnsserv_resolved(edge_connection_t *conn, - int answer_type, - size_t answer_len, - const char *answer, - int ttl); -void dnsserv_reject_request(edge_connection_t *conn); -int dnsserv_launch_request(const char *name, int is_reverse); /********************************* geoip.c **************************/ -#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 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); -country_t geoip_get_country(const char *countrycode); +/** Round all GeoIP results to the next multiple of this value, to avoid + * leaking information. */ +#define DIR_RECORD_USAGE_GRANULARITY 8 +/** Time interval: Flush geoip data to disk this often. */ +#define DIR_ENTRY_RECORD_USAGE_RETAIN_IPS (24*60*60) +/** How long do we have to have observed per-country request history before + * we are willing to talk about it? */ +#define DIR_RECORD_USAGE_MIN_OBSERVATION_TIME (12*60*60) + /** Indicates an action that we might be noting geoip statistics on. * Note that if we're noticing CONNECT, we're a bridge, and if we're noticing * the others, we're not. */ typedef enum { - /** We've noticed a connection as a bridge relay. */ + /** We've noticed a connection as a bridge relay or entry guard. */ GEOIP_CLIENT_CONNECT = 0, /** We've served a networkstatus consensus as a directory server. */ GEOIP_CLIENT_NETWORKSTATUS = 1, /** We've served a v2 networkstatus consensus as a directory server. */ GEOIP_CLIENT_NETWORKSTATUS_V2 = 2, } geoip_client_action_t; -void geoip_note_client_seen(geoip_client_action_t action, - uint32_t addr, time_t now); -void geoip_remove_old_clients(time_t cutoff); -time_t geoip_get_history_start(void); -char *geoip_get_client_history(time_t now, geoip_client_action_t action); -char *geoip_get_request_history(time_t now, geoip_client_action_t action); -int getinfo_helper_geoip(control_connection_t *control_conn, - const char *question, char **answer); -void geoip_free_all(void); -void dump_geoip_stats(void); - -/********************************* hibernate.c **********************/ - -int accounting_parse_options(or_options_t *options, int validate_only); -int accounting_is_enabled(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); -int accounting_record_bandwidth_usage(time_t now, or_state_t *state); -void hibernate_begin_shutdown(void); -int we_are_hibernating(void); -void consider_hibernation(time_t now); -int getinfo_helper_accounting(control_connection_t *conn, - const char *question, char **answer); -void accounting_set_bandwidth_usage_from_state(or_state_t *state); - -/********************************* main.c ***************************/ - -extern int has_completed_circuit; - -int connection_add(connection_t *conn); -int connection_remove(connection_t *conn); -int connection_in_array(connection_t *conn); -void add_connection_to_closeable_list(connection_t *conn); -int connection_is_on_closeable_list(connection_t *conn); - -smartlist_t *get_connection_array(void); - -void connection_watch_events(connection_t *conn, short events); -int connection_is_reading(connection_t *conn); -void connection_stop_reading(connection_t *conn); -void connection_start_reading(connection_t *conn); - -int connection_is_writing(connection_t *conn); -void connection_stop_writing(connection_t *conn); -void connection_start_writing(connection_t *conn); - -void connection_stop_reading_from_linked_conn(connection_t *conn); - -void directory_all_unreachable(time_t now); -void directory_info_has_arrived(time_t now, int from_cache); - -void ip_address_changed(int at_interface); -void dns_servers_relaunch_checks(void); - -void control_signal_act(int the_signal); -void handle_signals(int is_parent); - -int try_locking(or_options_t *options, int err_if_locked); -int have_lockfile(void); -void release_lockfile(void); - -void tor_cleanup(void); -void tor_free_all(int postfork); - -int tor_main(int argc, char *argv[]); - -#ifdef MAIN_PRIVATE -int do_main_loop(void); -int do_list_fingerprint(void); -void do_hash_password(void); -int tor_init(int argc, char **argv); -#endif +/** Indicates either a positive reply or a reason for rejectng a network + * status request that will be included in geoip statistics. */ +typedef enum { + /** Request is answered successfully. */ + GEOIP_SUCCESS = 0, + /** V3 network status is not signed by a sufficient number of requested + * authorities. */ + GEOIP_REJECT_NOT_ENOUGH_SIGS = 1, + /** Requested network status object is unavailable. */ + GEOIP_REJECT_UNAVAILABLE = 2, + /** Requested network status not found. */ + GEOIP_REJECT_NOT_FOUND = 3, + /** Network status has not been modified since If-Modified-Since time. */ + GEOIP_REJECT_NOT_MODIFIED = 4, + /** Directory is busy. */ + GEOIP_REJECT_BUSY = 5, +} geoip_ns_response_t; +#define GEOIP_NS_RESPONSE_NUM 6 + +/** Directory requests that we are measuring can be either direct or + * tunneled. */ +typedef enum { + DIRREQ_DIRECT = 0, + DIRREQ_TUNNELED = 1, +} dirreq_type_t; -/********************************* networkstatus.c *********************/ +/** Possible states for either direct or tunneled directory requests that + * are relevant for determining network status download times. */ +typedef enum { + /** Found that the client requests a network status; applies to both + * direct and tunneled requests; initial state of a request that we are + * measuring. */ + DIRREQ_IS_FOR_NETWORK_STATUS = 0, + /** Finished writing a network status to the directory connection; + * applies to both direct and tunneled requests; completes a direct + * request. */ + DIRREQ_FLUSHING_DIR_CONN_FINISHED = 1, + /** END cell sent to circuit that initiated a tunneled request. */ + DIRREQ_END_CELL_SENT = 2, + /** Flushed last cell from queue of the circuit that initiated a + * tunneled request to the outbuf of the OR connection. */ + DIRREQ_CIRC_QUEUE_FLUSHED = 3, + /** Flushed last byte from buffer of the OR connection belonging to the + * circuit that initiated a tunneled request; completes a tunneled + * request. */ + DIRREQ_OR_CONN_BUFFER_FLUSHED = 4 +} dirreq_state_t; + +#define WRITE_STATS_INTERVAL (24*60*60) + +/********************************* microdesc.c *************************/ + +typedef struct microdesc_cache_t microdesc_cache_t; -/** How old do we allow a v2 network-status to get before removing it - * completely? */ -#define MAX_NETWORKSTATUS_AGE (10*24*60*60) +/********************************* networkstatus.c *********************/ /** Location where we found a v2 networkstatus. */ typedef enum { @@ -3733,127 +3290,8 @@ typedef enum version_status_t { VS_UNKNOWN, /**< We have no idea. */ } version_status_t; -void networkstatus_reset_warnings(void); -void networkstatus_reset_download_failures(void); -int router_reload_v2_networkstatus(void); -int router_reload_consensus_networkstatus(void); -void routerstatus_free(routerstatus_t *rs); -void networkstatus_v2_free(networkstatus_v2_t *ns); -void networkstatus_vote_free(networkstatus_t *ns); -networkstatus_voter_info_t *networkstatus_get_voter_by_id( - networkstatus_t *vote, - const char *identity); -int networkstatus_check_consensus_signature(networkstatus_t *consensus, - int warn); -int networkstatus_check_voter_signature(networkstatus_t *consensus, - networkstatus_voter_info_t *voter, - authority_cert_t *cert); -char *networkstatus_get_cache_filename(const char *identity_digest); -int router_set_networkstatus_v2(const char *s, time_t arrived_at, - v2_networkstatus_source_t source, - smartlist_t *requested_fingerprints); -void networkstatus_v2_list_clean(time_t now); -routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns, - const char *digest); -routerstatus_t *networkstatus_vote_find_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 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 update_consensus_networkstatus_fetch_time(time_t now); -int should_delay_dir_fetches(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_live_consensus(time_t now); -networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now); -#define NSSET_FROM_CACHE 1 -#define NSSET_WAS_WAITING_FOR_CERTS 2 -#define NSSET_DONT_DOWNLOAD_CERTS 4 -#define NSSET_ACCEPT_OBSOLETE 8 -int networkstatus_set_current_consensus(const char *consensus, unsigned flags); -void networkstatus_note_certs_arrived(void); -void routers_update_all_from_networkstatus(time_t now, int dir_version); -void routerstatus_list_update_from_consensus_networkstatus(time_t now); -void routers_update_status_from_consensus_networkstatus(smartlist_t *routers, - int reset_failures); -void signed_descs_update_status_from_consensus_networkstatus( - smartlist_t *descs); - -char *networkstatus_getinfo_helper_single(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 default_val); -int getinfo_helper_networkstatus(control_connection_t *conn, - const char *question, char **answer); -void networkstatus_free_all(void); - -/********************************* ntmain.c ***************************/ -#ifdef MS_WINDOWS -#define NT_SERVICE -#endif - -#ifdef NT_SERVICE -int nt_service_parse_options(int argc, char **argv, int *should_exit); -int nt_service_is_stopping(void); -void nt_service_set_state(DWORD state); -#else -#define nt_service_is_stopping() (0) -#endif - -/********************************* onion.c ***************************/ - -int onion_pending_add(or_circuit_t *circ, char *onionskin); -or_circuit_t *onion_next_task(char **onionskin_out); -void onion_pending_remove(or_circuit_t *circ); - -int onion_skin_create(crypto_pk_env_t *router_key, - crypto_dh_env_t **handshake_state_out, - char *onion_skin_out); - -int onion_skin_server_handshake(const char *onion_skin, - crypto_pk_env_t *private_key, - crypto_pk_env_t *prev_private_key, - char *handshake_reply_out, - char *key_out, - size_t key_out_len); - -int onion_skin_client_handshake(crypto_dh_env_t *handshake_state, - const char *handshake_reply, - char *key_out, - size_t key_out_len); - -int fast_server_handshake(const uint8_t *key_in, - uint8_t *handshake_reply_out, - uint8_t *key_out, - size_t key_out_len); - -int fast_client_handshake(const uint8_t *handshake_state, - const uint8_t *handshake_reply_out, - uint8_t *key_out, - size_t key_out_len); - -void clear_pending_onions(void); - /********************************* policies.c ************************/ -/* (length of "accept 255.255.255.255/255.255.255.255:65535-65535\n" plus a - * NUL.) - */ -#define POLICY_BUF_LEN 52 - /** Outcome of applying an address policy to an address. */ typedef enum { /** The address was accepted */ @@ -3868,146 +3306,8 @@ typedef enum { ADDR_POLICY_PROBABLY_REJECTED=2 } addr_policy_result_t; -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_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); -int authdir_policy_permits_address(uint32_t addr, uint16_t port); -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); -void policy_expand_private(smartlist_t **policy); -int policies_parse_from_options(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); -int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, - int rejectprivate, const char *local_address); -void policies_set_router_exitpolicy_to_reject_all(routerinfo_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, - const char *question, char **answer); -int policy_write_item(char *buf, size_t buflen, addr_policy_t *item, - int format_for_desc); - -void addr_policy_list_free(smartlist_t *p); -void addr_policy_free(addr_policy_t *p); -void policies_free_all(void); - -char *policy_summarize(smartlist_t *policy); - -/********************************* reasons.c ***************************/ - -const char *stream_end_reason_to_control_string(int reason); -const char *stream_end_reason_to_string(int reason); -socks5_reply_status_t stream_end_reason_to_socks5_response(int reason); -uint8_t errno_to_stream_end_reason(int e); - -const char *orconn_end_reason_to_control_string(int r); -int tls_error_to_orconn_end_reason(int e); -int errno_to_orconn_end_reason(int e); - -const char *circuit_end_reason_to_control_string(int reason); - -/********************************* relay.c ***************************/ - -extern uint64_t stats_n_relay_cells_relayed; -extern uint64_t stats_n_relay_cells_delivered; - -int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, - cell_direction_t cell_direction); - -void relay_header_pack(uint8_t *dest, const relay_header_t *src); -void relay_header_unpack(relay_header_t *dest, const uint8_t *src); -int relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, - uint8_t relay_command, const char *payload, - size_t payload_len, crypt_path_t *cpath_layer); -int connection_edge_send_command(edge_connection_t *fromconn, - uint8_t relay_command, const char *payload, - size_t payload_len); -int connection_edge_package_raw_inbuf(edge_connection_t *conn, - int package_partial); -void connection_edge_consider_sending_sendme(edge_connection_t *conn); - -extern uint64_t stats_n_data_cells_packaged; -extern uint64_t stats_n_data_bytes_packaged; -extern uint64_t stats_n_data_cells_received; -extern uint64_t stats_n_data_bytes_received; - -void init_cell_pool(void); -void free_cell_pool(void); -void clean_cell_pool(void); -void dump_cell_pool_usage(int severity); - -void cell_queue_clear(cell_queue_t *queue); -void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell); -void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell); - -void append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, - cell_t *cell, cell_direction_t direction); -void connection_or_unlink_all_active_circs(or_connection_t *conn); -int connection_or_flush_from_first_active_circuit(or_connection_t *conn, - int max, time_t now); -void assert_active_circuits_ok(or_connection_t *orconn); -void make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn); -void make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn); - -int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr); -const uint8_t *decode_address_from_payload(tor_addr_t *addr_out, - const uint8_t *payload, - int payload_len); - /********************************* rephist.c ***************************/ -void rep_hist_init(void); -void rep_hist_note_connect_failed(const char* nickname, time_t when); -void rep_hist_note_connect_succeeded(const char* nickname, time_t when); -void rep_hist_note_disconnect(const char* nickname, time_t when); -void rep_hist_note_connection_died(const char* nickname, time_t when); -void rep_hist_note_extend_succeeded(const char *from_name, - const char *to_name); -void rep_hist_note_extend_failed(const char *from_name, const char *to_name); -void rep_hist_dump_stats(time_t now, int severity); -void rep_hist_note_bytes_read(size_t num_bytes, time_t when); -void rep_hist_note_bytes_written(size_t num_bytes, time_t when); -int rep_hist_bandwidth_assess(void); -char *rep_hist_get_bandwidth_lines(int for_extrainfo); -void rep_hist_update_state(or_state_t *state); -int rep_hist_load_state(or_state_t *state, char **err); -void rep_history_clean(time_t before); - -void rep_hist_note_router_reachable(const char *id, time_t when); -void rep_hist_note_router_unreachable(const char *id, time_t when); -int rep_hist_record_mtbf_data(time_t now, int missing_means_down); -int rep_hist_load_mtbf_data(time_t now); - -time_t rep_hist_downrate_old_runs(time_t now); -double rep_hist_get_stability(const char *id, time_t when); -double rep_hist_get_weighted_fractional_uptime(const char *id, time_t when); -long rep_hist_get_weighted_time_known(const char *id, time_t when); -int rep_hist_have_measured_enough_stability(void); -const char *rep_hist_get_router_stability_doc(time_t now); - -void rep_hist_note_used_port(time_t now, uint16_t port); -smartlist_t *rep_hist_get_predicted_ports(time_t now); -void rep_hist_note_used_resolve(time_t now); -void rep_hist_note_used_internal(time_t now, int need_uptime, - int need_capacity); -int rep_hist_get_predicted_internal(time_t now, int *need_uptime, - int *need_capacity); - -int any_predicted_circuits(time_t now); -int rep_hist_circbuilding_dormant(time_t now); - /** Possible public/private key operations in Tor: used to keep track of where * we're spending our time. */ typedef enum { @@ -4017,48 +3317,6 @@ typedef enum { TLS_HANDSHAKE_C, TLS_HANDSHAKE_S, REND_CLIENT, REND_MID, REND_SERVER, } pk_op_t; -void note_crypto_pk_op(pk_op_t operation); -void dump_pk_ops(int severity); - -void rep_hist_free_all(void); - -/* for hidden service usage statistics */ -void hs_usage_note_publish_total(const char *service_id, time_t now); -void hs_usage_note_publish_novel(const char *service_id, time_t now); -void hs_usage_note_fetch_total(const char *service_id, time_t now); -void hs_usage_note_fetch_successful(const char *service_id, time_t now); -void hs_usage_write_statistics_to_file(time_t now); -void hs_usage_free_all(void); - -/********************************* rendclient.c ***************************/ - -void rend_client_introcirc_has_opened(origin_circuit_t *circ); -void rend_client_rendcirc_has_opened(origin_circuit_t *circ); -int rend_client_introduction_acked(origin_circuit_t *circ, - const uint8_t *request, - size_t request_len); -void rend_client_refetch_renddesc(const char *query); -void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query); -int rend_client_remove_intro_point(extend_info_t *failed_intro, - const rend_data_t *rend_query); -int rend_client_rendezvous_acked(origin_circuit_t *circ, - const uint8_t *request, - size_t request_len); -int rend_client_receive_rendezvous(origin_circuit_t *circ, - const uint8_t *request, - size_t request_len); -void rend_client_desc_trynow(const char *query, int rend_version); - -extend_info_t *rend_client_get_random_intro(const rend_data_t *rend_query); - -int rend_client_send_introduction(origin_circuit_t *introcirc, - origin_circuit_t *rendcirc); -int rend_parse_service_authorization(or_options_t *options, - int validate_only); -rend_service_authorization_t *rend_client_lookup_service_authorization( - const char *onion_address); -void rend_service_authorization_free_all(void); -rend_data_t *rend_data_dup(const rend_data_t *request); /********************************* rendcommon.c ***************************/ @@ -4101,31 +3359,6 @@ typedef struct rend_service_descriptor_t { smartlist_t *successful_uploads; } rend_service_descriptor_t; -/** Free all storage associated with <b>data</b> */ -static INLINE void -rend_data_free(rend_data_t *data) -{ - tor_free(data); -} - -int rend_cmp_service_ids(const char *one, const char *two); - -void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, - int command, size_t length, - const uint8_t *payload); - -void rend_service_descriptor_free(rend_service_descriptor_t *desc); -int rend_encode_service_descriptor(rend_service_descriptor_t *desc, - crypto_pk_env_t *key, - char **str_out, - size_t *len_out); -rend_service_descriptor_t *rend_parse_service_descriptor(const char *str, - size_t len); -int rend_get_service_id(crypto_pk_env_t *pk, char *out); -void rend_encoded_v2_service_descriptor_free( - rend_encoded_v2_service_descriptor_t *desc); -void rend_intro_point_free(rend_intro_point_t *intro); - /** A cached rendezvous descriptor. */ typedef struct rend_cache_entry_t { size_t len; /**< Length of <b>desc</b> */ @@ -4134,150 +3367,6 @@ typedef struct rend_cache_entry_t { rend_service_descriptor_t *parsed; /**< Parsed value of 'desc' */ } rend_cache_entry_t; -void rend_cache_init(void); -void rend_cache_clean(void); -void rend_cache_clean_v2_descs_as_dir(void); -void rend_cache_free_all(void); -int rend_valid_service_id(const char *query); -int rend_cache_lookup_desc(const char *query, int version, const char **desc, - size_t *desc_len); -int rend_cache_lookup_entry(const char *query, int version, - rend_cache_entry_t **entry_out); -int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc); -int rend_cache_store(const char *desc, size_t desc_len, int published); -int rend_cache_store_v2_desc_as_client(const char *desc, - const rend_data_t *rend_query); -int rend_cache_store_v2_desc_as_dir(const char *desc); -int rend_cache_size(void); -int rend_encode_v2_descriptors(smartlist_t *descs_out, - rend_service_descriptor_t *desc, time_t now, - uint8_t period, rend_auth_type_t auth_type, - crypto_pk_env_t *client_key, - smartlist_t *client_cookies); -int rend_compute_v2_desc_id(char *desc_id_out, const char *service_id, - const char *descriptor_cookie, - time_t now, uint8_t replica); -int rend_id_is_in_interval(const char *a, const char *b, const char *c); -void rend_get_descriptor_id_bytes(char *descriptor_id_out, - const char *service_id, - const char *secret_id_part); - -/********************************* rendservice.c ***************************/ - -int num_rend_services(void); -int rend_config_services(or_options_t *options, int validate_only); -int rend_service_load_keys(void); -void rend_services_init(void); -void rend_services_introduce(void); -void rend_consider_services_upload(time_t now); -void rend_hsdir_routers_changed(void); -void rend_consider_descriptor_republication(void); - -void rend_service_intro_has_opened(origin_circuit_t *circuit); -int rend_service_intro_established(origin_circuit_t *circuit, - const uint8_t *request, - size_t request_len); -void rend_service_rendezvous_has_opened(origin_circuit_t *circuit); -int rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, - size_t request_len); -void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc); -int rend_service_set_connection_addr_port(edge_connection_t *conn, - origin_circuit_t *circ); -void rend_service_dump_stats(int severity); -void rend_service_free_all(void); - -/********************************* rendmid.c *******************************/ -int rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, - size_t request_len); -int rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, - size_t request_len); -int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, - size_t request_len); -int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, - size_t request_len); - -/********************************* router.c ***************************/ - -crypto_pk_env_t *get_onion_key(void); -time_t get_onion_key_set_at(void); -void set_identity_key(crypto_pk_env_t *k); -crypto_pk_env_t *get_identity_key(void); -int identity_key_is_set(void); -authority_cert_t *get_my_v3_authority_cert(void); -crypto_pk_env_t *get_my_v3_authority_signing_key(void); -authority_cert_t *get_my_v3_legacy_cert(void); -crypto_pk_env_t *get_my_v3_legacy_signing_key(void); -void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last); -void rotate_onion_key(void); -crypto_pk_env_t *init_key_from_file(const char *fname, int generate, - int severity); -void v3_authority_check_key_expiry(void); - -int init_keys(void); - -int check_whether_orport_reachable(void); -int check_whether_dirport_reachable(void); -void consider_testing_reachability(int test_or, int test_dir); -void router_orport_found_reachable(void); -void router_dirport_found_reachable(void); -void router_perform_bandwidth_test(int num_circs, time_t now); - -int authdir_mode(or_options_t *options); -int authdir_mode_v1(or_options_t *options); -int authdir_mode_v2(or_options_t *options); -int authdir_mode_v3(or_options_t *options); -int authdir_mode_any_main(or_options_t *options); -int authdir_mode_any_nonhidserv(or_options_t *options); -int authdir_mode_handles_descs(or_options_t *options, int purpose); -int authdir_mode_publishes_statuses(or_options_t *options); -int authdir_mode_tests_reachability(or_options_t *options); -int authdir_mode_bridge(or_options_t *options); - -int server_mode(or_options_t *options); -int advertised_server_mode(void); -int proxy_mode(or_options_t *options); -void consider_publishable_server(int force); - -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(void); -void check_descriptor_bandwidth_changed(time_t now); -void check_descriptor_ipaddress_changed(time_t now); -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); -routerinfo_t *router_get_my_routerinfo(void); -extrainfo_t *router_get_my_extrainfo(void); -const char *router_get_my_descriptor(void); -int router_digest_is_me(const char *digest); -int router_extrainfo_digest_is_me(const char *digest); -int router_is_me(routerinfo_t *router); -int router_fingerprint_is_me(const char *fp); -int router_pick_published_address(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); -int extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, - crypto_pk_env_t *ident_key); -char *extrainfo_get_client_geoip_summary(time_t); -int is_legal_nickname(const char *s); -int is_legal_nickname_or_hexdigest(const char *s); -int is_legal_hexdigest(const char *s); -void router_get_verbose_nickname(char *buf, const routerinfo_t *router); -void routerstatus_get_verbose_nickname(char *buf, - const routerstatus_t *router); -void router_reset_warnings(void); -void router_reset_reachability(void); -void router_free_all(void); - -const char *router_purpose_to_string(uint8_t p); -uint8_t router_purpose_from_string(const char *s); - -#ifdef ROUTER_PRIVATE -/* Used only by router.c and test.c */ -void get_platform_str(char *platform, size_t len); -#endif - /********************************* routerlist.c ***************************/ /** Represents information about a single trusted directory server. */ @@ -4317,21 +3406,6 @@ typedef struct trusted_dir_server_t { #define ROUTER_MAX_DECLARED_BANDWIDTH INT32_MAX -int get_n_authorities(authority_type_t type); -int trusted_dirs_reload_certs(void); -int trusted_dirs_load_certs_from_string(const char *contents, int from_store, - int flush); -void trusted_dirs_flush_certs_to_disk(void); -authority_cert_t *authority_cert_get_newest_by_id(const char *id_digest); -authority_cert_t *authority_cert_get_by_sk_digest(const char *sk_digest); -authority_cert_t *authority_cert_get_by_digests(const char *id_digest, - const char *sk_digest); -void authority_cert_get_all(smartlist_t *certs_out); -void authority_cert_dl_failed(const char *id_digest, int status); -void authority_certs_fetch_missing(networkstatus_t *status, time_t now); -int router_reload_router_list(void); -smartlist_t *router_get_trusted_dir_servers(void); - /* Flags for pick_directory_server and pick_trusteddirserver. */ /** Flag to indicate that we should not automatically be willing to use * ourself to answer a directory request. @@ -4361,34 +3435,13 @@ smartlist_t *router_get_trusted_dir_servers(void); */ #define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3) #define _PDS_PREFER_TUNNELED_DIR_CONNS (1<<16) -routerstatus_t *router_pick_directory_server(authority_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); -int router_get_my_share_of_directory_requests(double *v2_share_out, - double *v3_share_out); -void router_reset_status_download_failures(void); -void routerlist_add_family(smartlist_t *sl, routerinfo_t *router); -int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2); -void 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, - uint16_t port); -int router_is_unreliable(routerinfo_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); /** Possible ways to weight routers when choosing one randomly. See * routerlist_sl_choose_by_bandwidth() for more information.*/ -typedef enum { - NO_WEIGHTING, WEIGHT_FOR_EXIT, WEIGHT_FOR_GUARD +typedef enum bandwidth_weight_rule_t { + NO_WEIGHTING, WEIGHT_FOR_EXIT, WEIGHT_FOR_MID, WEIGHT_FOR_GUARD, + WEIGHT_FOR_DIR } bandwidth_weight_rule_t; -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); /** Flags to be passed to control router_choose_random_node() to indicate what * kind of nodes to pick according to what algorithm. */ @@ -4398,44 +3451,9 @@ typedef enum { CRN_NEED_GUARD = 1<<2, CRN_ALLOW_INVALID = 1<<3, /* XXXX not used, apparently. */ - CRN_STRICT_PREFERRED = 1<<4, - /* XXXX not used, apparently. */ CRN_WEIGHT_AS_EXIT = 1<<5 } router_crn_flags_t; -routerinfo_t *router_choose_random_node(const char *preferred, - smartlist_t *excludedsmartlist, - struct routerset_t *excludedset, - router_crn_flags_t flags); - -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_digest_is_trusted_dir_type(const char *digest, - authority_type_t type); -#define router_digest_is_trusted_dir(d) \ - router_digest_is_trusted_dir_type((d), NO_AUTHORITY) - -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); -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); -routerlist_t *router_get_routerlist(void); -void routerinfo_free(routerinfo_t *router); -void extrainfo_free(extrainfo_t *extrainfo); -void routerlist_free(routerlist_t *rl); -void dump_routerlist_mem_usage(int severity); -void routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old, - time_t now); -void routerlist_free_all(void); -void routerlist_reset_warnings(void); -void router_set_status(const char *digest, int up); - /** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */ typedef enum was_router_added_t { ROUTER_ADDED_SUCCESSFULLY = 1, @@ -4447,109 +3465,6 @@ typedef enum was_router_added_t { ROUTER_AUTHDIR_REJECTS = -5, } was_router_added_t; -static int WRA_WAS_ADDED(was_router_added_t s); -static int WRA_WAS_OUTDATED(was_router_added_t s); -static int WRA_WAS_REJECTED(was_router_added_t s); -/** Return true iff the descriptor was added. It might still be necessary to - * check whether the descriptor generator should be notified. - */ -static INLINE int -WRA_WAS_ADDED(was_router_added_t s) { - return s == ROUTER_ADDED_SUCCESSFULLY || s == ROUTER_ADDED_NOTIFY_GENERATOR; -} -/** Return true iff the descriptor was not added because it was either: - * - not in the consensus - * - neither in the consensus nor in any networkstatus document - * - it was outdated. - */ -static INLINE int WRA_WAS_OUTDATED(was_router_added_t s) -{ - return (s == ROUTER_WAS_NOT_NEW || - s == ROUTER_NOT_IN_CONSENSUS || - s == ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS); -} -/** Return true iff the descriptor rejected because it was malformed. */ -static INLINE int WRA_WAS_REJECTED(was_router_added_t s) -{ - return (s == ROUTER_AUTHDIR_REJECTS); -} -was_router_added_t router_add_to_routerlist(routerinfo_t *router, - const char **msg, - int from_cache, - int from_fetch); -was_router_added_t router_add_extrainfo_to_routerlist( - extrainfo_t *ei, const char **msg, - int from_cache, int from_fetch); -void routerlist_remove_old_routers(void); -int router_load_single_router(const char *s, uint8_t purpose, int cache, - const char **msg); -int router_load_routers_from_string(const char *s, const char *eos, - saved_location_t saved_location, - smartlist_t *requested_fingerprints, - int descriptor_digests, - const char *prepend_annotations); -void router_load_extrainfo_from_string(const char *s, const char *eos, - saved_location_t saved_location, - smartlist_t *requested_fingerprints, - 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); -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); -void authority_cert_free(authority_cert_t *cert); -void clear_trusted_dir_servers(void); -int any_trusted_dir_is_v1_authority(void); -void update_router_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, - signed_descriptor_t *sd, - const char **msg); -void routerlist_assert_ok(routerlist_t *rl); -const char *esc_router_info(routerinfo_t *router); -void routers_sort_by_identity(smartlist_t *routers); - -routerset_t *routerset_new(void); -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_contains_router(const routerset_t *set, routerinfo_t *ri); -int routerset_contains_routerstatus(const routerset_t *set, - routerstatus_t *rs); -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, - int running_only); -void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source, - const routerset_t *include, - const routerset_t *exclude, int running_only); -void routerset_subtract_routers(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, - const char *id); -int hid_serv_acting_as_directory(void); -int hid_serv_responsible_for_desc_id(const char *id); - /********************************* routerparse.c ************************/ #define MAX_STATUS_TAG_LEN 32 @@ -4568,71 +3483,10 @@ typedef struct tor_version_t { int patchlevel; char status_tag[MAX_STATUS_TAG_LEN]; int svn_revision; -} tor_version_t; -int router_get_router_hash(const char *s, size_t s_len, char *digest); -int router_get_dir_hash(const char *s, char *digest); -int router_get_runningrouters_hash(const char *s, char *digest); -int router_get_networkstatus_v2_hash(const char *s, char *digest); -int router_get_networkstatus_v3_hash(const char *s, char *digest); -int router_get_extrainfo_hash(const char *s, char *digest); -int router_append_dirobj_signature(char *buf, size_t buf_len, - const char *digest, - crypto_pk_env_t *private_key); -int router_parse_list_from_string(const char **s, const char *eos, - smartlist_t *dest, - saved_location_t saved_location, - int is_extrainfo, - int allow_annotations, - const char *prepend_annotations); -int router_parse_routerlist_from_directory(const char *s, - routerlist_t **dest, - crypto_pk_env_t *pkey, - int check_version, - int write_to_cache); -int router_parse_runningrouters(const char *str); -int router_parse_directory(const char *str); -routerinfo_t *router_parse_entry_from_string(const char *s, const char *end, - int cache_copy, - int allow_annotations, - const char *prepend_annotations); -extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end, - int cache_copy, struct digest_ri_map_t *routermap); -addr_policy_t *router_parse_addr_policy_item_from_string(const char *s, - int assume_action); -version_status_t tor_version_is_obsolete(const char *myversion, - const char *versionlist); -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); -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); - -networkstatus_v2_t *networkstatus_v2_parse_from_string(const char *s); -networkstatus_t *networkstatus_parse_vote_from_string(const char *s, - const char **eos_out, - networkstatus_type_t ns_type); -ns_detached_signatures_t *networkstatus_parse_detached_signatures( - const char *s, const char *eos); - -authority_cert_t *authority_cert_parse_from_string(const char *s, - const char **end_of_string); -int rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, - char *desc_id_out, - char **intro_points_encrypted_out, - size_t *intro_points_encrypted_size_out, - size_t *encoded_size_out, - const char **next_out, const char *desc); -int rend_decrypt_introduction_points(char **ipos_decrypted, - size_t *ipos_decrypted_size, - const char *descriptor_cookie, - const char *ipos_encrypted, - size_t ipos_encrypted_size); -int rend_parse_introduction_points(rend_service_descriptor_t *parsed, - const char *intro_points_encoded, - size_t intro_points_encoded_size); -int rend_parse_client_keys(strmap_t *parsed_clients, const char *str); + int git_tag_len; + char git_tag[DIGEST_LEN]; +} tor_version_t; #endif diff --git a/src/or/policies.c b/src/or/policies.c index 7299b7db3c..4fd0904152 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -9,6 +9,10 @@ **/ #include "or.h" +#include "config.h" +#include "dirserv.h" +#include "policies.h" +#include "routerparse.h" #include "ht.h" /** Policy that addresses for incoming SOCKS connections must match. */ @@ -344,7 +348,8 @@ validate_addr_policies(or_options_t *options, char **msg) *msg = NULL; if (policies_parse_exit_policy(options->ExitPolicy, &addr_policy, - options->ExitPolicyRejectPrivate, NULL)) + options->ExitPolicyRejectPrivate, NULL, + !options->BridgeRelay)) REJECT("Error in ExitPolicy entry."); /* The rest of these calls *append* to addr_policy. So don't actually @@ -375,14 +380,8 @@ validate_addr_policies(or_options_t *options, char **msg) if (parse_addr_policy(options->ReachableDirAddresses, &addr_policy, ADDR_POLICY_ACCEPT)) REJECT("Error in ReachableDirAddresses entry."); - if (parse_addr_policy(options->AuthDirReject, &addr_policy, - ADDR_POLICY_REJECT)) - REJECT("Error in AuthDirReject entry."); - if (parse_addr_policy(options->AuthDirInvalid, &addr_policy, - ADDR_POLICY_REJECT)) - REJECT("Error in AuthDirInvalid entry."); -err: + err: addr_policy_list_free(addr_policy); return *msg ? -1 : 0; #undef REJECT @@ -829,14 +828,16 @@ exit_policy_remove_redundancies(smartlist_t *dest) "reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*" /** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>. If - * cfg doesn't end in an absolute accept or reject, add the default exit + * cfg doesn't end in an absolute accept or reject and if + * <b>add_default_policy</b> is true, add the default exit * policy afterwards. If <b>rejectprivate</b> is true, prepend * "reject private:*" to the policy. Return -1 if we can't parse cfg, * else return 0. */ int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, - int rejectprivate, const char *local_address) + int rejectprivate, const char *local_address, + int add_default_policy) { if (rejectprivate) { append_exit_policy_string(dest, "reject private:*"); @@ -848,8 +849,10 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, } if (parse_addr_policy(cfg, dest, -1)) return -1; - append_exit_policy_string(dest, DEFAULT_EXIT_POLICY); - + if (add_default_policy) + append_exit_policy_string(dest, DEFAULT_EXIT_POLICY); + else + append_exit_policy_string(dest, "reject *:*"); exit_policy_remove_redundancies(*dest); return 0; @@ -866,6 +869,49 @@ policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r) smartlist_add(r->exit_policy, item); } +/** Return 1 if there is at least one /8 subnet in <b>policy</b> that + * allows exiting to <b>port</b>. Otherwise, return 0. */ +static int +exit_policy_is_general_exit_helper(smartlist_t *policy, int port) +{ + uint32_t mask, ip, i; + /* Is this /8 rejected (1), or undecided (0)? */ + char subnet_status[256]; + + memset(subnet_status, 0, sizeof(subnet_status)); + SMARTLIST_FOREACH(policy, addr_policy_t *, p, { + if (p->prt_min > port || p->prt_max < port) + continue; /* Doesn't cover our port. */ + mask = 0; + tor_assert(p->maskbits <= 32); + + if (p->maskbits) + mask = UINT32_MAX<<(32-p->maskbits); + ip = tor_addr_to_ipv4h(&p->addr); + + /* Calculate the first and last subnet that this exit policy touches + * and set it as loop boundaries. */ + for (i = ((mask & ip)>>24); i <= (~((mask & ip) ^ mask)>>24); ++i) { + tor_addr_t addr; + if (subnet_status[i] != 0) + continue; /* We already reject some part of this /8 */ + tor_addr_from_ipv4h(&addr, i<<24); + if (tor_addr_is_internal(&addr, 0)) + continue; /* Local or non-routable addresses */ + if (p->policy_type == ADDR_POLICY_ACCEPT) { + if (p->maskbits > 8) + continue; /* Narrower than a /8. */ + /* We found an allowed subnet of at least size /8. Done + * for this port! */ + return 1; + } else if (p->policy_type == ADDR_POLICY_REJECT) { + subnet_status[i] = 1; + } + } + }); + return 0; +} + /** Return true iff <b>ri</b> is "useful as an exit node", meaning * it allows exit to at least one /8 address space for at least * two of ports 80, 443, and 6667. */ @@ -879,19 +925,7 @@ exit_policy_is_general_exit(smartlist_t *policy) return 0; for (i = 0; i < 3; ++i) { - SMARTLIST_FOREACH(policy, addr_policy_t *, p, { - if (p->prt_min > ports[i] || p->prt_max < ports[i]) - continue; /* Doesn't cover our port. */ - if (p->maskbits > 8) - continue; /* Narrower than a /8. */ - if (tor_addr_is_loopback(&p->addr)) - continue; /* 127.x or ::1. */ - /* We have a match that is at least a /8. */ - if (p->policy_type == ADDR_POLICY_ACCEPT) { - ++n_allowed; - break; /* stop considering this port */ - } - }); + n_allowed += exit_policy_is_general_exit_helper(policy, ports[i]); } return n_allowed >= 2; } @@ -1238,7 +1272,7 @@ policy_summarize(smartlist_t *policy) result = tor_malloc(final_size); tor_snprintf(result, final_size, "%s %s", prefix, shorter_str); -cleanup: + cleanup: /* cleanup */ SMARTLIST_FOREACH(summary, policy_summary_item_t *, s, tor_free(s)); smartlist_free(summary); @@ -1258,9 +1292,11 @@ cleanup: * about "exit-policy/..." */ int getinfo_helper_policies(control_connection_t *conn, - const char *question, char **answer) + const char *question, char **answer, + const char **errmsg) { (void) conn; + (void) errmsg; if (!strcmp(question, "exit-policy/default")) { *answer = tor_strdup(DEFAULT_EXIT_POLICY); } @@ -1271,7 +1307,8 @@ getinfo_helper_policies(control_connection_t *conn, void addr_policy_list_free(smartlist_t *lst) { - if (!lst) return; + if (!lst) + return; SMARTLIST_FOREACH(lst, addr_policy_t *, policy, addr_policy_free(policy)); smartlist_free(lst); } @@ -1280,19 +1317,20 @@ addr_policy_list_free(smartlist_t *lst) void addr_policy_free(addr_policy_t *p) { - if (p) { - if (--p->refcnt <= 0) { - if (p->is_canonical) { - policy_map_ent_t search, *found; - search.policy = p; - found = HT_REMOVE(policy_map, &policy_root, &search); - if (found) { - tor_assert(p == found->policy); - tor_free(found); - } + if (!p) + return; + + if (--p->refcnt <= 0) { + if (p->is_canonical) { + policy_map_ent_t search, *found; + search.policy = p; + found = HT_REMOVE(policy_map, &policy_root, &search); + if (found) { + tor_assert(p == found->policy); + tor_free(found); } - tor_free(p); } + tor_free(p); } } diff --git a/src/or/policies.h b/src/or/policies.h new file mode 100644 index 0000000000..dd46f4de9c --- /dev/null +++ b/src/or/policies.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-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file policies.h + * \brief Header file for policies.c. + **/ + +#ifndef _TOR_POLICIES_H +#define _TOR_POLICIES_H + +/* (length of "accept 255.255.255.255/255.255.255.255:65535-65535\n" plus a + * NUL.) + */ +#define POLICY_BUF_LEN 52 + +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_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); +int authdir_policy_permits_address(uint32_t addr, uint16_t port); +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); +void policy_expand_private(smartlist_t **policy); +int policies_parse_from_options(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); +int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, + int rejectprivate, const char *local_address, + int add_default_policy); +void policies_set_router_exitpolicy_to_reject_all(routerinfo_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, + const char *question, char **answer, + const char **errmsg); +int policy_write_item(char *buf, size_t buflen, addr_policy_t *item, + int format_for_desc); + +void addr_policy_list_free(smartlist_t *p); +void addr_policy_free(addr_policy_t *p); +void policies_free_all(void); + +char *policy_summarize(smartlist_t *policy); + +#endif + diff --git a/src/or/reasons.c b/src/or/reasons.c index 97fe0f83a7..aa7972be5b 100644 --- a/src/or/reasons.c +++ b/src/or/reasons.c @@ -9,6 +9,8 @@ **/ #include "or.h" +#include "config.h" +#include "reasons.h" /***************************** Edge (stream) reasons **********************/ @@ -332,9 +334,78 @@ circuit_end_reason_to_control_string(int reason) return "NOPATH"; case END_CIRC_REASON_NOSUCHSERVICE: return "NOSUCHSERVICE"; + case END_CIRC_REASON_MEASUREMENT_EXPIRED: + return "MEASUREMENT_EXPIRED"; default: log_warn(LD_BUG, "Unrecognized reason code %d", (int)reason); return NULL; } } +/** Return a string corresponding to a SOCKS4 reponse code. */ +const char * +socks4_response_code_to_string(uint8_t code) +{ + switch (code) { + case 0x5a: + return "connection accepted"; + case 0x5b: + return "server rejected connection"; + case 0x5c: + return "server cannot connect to identd on this client"; + case 0x5d: + return "user id does not match identd"; + default: + return "invalid SOCKS 4 response code"; + } +} + +/** Return a string corresponding to a SOCKS5 reponse code. */ +const char * +socks5_response_code_to_string(uint8_t code) +{ + switch (code) { + case 0x00: + return "connection accepted"; + case 0x01: + return "general SOCKS server failure"; + case 0x02: + return "connection not allowed by ruleset"; + case 0x03: + return "Network unreachable"; + case 0x04: + return "Host unreachable"; + case 0x05: + return "Connection refused"; + case 0x06: + return "TTL expired"; + case 0x07: + return "Command not supported"; + case 0x08: + return "Address type not supported"; + default: + return "unknown reason"; + } +} + +/** Return a string corresponding to a bandwidht_weight_rule_t */ +const char * +bandwidth_weight_rule_to_string(bandwidth_weight_rule_t rule) +{ + switch (rule) + { + case NO_WEIGHTING: + return "no weighting"; + case WEIGHT_FOR_EXIT: + return "weight as exit"; + case WEIGHT_FOR_MID: + return "weight as middle node"; + case WEIGHT_FOR_GUARD: + return "weight as guard"; + case WEIGHT_FOR_DIR: + return "weight as directory"; + default: + return "unknown rule"; + } +} + diff --git a/src/or/reasons.h b/src/or/reasons.h new file mode 100644 index 0000000000..b87d36a77a --- /dev/null +++ b/src/or/reasons.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file reasons.h + * \brief Header file for reasons.c. + **/ + +#ifndef _TOR_REASONS_H +#define _TOR_REASONS_H + +const char *stream_end_reason_to_control_string(int reason); +const char *stream_end_reason_to_string(int reason); +socks5_reply_status_t stream_end_reason_to_socks5_response(int reason); +uint8_t errno_to_stream_end_reason(int e); + +const char *orconn_end_reason_to_control_string(int r); +int tls_error_to_orconn_end_reason(int e); +int errno_to_orconn_end_reason(int e); + +const char *circuit_end_reason_to_control_string(int reason); +const char *socks4_response_code_to_string(uint8_t code); +const char *socks5_response_code_to_string(uint8_t code); + +const char *bandwidth_weight_rule_to_string(enum bandwidth_weight_rule_t rule); + +#endif + diff --git a/src/or/relay.c b/src/or/relay.c index 02671473e6..c951cab560 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -10,8 +10,26 @@ * receiving from circuits, plus queuing on circuits. **/ +#include <math.h> #include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "connection_or.h" +#include "control.h" +#include "geoip.h" +#include "main.h" #include "mempool.h" +#include "networkstatus.h" +#include "policies.h" +#include "reasons.h" +#include "relay.h" +#include "rendcommon.h" +#include "routerlist.h" +#include "routerparse.h" static int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, @@ -20,20 +38,46 @@ static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, crypt_path_t *layer_hint); -static int -connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, - edge_connection_t *conn, - crypt_path_t *layer_hint); -static void -circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint); +static int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, + edge_connection_t *conn, + crypt_path_t *layer_hint); +static void circuit_consider_sending_sendme(circuit_t *circ, + crypt_path_t *layer_hint); +static void circuit_resume_edge_reading(circuit_t *circ, + crypt_path_t *layer_hint); +static int circuit_resume_edge_reading_helper(edge_connection_t *conn, + circuit_t *circ, + crypt_path_t *layer_hint); +static int circuit_consider_stop_edge_reading(circuit_t *circ, + crypt_path_t *layer_hint); +static int circuit_queue_streams_are_blocked(circuit_t *circ); + +/** Cache the current hi-res time; the cache gets reset when libevent + * calls us. */ + +static struct timeval cached_time_hires = {0, 0}; + +/** Stop reading on edge connections when we have this many cells + * waiting on the appropriate queue. */ +#define CELL_QUEUE_HIGHWATER_SIZE 256 +/** Start reading from edge connections again when we get down to this many + * cells. */ +#define CELL_QUEUE_LOWWATER_SIZE 64 + static void -circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); -static int -circuit_resume_edge_reading_helper(edge_connection_t *conn, - circuit_t *circ, - crypt_path_t *layer_hint); -static int -circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); +tor_gettimeofday_cached(struct timeval *tv) +{ + if (cached_time_hires.tv_sec == 0) { + tor_gettimeofday(&cached_time_hires); + } + *tv = cached_time_hires; +} + +void +tor_gettimeofday_cache_clear(void) +{ + cached_time_hires.tv_sec = 0; +} /** Stats: how many relay cells have originated at this hop, or have * been relayed onward (not recognized at this hop)? @@ -230,7 +274,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, * we might kill the circ before we relay * the cells. */ - append_cell_to_circuit_queue(circ, or_conn, cell, cell_direction); + append_cell_to_circuit_queue(circ, or_conn, cell, cell_direction, 0); return 0; } @@ -327,7 +371,7 @@ relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, static int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, cell_direction_t cell_direction, - crypt_path_t *layer_hint) + crypt_path_t *layer_hint, streamid_t on_stream) { or_connection_t *conn; /* where to send the cell */ @@ -371,7 +415,7 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, } ++stats_n_relay_cells_relayed; - append_cell_to_circuit_queue(circ, conn, cell, cell_direction); + append_cell_to_circuit_queue(circ, conn, cell, cell_direction, on_stream); return 0; } @@ -496,7 +540,7 @@ relay_command_to_string(uint8_t command) * return 0. */ int -relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ, +relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, uint8_t relay_command, const char *payload, size_t payload_len, crypt_path_t *cpath_layer) { @@ -531,6 +575,12 @@ relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ, log_debug(LD_OR,"delivering %d cell %s.", relay_command, cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward"); + /* If we are sending an END cell and this circuit is used for a tunneled + * directory request, advance its state. */ + if (relay_command == RELAY_COMMAND_END && circ->dirreq_id) + geoip_change_dirreq_state(circ->dirreq_id, DIRREQ_TUNNELED, + DIRREQ_END_CELL_SENT); + if (cell_direction == CELL_DIRECTION_OUT && circ->n_conn) { /* if we're using relaybandwidthrate, this conn wants priority */ circ->n_conn->client_used = approx_time(); @@ -540,17 +590,11 @@ relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ, origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); if (origin_circ->remaining_relay_early_cells > 0 && (relay_command == RELAY_COMMAND_EXTEND || - (cpath_layer != origin_circ->cpath && - !CIRCUIT_PURPOSE_IS_ESTABLISHED_REND(circ->purpose)))) { - /* If we've got any relay_early cells left, and we're sending - * an extend cell or (we're not talking to the first hop and we're - * not talking to a rendezvous circuit), use one of them. - * Don't worry about the conn protocol version: + cpath_layer != origin_circ->cpath)) { + /* If we've got any relay_early cells left and (we're sending + * an extend cell or we're not talking to the first hop), use + * one of them. Don't worry about the conn protocol version: * append_cell_to_circuit_queue will fix it up. */ - /* XXX For now, clients don't use RELAY_EARLY cells when sending - * relay cells on rendezvous circuits. See bug 1038. Eventually, - * we can take this behavior away in favor of having clients avoid - * rendezvous points running 0.2.1.3-alpha through 0.2.1.18. -RD */ cell.command = CELL_RELAY_EARLY; --origin_circ->remaining_relay_early_cells; log_debug(LD_OR, "Sending a RELAY_EARLY cell; %d remaining.", @@ -578,8 +622,8 @@ relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ, } } - if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer) - < 0) { + if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer, + stream_id) < 0) { log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing."); circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return -1; @@ -901,7 +945,7 @@ connection_edge_process_relay_cell_not_open( } /* handle anything that might have queued */ - if (connection_edge_package_raw_inbuf(conn, 1) < 0) { + if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) { /* (We already sent an end cell if possible) */ connection_mark_for_close(TO_CONN(conn)); return 0; @@ -999,7 +1043,8 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, relay_header_unpack(&rh, cell->payload); // log_fn(LOG_DEBUG,"command %d stream %d", rh.command, rh.stream_id); num_seen++; - log_debug(domain, "Now seen %d relay cells here.", num_seen); + log_debug(domain, "Now seen %d relay cells here (command %d, stream %d).", + num_seen, rh.command, rh.stream_id); if (rh.length > RELAY_PAYLOAD_SIZE) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, @@ -1038,6 +1083,16 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, "Begin cell for known stream. Dropping."); return 0; } + if (rh.command == RELAY_COMMAND_BEGIN_DIR) { + /* Assign this circuit and its app-ward OR connection a unique ID, + * so that we can measure download times. The local edge and dir + * connection will be assigned the same ID when they are created + * and linked. */ + static uint64_t next_id = 0; + circ->dirreq_id = ++next_id; + TO_CONN(TO_OR_CIRCUIT(circ)->p_conn)->dirreq_id = circ->dirreq_id; + } + return connection_exit_begin_conn(cell, circ); case RELAY_COMMAND_DATA: ++stats_n_data_cells_received; @@ -1131,6 +1186,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, } if (circ->n_conn) { uint8_t trunc_reason = *(uint8_t*)(cell->payload + RELAY_HEADER_SIZE); + circuit_clear_cell_queue(circ, circ->n_conn); connection_or_send_destroy(circ->n_circ_id, circ->n_conn, trunc_reason); circuit_set_n_circid_orconn(circ, 0, NULL); @@ -1179,9 +1235,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, conn->package_window += STREAMWINDOW_INCREMENT; log_debug(domain,"stream-level sendme, packagewindow now %d.", conn->package_window); + if (circuit_queue_streams_are_blocked(circ)) { + /* Still waiting for queue to flush; don't touch conn */ + return 0; + } connection_start_reading(TO_CONN(conn)); /* handle whatever might still be on the inbuf */ - if (connection_edge_package_raw_inbuf(conn, 1) < 0) { + if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) { /* (We already sent an end cell if possible) */ connection_mark_for_close(TO_CONN(conn)); return 0; @@ -1247,15 +1307,19 @@ uint64_t stats_n_data_cells_received = 0; * ever received were completely full of data. */ uint64_t stats_n_data_bytes_received = 0; -/** While conn->inbuf has an entire relay payload of bytes on it, - * and the appropriate package windows aren't empty, grab a cell - * and send it down the circuit. +/** If <b>conn</b> has an entire relay payload of bytes on its inbuf (or + * <b>package_partial</b> is true), and the appropriate package windows aren't + * empty, grab a cell and send it down the circuit. + * + * If *<b>max_cells</b> is given, package no more than max_cells. Decrement + * *<b>max_cells</b> by the number of cells packaged. * * Return -1 (and send a RELAY_COMMAND_END cell if necessary) if conn should * be marked for close, else return 0. */ int -connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial) +connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, + int *max_cells) { size_t amount_to_process, length; char payload[CELL_PAYLOAD_SIZE]; @@ -1271,7 +1335,10 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial) return 0; } -repeat_connection_edge_package_raw_inbuf: + if (max_cells && *max_cells <= 0) + return 0; + + repeat_connection_edge_package_raw_inbuf: circ = circuit_get_by_edge_conn(conn); if (!circ) { @@ -1332,6 +1399,12 @@ repeat_connection_edge_package_raw_inbuf: } log_debug(domain,"conn->package_window is now %d",conn->package_window); + if (max_cells) { + *max_cells -= 1; + if (*max_cells <= 0) + return 0; + } + /* handle more if there's more, or return 0 if there isn't */ goto repeat_connection_edge_package_raw_inbuf; } @@ -1379,7 +1452,10 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn) static void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) { - + if (circuit_queue_streams_are_blocked(circ)) { + log_debug(layer_hint?LD_APP:LD_EXIT,"Too big queue, no resuming"); + return; + } log_debug(layer_hint?LD_APP:LD_EXIT,"resuming"); if (CIRCUIT_IS_ORIGIN(circ)) @@ -1395,31 +1471,136 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) * of a linked list of edge streams that should each be considered. */ static int -circuit_resume_edge_reading_helper(edge_connection_t *conn, +circuit_resume_edge_reading_helper(edge_connection_t *first_conn, circuit_t *circ, crypt_path_t *layer_hint) { - for ( ; conn; conn=conn->next_stream) { - if (conn->_base.marked_for_close) + edge_connection_t *conn; + int n_packaging_streams, n_streams_left; + int packaged_this_round; + int cells_on_queue; + int cells_per_conn; + edge_connection_t *chosen_stream = NULL; + + /* How many cells do we have space for? It will be the minimum of + * the number needed to exhaust the package window, and the minimum + * needed to fill the cell queue. */ + int max_to_package = circ->package_window; + if (CIRCUIT_IS_ORIGIN(circ)) { + cells_on_queue = circ->n_conn_cells.n; + } else { + or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); + cells_on_queue = or_circ->p_conn_cells.n; + } + if (CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue < max_to_package) + max_to_package = CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue; + + /* Once we used to start listening on the streams in the order they + * appeared in the linked list. That leads to starvation on the + * streams that appeared later on the list, since the first streams + * would always get to read first. Instead, we just pick a random + * stream on the list, and enable reading for streams starting at that + * point (and wrapping around as if the list were circular). It would + * probably be better to actually remember which streams we've + * serviced in the past, but this is simple and effective. */ + + /* Select a stream uniformly at random from the linked list. We + * don't need cryptographic randomness here. */ + { + int num_streams = 0; + for (conn = first_conn; conn; conn = conn->next_stream) { + num_streams++; + if ((tor_weak_random() % num_streams)==0) + chosen_stream = conn; + /* Invariant: chosen_stream has been chosen uniformly at random from + * among the first num_streams streams on first_conn. */ + } + } + + /* Count how many non-marked streams there are that have anything on + * their inbuf, and enable reading on all of the connections. */ + n_packaging_streams = 0; + /* Activate reading starting from the chosen stream */ + for (conn=chosen_stream; conn; conn = conn->next_stream) { + /* Start reading for the streams starting from here */ + if (conn->_base.marked_for_close || conn->package_window <= 0) continue; - if ((!layer_hint && conn->package_window > 0) || - (layer_hint && conn->package_window > 0 && - conn->cpath_layer == layer_hint)) { + if (!layer_hint || conn->cpath_layer == layer_hint) { connection_start_reading(TO_CONN(conn)); + + if (buf_datalen(conn->_base.inbuf) > 0) + ++n_packaging_streams; + } + } + /* Go back and do the ones we skipped, circular-style */ + for (conn = first_conn; conn != chosen_stream; conn = conn->next_stream) { + if (conn->_base.marked_for_close || conn->package_window <= 0) + continue; + if (!layer_hint || conn->cpath_layer == layer_hint) { + connection_start_reading(TO_CONN(conn)); + + if (buf_datalen(conn->_base.inbuf) > 0) + ++n_packaging_streams; + } + } + + if (n_packaging_streams == 0) /* avoid divide-by-zero */ + return 0; + + again: + + cells_per_conn = CEIL_DIV(max_to_package, n_packaging_streams); + + packaged_this_round = 0; + n_streams_left = 0; + + /* Iterate over all connections. Package up to cells_per_conn cells on + * each. Update packaged_this_round with the total number of cells + * packaged, and n_streams_left with the number that still have data to + * package. + */ + for (conn=first_conn; conn; conn=conn->next_stream) { + if (conn->_base.marked_for_close || conn->package_window <= 0) + continue; + if (!layer_hint || conn->cpath_layer == layer_hint) { + int n = cells_per_conn, r; /* handle whatever might still be on the inbuf */ - if (connection_edge_package_raw_inbuf(conn, 1)<0) { - /* (We already sent an end cell if possible) */ + r = connection_edge_package_raw_inbuf(conn, 1, &n); + + /* Note how many we packaged */ + packaged_this_round += (cells_per_conn-n); + + if (r<0) { + /* Problem while packaging. (We already sent an end cell if + * possible) */ connection_mark_for_close(TO_CONN(conn)); continue; } + /* If there's still data to read, we'll be coming back to this stream. */ + if (buf_datalen(conn->_base.inbuf)) + ++n_streams_left; + /* If the circuit won't accept any more data, return without looking * at any more of the streams. Any connections that should be stopped * have already been stopped by connection_edge_package_raw_inbuf. */ if (circuit_consider_stop_edge_reading(circ, layer_hint)) return -1; + /* XXXX should we also stop immediately if we fill up the cell queue? + * Probably. */ } } + + /* If we made progress, and we are willing to package more, and there are + * any streams left that want to package stuff... try again! + */ + if (packaged_this_round && packaged_this_round < max_to_package && + n_streams_left) { + max_to_package -= packaged_this_round; + n_packaging_streams = n_streams_left; + goto again; + } + return 0; } @@ -1488,13 +1669,6 @@ circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint) } } -/** Stop reading on edge connections when we have this many cells - * waiting on the appropriate queue. */ -#define CELL_QUEUE_HIGHWATER_SIZE 256 -/** Start reading from edge connections again when we get down to this many - * cells. */ -#define CELL_QUEUE_LOWWATER_SIZE 64 - #ifdef ACTIVE_CIRCUITS_PARANOIA #define assert_active_circuits_ok_paranoid(conn) \ assert_active_circuits_ok(conn) @@ -1508,6 +1682,10 @@ static int total_cells_allocated = 0; /** A memory pool to allocate packed_cell_t objects. */ static mp_pool_t *cell_pool = NULL; +/** Memory pool to allocate insertion_time_elem_t objects used for cell + * statistics. */ +static mp_pool_t *it_pool = NULL; + /** Allocate structures to hold cells. */ void init_cell_pool(void) @@ -1516,7 +1694,8 @@ init_cell_pool(void) cell_pool = mp_pool_new(sizeof(packed_cell_t), 128*1024); } -/** Free all storage used to hold cells. */ +/** Free all storage used to hold cells (and insertion times if we measure + * cell statistics). */ void free_cell_pool(void) { @@ -1525,6 +1704,10 @@ free_cell_pool(void) mp_pool_destroy(cell_pool); cell_pool = NULL; } + if (it_pool) { + mp_pool_destroy(it_pool); + it_pool = NULL; + } } /** Free excess storage in cell pool. */ @@ -1537,7 +1720,7 @@ clean_cell_pool(void) /** Release storage held by <b>cell</b>. */ static INLINE void -packed_cell_free(packed_cell_t *cell) +packed_cell_free_unchecked(packed_cell_t *cell) { --total_cells_allocated; mp_pool_release(cell); @@ -1599,7 +1782,38 @@ cell_queue_append(cell_queue_t *queue, packed_cell_t *cell) void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell) { - cell_queue_append(queue, packed_cell_copy(cell)); + packed_cell_t *copy = packed_cell_copy(cell); + /* Remember the time when this cell was put in the queue. */ + if (get_options()->CellStatistics) { + struct timeval now; + uint32_t added; + insertion_time_queue_t *it_queue = queue->insertion_times; + if (!it_pool) + it_pool = mp_pool_new(sizeof(insertion_time_elem_t), 1024); + tor_gettimeofday_cached(&now); +#define SECONDS_IN_A_DAY 86400L + added = (uint32_t)(((now.tv_sec % SECONDS_IN_A_DAY) * 100L) + + ((uint32_t)now.tv_usec / (uint32_t)10000L)); + if (!it_queue) { + it_queue = tor_malloc_zero(sizeof(insertion_time_queue_t)); + queue->insertion_times = it_queue; + } + if (it_queue->last && it_queue->last->insertion_time == added) { + it_queue->last->counter++; + } else { + insertion_time_elem_t *elem = mp_pool_get(it_pool); + elem->next = NULL; + elem->insertion_time = added; + elem->counter = 1; + if (it_queue->last) { + it_queue->last->next = elem; + it_queue->last = elem; + } else { + it_queue->first = it_queue->last = elem; + } + } + } + cell_queue_append(queue, copy); } /** Remove and free every cell in <b>queue</b>. */ @@ -1610,11 +1824,19 @@ cell_queue_clear(cell_queue_t *queue) cell = queue->head; while (cell) { next = cell->next; - packed_cell_free(cell); + packed_cell_free_unchecked(cell); cell = next; } queue->head = queue->tail = NULL; queue->n = 0; + if (queue->insertion_times) { + while (queue->insertion_times->first) { + insertion_time_elem_t *elem = queue->insertion_times->first; + queue->insertion_times->first = elem->next; + mp_pool_release(elem); + } + tor_free(queue->insertion_times); + } } /** Extract and return the cell at the head of <b>queue</b>; return NULL if @@ -1666,8 +1888,226 @@ prev_circ_on_conn_p(circuit_t *circ, or_connection_t *conn) } } +/** Helper for sorting cell_ewma_t values in their priority queue. */ +static int +compare_cell_ewma_counts(const void *p1, const void *p2) +{ + const cell_ewma_t *e1=p1, *e2=p2; + if (e1->cell_count < e2->cell_count) + return -1; + else if (e1->cell_count > e2->cell_count) + return 1; + else + return 0; +} + +/** Given a cell_ewma_t, return a pointer to the circuit containing it. */ +static circuit_t * +cell_ewma_to_circuit(cell_ewma_t *ewma) +{ + if (ewma->is_for_p_conn) { + /* This is an or_circuit_t's p_cell_ewma. */ + or_circuit_t *orcirc = SUBTYPE_P(ewma, or_circuit_t, p_cell_ewma); + return TO_CIRCUIT(orcirc); + } else { + /* This is some circuit's n_cell_ewma. */ + return SUBTYPE_P(ewma, circuit_t, n_cell_ewma); + } +} + +/* ==== Functions for scaling cell_ewma_t ==== + + When choosing which cells to relay first, we favor circuits that have been + quiet recently. This gives better latency on connections that aren't + pushing lots of data, and makes the network feel more interactive. + + Conceptually, we take an exponentially weighted mean average of the number + of cells a circuit has sent, and allow active circuits (those with cells to + relay) to send cells in reverse order of their exponentially-weighted mean + average (EWMA) cell count. [That is, a cell sent N seconds ago 'counts' + F^N times as much as a cell sent now, for 0<F<1.0, and we favor the + circuit that has sent the fewest cells] + + If 'double' had infinite precision, we could do this simply by counting a + cell sent at startup as having weight 1.0, and a cell sent N seconds later + as having weight F^-N. This way, we would never need to re-scale + any already-sent cells. + + To prevent double from overflowing, we could count a cell sent now as + having weight 1.0 and a cell sent N seconds ago as having weight F^N. + This, however, would mean we'd need to re-scale *ALL* old circuits every + time we wanted to send a cell. + + So as a compromise, we divide time into 'ticks' (currently, 10-second + increments) and say that a cell sent at the start of a current tick is + worth 1.0, a cell sent N seconds before the start of the current tick is + worth F^N, and a cell sent N seconds after the start of the current tick is + worth F^-N. This way we don't overflow, and we don't need to constantly + rescale. + */ + +/** How long does a tick last (seconds)? */ +#define EWMA_TICK_LEN 10 + +/** The default per-tick scale factor, if it hasn't been overridden by a + * consensus or a configuration setting. zero means "disabled". */ +#define EWMA_DEFAULT_HALFLIFE 0.0 + +/** Given a timeval <b>now</b>, compute the cell_ewma tick in which it occurs + * and the fraction of the tick that has elapsed between the start of the tick + * and <b>now</b>. Return the former and store the latter in + * *<b>remainder_out</b>. + * + * These tick values are not meant to be shared between Tor instances, or used + * for other purposes. */ +static unsigned +cell_ewma_tick_from_timeval(const struct timeval *now, + double *remainder_out) +{ + unsigned res = (unsigned) (now->tv_sec / EWMA_TICK_LEN); + /* rem */ + double rem = (now->tv_sec % EWMA_TICK_LEN) + + ((double)(now->tv_usec)) / 1.0e6; + *remainder_out = rem / EWMA_TICK_LEN; + return res; +} + +/** Compute and return the current cell_ewma tick. */ +unsigned +cell_ewma_get_tick(void) +{ + return ((unsigned)approx_time() / EWMA_TICK_LEN); +} + +/** The per-tick scale factor to be used when computing cell-count EWMA + * values. (A cell sent N ticks before the start of the current tick + * has value ewma_scale_factor ** N.) + */ +static double ewma_scale_factor = 0.1; +static int ewma_enabled = 0; + +#define EPSILON 0.00001 +#define LOG_ONEHALF -0.69314718055994529 + +/** Adjust the global cell scale factor based on <b>options</b> */ +void +cell_ewma_set_scale_factor(or_options_t *options, networkstatus_t *consensus) +{ + int32_t halflife_ms; + double halflife; + const char *source; + if (options && options->CircuitPriorityHalflife >= -EPSILON) { + halflife = options->CircuitPriorityHalflife; + source = "CircuitPriorityHalflife in configuration"; + } else if (consensus && + (halflife_ms = networkstatus_get_param( + consensus, "CircuitPriorityHalflifeMsec", -1)) >= 0) { + halflife = ((double)halflife_ms)/1000.0; + source = "CircuitPriorityHalflifeMsec in consensus"; + } else { + halflife = EWMA_DEFAULT_HALFLIFE; + source = "Default value"; + } + + if (halflife <= EPSILON) { + /* The cell EWMA algorithm is disabled. */ + ewma_scale_factor = 0.1; + ewma_enabled = 0; + log_info(LD_OR, + "Disabled cell_ewma algorithm because of value in %s", + source); + } else { + /* convert halflife into halflife-per-tick. */ + halflife /= EWMA_TICK_LEN; + /* compute per-tick scale factor. */ + ewma_scale_factor = exp( LOG_ONEHALF / halflife ); + ewma_enabled = 1; + log_info(LD_OR, + "Enabled cell_ewma algorithm because of value in %s; " + "scale factor is %lf per %d seconds", + source, ewma_scale_factor, EWMA_TICK_LEN); + } +} + +/** Return the multiplier necessary to convert the value of a cell sent in + * 'from_tick' to one sent in 'to_tick'. */ +static INLINE double +get_scale_factor(unsigned from_tick, unsigned to_tick) +{ + /* This math can wrap around, but that's okay: unsigned overflow is + well-defined */ + int diff = (int)(to_tick - from_tick); + return pow(ewma_scale_factor, diff); +} + +/** Adjust the cell count of <b>ewma</b> so that it is scaled with respect to + * <b>cur_tick</b> */ +static void +scale_single_cell_ewma(cell_ewma_t *ewma, unsigned cur_tick) +{ + double factor = get_scale_factor(ewma->last_adjusted_tick, cur_tick); + ewma->cell_count *= factor; + ewma->last_adjusted_tick = cur_tick; +} + +/** Adjust the cell count of every active circuit on <b>conn</b> so + * that they are scaled with respect to <b>cur_tick</b> */ +static void +scale_active_circuits(or_connection_t *conn, unsigned cur_tick) +{ + + double factor = get_scale_factor( + conn->active_circuit_pqueue_last_recalibrated, + cur_tick); + /** Ordinarily it isn't okay to change the value of an element in a heap, + * but it's okay here, since we are preserving the order. */ + SMARTLIST_FOREACH(conn->active_circuit_pqueue, cell_ewma_t *, e, { + tor_assert(e->last_adjusted_tick == + conn->active_circuit_pqueue_last_recalibrated); + e->cell_count *= factor; + e->last_adjusted_tick = cur_tick; + }); + conn->active_circuit_pqueue_last_recalibrated = cur_tick; +} + +/** Rescale <b>ewma</b> to the same scale as <b>conn</b>, and add it to + * <b>conn</b>'s priority queue of active circuits */ +static void +add_cell_ewma_to_conn(or_connection_t *conn, cell_ewma_t *ewma) +{ + tor_assert(ewma->heap_index == -1); + scale_single_cell_ewma(ewma, + conn->active_circuit_pqueue_last_recalibrated); + + smartlist_pqueue_add(conn->active_circuit_pqueue, + compare_cell_ewma_counts, + STRUCT_OFFSET(cell_ewma_t, heap_index), + ewma); +} + +/** Remove <b>ewma</b> from <b>conn</b>'s priority queue of active circuits */ +static void +remove_cell_ewma_from_conn(or_connection_t *conn, cell_ewma_t *ewma) +{ + tor_assert(ewma->heap_index != -1); + smartlist_pqueue_remove(conn->active_circuit_pqueue, + compare_cell_ewma_counts, + STRUCT_OFFSET(cell_ewma_t, heap_index), + ewma); +} + +/** Remove and return the first cell_ewma_t from conn's priority queue of + * active circuits. Requires that the priority queue is nonempty. */ +static cell_ewma_t * +pop_first_cell_ewma_from_conn(or_connection_t *conn) +{ + return smartlist_pqueue_pop(conn->active_circuit_pqueue, + compare_cell_ewma_counts, + STRUCT_OFFSET(cell_ewma_t, heap_index)); +} + /** Add <b>circ</b> to the list of circuits with pending cells on - * <b>conn</b>. No effect if <b>circ</b> is already unlinked. */ + * <b>conn</b>. No effect if <b>circ</b> is already linked. */ void make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn) { @@ -1679,6 +2119,8 @@ make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn) return; } + assert_active_circuits_ok_paranoid(conn); + if (! conn->active_circuits) { conn->active_circuits = circ; *prevp = *nextp = circ; @@ -1690,10 +2132,19 @@ make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn) *prev_circ_on_conn_p(head, conn) = circ; *prevp = old_tail; } + + if (circ->n_conn == conn) { + add_cell_ewma_to_conn(conn, &circ->n_cell_ewma); + } else { + or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); + tor_assert(conn == orcirc->p_conn); + add_cell_ewma_to_conn(conn, &orcirc->p_cell_ewma); + } + assert_active_circuits_ok_paranoid(conn); } -/** Remove <b>circ</b> to the list of circuits with pending cells on +/** Remove <b>circ</b> from the list of circuits with pending cells on * <b>conn</b>. No effect if <b>circ</b> is already unlinked. */ void make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn) @@ -1707,6 +2158,8 @@ make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn) return; } + assert_active_circuits_ok_paranoid(conn); + tor_assert(next && prev); tor_assert(*prev_circ_on_conn_p(next, conn) == circ); tor_assert(*next_circ_on_conn_p(prev, conn) == circ); @@ -1720,6 +2173,15 @@ make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn) conn->active_circuits = next; } *prevp = *nextp = NULL; + + if (circ->n_conn == conn) { + remove_cell_ewma_from_conn(conn, &circ->n_cell_ewma); + } else { + or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); + tor_assert(conn == orcirc->p_conn); + remove_cell_ewma_from_conn(conn, &orcirc->p_cell_ewma); + } + assert_active_circuits_ok_paranoid(conn); } @@ -1739,16 +2201,27 @@ connection_or_unlink_all_active_circs(or_connection_t *orconn) cur = next; } while (cur != head); orconn->active_circuits = NULL; + + SMARTLIST_FOREACH(orconn->active_circuit_pqueue, cell_ewma_t *, e, + e->heap_index = -1); + smartlist_clear(orconn->active_circuit_pqueue); } /** Block (if <b>block</b> is true) or unblock (if <b>block</b> is false) * every edge connection that is using <b>circ</b> to write to <b>orconn</b>, - * and start or stop reading as appropriate. */ -static void + * and start or stop reading as appropriate. + * + * If <b>stream_id</b> is nonzero, block only the edge connection whose + * stream_id matches it. + * + * Returns the number of streams whose status we changed. + */ +static int set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn, - int block) + int block, streamid_t stream_id) { edge_connection_t *edge = NULL; + int n = 0; if (circ->n_conn == orconn) { circ->streams_blocked_on_n_conn = block; if (CIRCUIT_IS_ORIGIN(circ)) @@ -1761,7 +2234,13 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn, for (; edge; edge = edge->next_stream) { connection_t *conn = TO_CONN(edge); - edge->edge_blocked_on_circ = block; + if (stream_id && edge->stream_id != stream_id) + continue; + + if (edge->edge_blocked_on_circ != block) { + ++n; + edge->edge_blocked_on_circ = block; + } if (!conn->read_event) { /* This connection is a placeholder for something; probably a DNS @@ -1778,10 +2257,12 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn, connection_start_reading(conn); } } + + return n; } /** Pull as many cells as possible (but no more than <b>max</b>) from the - * queue of the first active circuit on <b>conn</b>, and write then to + * queue of the first active circuit on <b>conn</b>, and write them to * <b>conn</b>->outbuf. Return the number of cells written. Advance * the active circuit pointer to the next active circuit in the ring. */ int @@ -1792,9 +2273,35 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max, cell_queue_t *queue; circuit_t *circ; int streams_blocked; + + /* The current (hi-res) time */ + struct timeval now_hires; + + /* The EWMA cell counter for the circuit we're flushing. */ + cell_ewma_t *cell_ewma = NULL; + double ewma_increment = -1; + circ = conn->active_circuits; if (!circ) return 0; assert_active_circuits_ok_paranoid(conn); + + /* See if we're doing the ewma circuit selection algorithm. */ + if (ewma_enabled) { + unsigned tick; + double fractional_tick; + tor_gettimeofday_cached(&now_hires); + tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick); + + if (tick != conn->active_circuit_pqueue_last_recalibrated) { + scale_active_circuits(conn, tick); + } + + ewma_increment = pow(ewma_scale_factor, -fractional_tick); + + cell_ewma = smartlist_get(conn->active_circuit_pqueue, 0); + circ = cell_ewma_to_circuit(cell_ewma); + } + if (circ->n_conn == conn) { queue = &circ->n_conn_cells; streams_blocked = circ->streams_blocked_on_n_conn; @@ -1808,10 +2315,60 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max, packed_cell_t *cell = cell_queue_pop(queue); tor_assert(*next_circ_on_conn_p(circ,conn)); + /* Calculate the exact time that this cell has spent in the queue. */ + if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) { + struct timeval now; + 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); + if (!it_queue || !it_queue->first) { + log_info(LD_GENERAL, "Cannot determine insertion time of cell. " + "Looks like the CellStatistics option was " + "recently enabled."); + } else { + or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); + insertion_time_elem_t *elem = it_queue->first; + cell_waiting_time = + (uint32_t)((flushed * 10L + SECONDS_IN_A_DAY * 1000L - + elem->insertion_time * 10L) % + (SECONDS_IN_A_DAY * 1000L)); +#undef SECONDS_IN_A_DAY + elem->counter--; + if (elem->counter < 1) { + it_queue->first = elem->next; + if (elem == it_queue->last) + it_queue->last = NULL; + mp_pool_release(elem); + } + orcirc->total_cell_waiting_time += cell_waiting_time; + orcirc->processed_cells++; + } + } + + /* If we just flushed our queue and this circuit is used for a + * tunneled directory request, possibly advance its state. */ + if (queue->n == 0 && TO_CONN(conn)->dirreq_id) + geoip_change_dirreq_state(TO_CONN(conn)->dirreq_id, + DIRREQ_TUNNELED, + DIRREQ_CIRC_QUEUE_FLUSHED); + connection_write_to_buf(cell->body, CELL_NETWORK_SIZE, TO_CONN(conn)); - packed_cell_free(cell); + packed_cell_free_unchecked(cell); ++n_flushed; + if (cell_ewma) { + cell_ewma_t *tmp; + cell_ewma->cell_count += ewma_increment; + /* We pop and re-add the cell_ewma_t here, not above, since we need to + * re-add it immediately to keep the priority queue consistent with + * the linked-list implementation */ + tmp = pop_first_cell_ewma_from_conn(conn); + tor_assert(tmp == cell_ewma); + add_cell_ewma_to_conn(conn, cell_ewma); + } if (circ != conn->active_circuits) { /* If this happens, the current circuit just got made inactive by * a call in connection_write_to_buf(). That's nothing to worry about: @@ -1829,9 +2386,9 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max, /* Is the cell queue low enough to unblock all the streams that are waiting * to write to this circuit? */ if (streams_blocked && queue->n <= CELL_QUEUE_LOWWATER_SIZE) - set_streams_blocked_on_circ(circ, conn, 0); /* unblock streams */ + set_streams_blocked_on_circ(circ, conn, 0, 0); /* unblock streams */ - /* Did we just ran out of cells on this queue? */ + /* Did we just run out of cells on this circuit's queue? */ if (queue->n == 0) { log_debug(LD_GENERAL, "Made a circuit inactive."); make_circuit_inactive_on_conn(circ, conn); @@ -1846,10 +2403,14 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max, * transmitting in <b>direction</b>. */ void append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, - cell_t *cell, cell_direction_t direction) + cell_t *cell, cell_direction_t direction, + streamid_t fromstream) { cell_queue_t *queue; int streams_blocked; + if (circ->marked_for_close) + return; + if (direction == CELL_DIRECTION_OUT) { queue = &circ->n_conn_cells; streams_blocked = circ->streams_blocked_on_n_conn; @@ -1868,7 +2429,12 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, /* If we have too many cells on the circuit, we should stop reading from * the edge streams for a while. */ if (!streams_blocked && queue->n >= CELL_QUEUE_HIGHWATER_SIZE) - set_streams_blocked_on_circ(circ, orconn, 1); /* block streams */ + set_streams_blocked_on_circ(circ, orconn, 1, 0); /* block streams */ + + if (streams_blocked && fromstream) { + /* This edge connection is apparently not blocked; block it. */ + set_streams_blocked_on_circ(circ, orconn, 1, fromstream); + } if (queue->n == 1) { /* This was the first cell added to the queue. We need to make this @@ -1947,6 +2513,25 @@ decode_address_from_payload(tor_addr_t *addr_out, const uint8_t *payload, return payload + 2 + payload[1]; } +/** Remove all the cells queued on <b>circ</b> for <b>orconn</b>. */ +void +circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn) +{ + cell_queue_t *queue; + if (circ->n_conn == orconn) { + queue = &circ->n_conn_cells; + } else { + or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); + tor_assert(orcirc->p_conn == orconn); + queue = &orcirc->p_conn_cells; + } + + if (queue->n) + make_circuit_inactive_on_conn(circ,orconn); + + cell_queue_clear(queue); +} + /** Fail with an assert if the active circuits ring on <b>orconn</b> is * corrupt. */ void @@ -1954,16 +2539,44 @@ assert_active_circuits_ok(or_connection_t *orconn) { circuit_t *head = orconn->active_circuits; circuit_t *cur = head; + int n = 0; if (! head) return; do { circuit_t *next = *next_circ_on_conn_p(cur, orconn); circuit_t *prev = *prev_circ_on_conn_p(cur, orconn); + cell_ewma_t *ewma; tor_assert(next); tor_assert(prev); tor_assert(*next_circ_on_conn_p(prev, orconn) == cur); tor_assert(*prev_circ_on_conn_p(next, orconn) == cur); + if (orconn == cur->n_conn) { + ewma = &cur->n_cell_ewma; + tor_assert(!ewma->is_for_p_conn); + } else { + ewma = &TO_OR_CIRCUIT(cur)->p_cell_ewma; + tor_assert(ewma->is_for_p_conn); + } + tor_assert(ewma->heap_index != -1); + tor_assert(ewma == smartlist_get(orconn->active_circuit_pqueue, + ewma->heap_index)); + n++; cur = next; } while (cur != head); + + tor_assert(n == smartlist_len(orconn->active_circuit_pqueue)); +} + +/** Return 1 if we shouldn't restart reading on this circuit, even if + * we get a SENDME. Else return 0. +*/ +static int +circuit_queue_streams_are_blocked(circuit_t *circ) +{ + if (CIRCUIT_IS_ORIGIN(circ)) { + return circ->streams_blocked_on_n_conn; + } else { + return circ->streams_blocked_on_p_conn; + } } diff --git a/src/or/relay.h b/src/or/relay.h new file mode 100644 index 0000000000..8ccf0e2b30 --- /dev/null +++ b/src/or/relay.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file relay.h + * \brief Header file for relay.c. + **/ + +#ifndef _TOR_RELAY_H +#define _TOR_RELAY_H + +extern uint64_t stats_n_relay_cells_relayed; +extern uint64_t stats_n_relay_cells_delivered; + +int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, + cell_direction_t cell_direction); + +void relay_header_pack(uint8_t *dest, const relay_header_t *src); +void relay_header_unpack(relay_header_t *dest, const uint8_t *src); +int relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, + uint8_t relay_command, const char *payload, + size_t payload_len, crypt_path_t *cpath_layer); +int connection_edge_send_command(edge_connection_t *fromconn, + uint8_t relay_command, const char *payload, + size_t payload_len); +int connection_edge_package_raw_inbuf(edge_connection_t *conn, + int package_partial, + int *max_cells); +void connection_edge_consider_sending_sendme(edge_connection_t *conn); + +extern uint64_t stats_n_data_cells_packaged; +extern uint64_t stats_n_data_bytes_packaged; +extern uint64_t stats_n_data_cells_received; +extern uint64_t stats_n_data_bytes_received; + +void init_cell_pool(void); +void free_cell_pool(void); +void clean_cell_pool(void); +void dump_cell_pool_usage(int severity); + +void cell_queue_clear(cell_queue_t *queue); +void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell); +void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell); + +void append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, + cell_t *cell, cell_direction_t direction, + streamid_t fromstream); +void connection_or_unlink_all_active_circs(or_connection_t *conn); +int connection_or_flush_from_first_active_circuit(or_connection_t *conn, + int max, time_t now); +void assert_active_circuits_ok(or_connection_t *orconn); +void make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn); +void make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn); + +int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr); +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 circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn); + +#endif + diff --git a/src/or/rendclient.c b/src/or/rendclient.c index feecf237c4..ab968078e8 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -8,6 +8,19 @@ **/ #include "or.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "connection_edge.h" +#include "directory.h" +#include "main.h" +#include "relay.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rephist.h" +#include "routerlist.h" /** Called when we've established a circuit to an introduction point: * send the introduction request. */ @@ -63,7 +76,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, rend_cache_entry_t *entry; crypt_path_t *cpath; off_t dh_offset; - crypto_pk_env_t *intro_key; /* either Bob's public key or an intro key. */ + crypto_pk_env_t *intro_key = NULL; tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY); @@ -76,48 +89,26 @@ rend_client_send_introduction(origin_circuit_t *introcirc, &entry) < 1) { log_warn(LD_REND, "query %s didn't have valid rend desc in cache. Failing.", - escaped_safe_str(introcirc->rend_data->onion_address)); + escaped_safe_str_client(introcirc->rend_data->onion_address)); goto err; } - /* first 20 bytes of payload are the hash of Bob's pk */ - if (entry->parsed->version == 0) { /* un-versioned descriptor */ - intro_key = entry->parsed->pk; - } else { /* versioned descriptor */ - intro_key = NULL; - SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, - intro, { - if (!memcmp(introcirc->build_state->chosen_exit->identity_digest, - intro->extend_info->identity_digest, DIGEST_LEN)) { - intro_key = intro->intro_key; - break; - } - }); - if (!intro_key) { - /** XXX This case probably means that the intro point vanished while - * we were building a circuit to it. In the future, we should find - * out how that happened and whether we should kill the circuits to - * removed intro points immediately. See task 1073. */ - int num_intro_points = smartlist_len(entry->parsed->intro_nodes); - if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, - 0, &entry) > 0) { - log_info(LD_REND, "We have both a v0 and a v2 rend desc for this " - "service. The v2 desc doesn't contain the introduction " - "point (and key) to send an INTRODUCE1/2 cell to this " - "introduction point. Assuming the introduction point " - "is for v0 rend clients and using the service key " - "from the v0 desc instead. (This is probably a bug, " - "because we shouldn't even have both a v0 and a v2 " - "descriptor for the same service.)"); - /* See flyspray task 1024. */ - intro_key = entry->parsed->pk; - } else { - log_info(LD_REND, "Internal error: could not find intro key; we " - "only have a v2 rend desc with %d intro points.", - num_intro_points); - goto err; - } + /* first 20 bytes of payload are the hash of the intro key */ + intro_key = NULL; + SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, + intro, { + if (!memcmp(introcirc->build_state->chosen_exit->identity_digest, + intro->extend_info->identity_digest, DIGEST_LEN)) { + intro_key = intro->intro_key; + break; } + }); + if (!intro_key) { + log_info(LD_REND, "Our introduction point knowledge changed in " + "mid-connect! Could not find intro key; we only have a " + "v2 rend desc with %d intro points. Giving up.", + smartlist_len(entry->parsed->intro_nodes)); + goto err; } if (crypto_pk_get_digest(intro_key, payload)<0) { log_warn(LD_BUG, "Internal error: couldn't hash public key."); @@ -218,7 +209,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT; return 0; -err: + err: circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL); circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL); return -1; @@ -291,7 +282,7 @@ rend_client_introduction_acked(origin_circuit_t *circ, extend_info = rend_client_get_random_intro(circ->rend_data); if (!extend_info) { log_warn(LD_REND, "No introduction points left for %s. Closing.", - escaped_safe_str(circ->rend_data->onion_address)); + escaped_safe_str_client(circ->rend_data->onion_address)); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return -1; } @@ -299,7 +290,7 @@ rend_client_introduction_acked(origin_circuit_t *circ, log_info(LD_REND, "Got nack for %s from %s. Re-extending circ %d, " "this time to %s.", - escaped_safe_str(circ->rend_data->onion_address), + escaped_safe_str_client(circ->rend_data->onion_address), circ->build_state->chosen_exit->nickname, circ->_base.n_circ_id, extend_info->nickname); result = circuit_extend_to_new_exit(circ, extend_info); @@ -307,7 +298,7 @@ rend_client_introduction_acked(origin_circuit_t *circ, log_info(LD_REND, "Got nack for %s from %s. Building a new introduction " "circuit, this time to %s.", - escaped_safe_str(circ->rend_data->onion_address), + escaped_safe_str_client(circ->rend_data->onion_address), circ->build_state->chosen_exit->nickname, extend_info->nickname); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); @@ -470,45 +461,21 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) rend_query->onion_address, desc_id_base32, rend_query->auth_type, (rend_query->auth_type == REND_NO_AUTH ? "[none]" : - escaped_safe_str(descriptor_cookie_base64)), + escaped_safe_str_client(descriptor_cookie_base64)), hs_dir->nickname, hs_dir->dir_port); return 1; } -/** If we are not currently fetching a rendezvous service descriptor - * for the service ID <b>query</b>, start a directory connection to fetch a - * new one. - */ -void -rend_client_refetch_renddesc(const char *query) -{ - if (!get_options()->FetchHidServDescriptors) - return; - log_info(LD_REND, "Fetching rendezvous descriptor for service %s", - escaped_safe_str(query)); - if (connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query, 0)) { - log_info(LD_REND,"Would fetch a new renddesc here (for %s), but one is " - "already in progress.", escaped_safe_str(query)); - } else { - /* not one already; initiate a dir rend desc lookup */ - directory_get_from_dirserver(DIR_PURPOSE_FETCH_RENDDESC, - ROUTER_PURPOSE_GENERAL, query, - PDS_RETRY_IF_NO_SERVERS); - } -} - -/** Start a connection to a hidden service directory to fetch a v2 - * rendezvous service descriptor for the base32-encoded service ID - * <b>query</b>. - */ +/** Unless we already have a descriptor for <b>rend_query</b> with at least + * one (possibly) working introduction point in it, start a connection to a + * hidden service directory to fetch a v2 rendezvous service descriptor. */ void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query) { char descriptor_id[DIGEST_LEN]; int replicas_left_to_try[REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS]; - int i, tries_left, r; + int i, tries_left; rend_cache_entry_t *e = NULL; - time_t now = time(NULL); tor_assert(rend_query); /* Are we configured to fetch descriptors? */ if (!get_options()->FetchHidServDescriptors) { @@ -517,15 +484,13 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query) return; } /* Before fetching, check if we already have the descriptor here. */ - r = rend_cache_lookup_entry(rend_query->onion_address, -1, &e); - if (r > 0 && now - e->received < NUM_SECONDS_BEFORE_HS_REFETCH) { + if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e) > 0) { log_info(LD_REND, "We would fetch a v2 rendezvous descriptor, but we " - "already have a fresh copy of that descriptor here. " - "Not fetching."); + "already have that descriptor here. Not fetching."); return; } log_debug(LD_REND, "Fetching v2 rendezvous descriptor for service %s", - safe_str(rend_query->onion_address)); + safe_str_client(rend_query->onion_address)); /* Randomly iterate over the replicas until a descriptor can be fetched * from one of the consecutive nodes, or no options are left. */ tries_left = REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; @@ -551,8 +516,8 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query) log_info(LD_REND, "Could not pick one of the responsible hidden " "service directories to fetch descriptors, because " "we already tried them all unsuccessfully."); - /* Close pending connections (unless a v0 request is still going on). */ - rend_client_desc_trynow(rend_query->onion_address, 2); + /* Close pending connections. */ + rend_client_desc_trynow(rend_query->onion_address); return; } @@ -573,18 +538,13 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, r = rend_cache_lookup_entry(rend_query->onion_address, -1, &ent); if (r<0) { log_warn(LD_BUG, "Malformed service ID %s.", - escaped_safe_str(rend_query->onion_address)); + escaped_safe_str_client(rend_query->onion_address)); return -1; } if (r==0) { log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.", - escaped_safe_str(rend_query->onion_address)); - /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever - * arrives first. Exception: When using client authorization, only - * fetch v2 descriptors.*/ + escaped_safe_str_client(rend_query->onion_address)); rend_client_refetch_v2_renddesc(rend_query); - if (rend_query->auth_type == REND_NO_AUTH) - rend_client_refetch_renddesc(rend_query->onion_address); return 0; } @@ -601,18 +561,13 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, if (smartlist_len(ent->parsed->intro_nodes) == 0) { log_info(LD_REND, "No more intro points remain for %s. Re-fetching descriptor.", - escaped_safe_str(rend_query->onion_address)); - /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever - * arrives first. Exception: When using client authorization, only - * fetch v2 descriptors.*/ + escaped_safe_str_client(rend_query->onion_address)); rend_client_refetch_v2_renddesc(rend_query); - if (rend_query->auth_type == REND_NO_AUTH) - rend_client_refetch_renddesc(rend_query->onion_address); /* move all pending streams back to renddesc_wait */ while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP, AP_CONN_STATE_CIRCUIT_WAIT, - rend_query->onion_address, -1))) { + rend_query->onion_address))) { conn->state = AP_CONN_STATE_RENDDESC_WAIT; } @@ -620,7 +575,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, } log_info(LD_REND,"%d options left for %s.", smartlist_len(ent->parsed->intro_nodes), - escaped_safe_str(rend_query->onion_address)); + escaped_safe_str_client(rend_query->onion_address)); return 1; } @@ -682,7 +637,8 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, tor_assert(circ->build_state->pending_final_cpath); hop = circ->build_state->pending_final_cpath; tor_assert(hop->dh_handshake_state); - if (crypto_dh_compute_secret(hop->dh_handshake_state, (char*)request, + if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, + hop->dh_handshake_state, (char*)request, DH_KEY_LEN, keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) { log_warn(LD_GENERAL, "Couldn't complete DH handshake."); @@ -722,24 +678,18 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, return -1; } -/** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that - * are waiting on query. If there's a working cache entry here - * with at least one intro point, move them to the next state. If - * <b>rend_version</b> is non-negative, fail connections that have - * requested <b>query</b> unless there are still descriptor fetch - * requests in progress for other descriptor versions than - * <b>rend_version</b>. - */ +/** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that are + * waiting on <b>query</b>. If there's a working cache entry here with at + * least one intro point, move them to the next state. */ void -rend_client_desc_trynow(const char *query, int rend_version) +rend_client_desc_trynow(const char *query) { edge_connection_t *conn; rend_cache_entry_t *entry; time_t now = time(NULL); smartlist_t *conns = get_connection_array(); - SMARTLIST_FOREACH(conns, connection_t *, _conn, - { + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, _conn) { if (_conn->type != CONN_TYPE_AP || _conn->state != AP_CONN_STATE_RENDDESC_WAIT || _conn->marked_for_close) @@ -771,17 +721,12 @@ rend_client_desc_trynow(const char *query, int rend_version) connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); } } else { /* 404, or fetch didn't get that far */ - /* Unless there are requests for another descriptor version pending, - * close the connection. */ - if (rend_version >= 0 && - !connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query, - rend_version == 0 ? 2 : 0)) { - log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is " - "unavailable (try again later).", safe_str(query)); - connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED); - } + log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is " + "unavailable (try again later).", + safe_str_client(query)); + connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED); } - }); + } SMARTLIST_FOREACH_END(_conn); } /** Return a newly allocated extend_info_t* for a randomly chosen introduction @@ -799,7 +744,7 @@ rend_client_get_random_intro(const rend_data_t *rend_query) if (rend_cache_lookup_entry(rend_query->onion_address, -1, &entry) < 1) { log_warn(LD_REND, "Query '%s' didn't have valid rend desc in cache. Failing.", - safe_str(rend_query->onion_address)); + safe_str_client(rend_query->onion_address)); return NULL; } @@ -811,7 +756,10 @@ rend_client_get_random_intro(const rend_data_t *rend_query) intro = smartlist_get(entry->parsed->intro_nodes, i); /* Do we need to look up the router or is the extend info complete? */ if (!intro->extend_info->onion_key) { - router = router_get_by_nickname(intro->extend_info->nickname, 0); + if (tor_digest_is_zero(intro->extend_info->identity_digest)) + router = router_get_by_hexdigest(intro->extend_info->nickname); + else + router = router_get_by_digest(intro->extend_info->identity_digest); if (!router) { log_info(LD_REND, "Unknown router with nickname '%s'; trying another.", intro->extend_info->nickname); @@ -949,8 +897,7 @@ rend_parse_service_authorization(or_options_t *options, int validate_only) err: res = -1; done: - if (auth) - rend_service_authorization_free(auth); + rend_service_authorization_free(auth); SMARTLIST_FOREACH(sl, char *, c, tor_free(c);); smartlist_free(sl); if (!validate_only && res == 0) { diff --git a/src/or/rendclient.h b/src/or/rendclient.h new file mode 100644 index 0000000000..79d37b2a58 --- /dev/null +++ b/src/or/rendclient.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file rendclient.h + * \brief Header file for rendclient.c. + **/ + +#ifndef _TOR_RENDCLIENT_H +#define _TOR_RENDCLIENT_H + +void rend_client_introcirc_has_opened(origin_circuit_t *circ); +void rend_client_rendcirc_has_opened(origin_circuit_t *circ); +int rend_client_introduction_acked(origin_circuit_t *circ, + const uint8_t *request, + size_t request_len); +void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query); +int rend_client_remove_intro_point(extend_info_t *failed_intro, + const rend_data_t *rend_query); +int rend_client_rendezvous_acked(origin_circuit_t *circ, + const uint8_t *request, + size_t request_len); +int rend_client_receive_rendezvous(origin_circuit_t *circ, + const uint8_t *request, + size_t request_len); +void rend_client_desc_trynow(const char *query); + +extend_info_t *rend_client_get_random_intro(const rend_data_t *rend_query); + +int rend_client_send_introduction(origin_circuit_t *introcirc, + origin_circuit_t *rendcirc); +int rend_parse_service_authorization(or_options_t *options, + int validate_only); +rend_service_authorization_t *rend_client_lookup_service_authorization( + const char *onion_address); +void rend_service_authorization_free_all(void); +rend_data_t *rend_data_dup(const rend_data_t *request); + +#endif + diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 9ee86f6673..85d97e0253 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -9,6 +9,15 @@ **/ #include "or.h" +#include "circuitbuild.h" +#include "config.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rendmid.h" +#include "rendservice.h" +#include "rephist.h" +#include "routerlist.h" +#include "routerparse.h" /** Return 0 if one and two are the same service ids, else -1 or 1 */ int @@ -22,6 +31,8 @@ rend_cmp_service_ids(const char *one, const char *two) void rend_service_descriptor_free(rend_service_descriptor_t *desc) { + if (!desc) + return; if (desc->pk) crypto_free_pk_env(desc->pk); if (desc->intro_nodes) { @@ -125,7 +136,8 @@ rend_compute_v2_desc_id(char *desc_id_out, const char *service_id, if (!service_id || strlen(service_id) != REND_SERVICE_ID_LEN_BASE32) { log_warn(LD_REND, "Could not compute v2 descriptor ID: " - "Illegal service ID: %s", safe_str(service_id)); + "Illegal service ID: %s", + safe_str(service_id)); return -1; } if (replica >= REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS) { @@ -138,7 +150,7 @@ rend_compute_v2_desc_id(char *desc_id_out, const char *service_id, service_id, REND_SERVICE_ID_LEN_BASE32) < 0) { log_warn(LD_REND, "Could not compute v2 descriptor ID: " "Illegal characters in service ID: %s", - safe_str(service_id)); + safe_str_client(service_id)); return -1; } /* Calculate current time-period. */ @@ -403,8 +415,7 @@ rend_desc_v2_is_parsable(rend_encoded_v2_service_descriptor_t *desc) &test_intro_size, &test_encoded_size, &test_next, desc->desc_str); - if (test_parsed) - rend_service_descriptor_free(test_parsed); + rend_service_descriptor_free(test_parsed); tor_free(test_intro_content); return (res >= 0); } @@ -414,6 +425,8 @@ void rend_encoded_v2_service_descriptor_free( rend_encoded_v2_service_descriptor_t *desc) { + if (!desc) + return; tor_free(desc->desc_str); tor_free(desc); } @@ -422,10 +435,11 @@ rend_encoded_v2_service_descriptor_free( void rend_intro_point_free(rend_intro_point_t *intro) { - if (intro->extend_info) - extend_info_free(intro->extend_info); - if (intro->intro_key) - crypto_free_pk_env(intro->intro_key); + if (!intro) + return; + + extend_info_free(intro->extend_info); + crypto_free_pk_env(intro->intro_key); tor_free(intro); } @@ -618,7 +632,8 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, } if (router_append_dirobj_signature(desc_str + written, desc_len - written, - desc_digest, service_key) < 0) { + desc_digest, DIGEST_LEN, + service_key) < 0) { log_warn(LD_BUG, "Couldn't sign desc."); rend_encoded_v2_service_descriptor_free(enc); goto err; @@ -655,61 +670,6 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, return seconds_valid; } -/** Encode a service descriptor for <b>desc</b>, and sign it with - * <b>key</b>. Store the descriptor in *<b>str_out</b>, and set - * *<b>len_out</b> to its length. - */ -int -rend_encode_service_descriptor(rend_service_descriptor_t *desc, - crypto_pk_env_t *key, - char **str_out, size_t *len_out) -{ - char *cp; - char *end; - int i, r; - size_t asn1len; - size_t buflen = - PK_BYTES*2*(smartlist_len(desc->intro_nodes)+2);/*Too long, but ok*/ - cp = *str_out = tor_malloc(buflen); - end = cp + PK_BYTES*2*(smartlist_len(desc->intro_nodes)+1); - r = crypto_pk_asn1_encode(desc->pk, cp+2, end-(cp+2)); - if (r < 0) { - tor_free(*str_out); - return -1; - } - asn1len = r; - set_uint16(cp, htons((uint16_t)asn1len)); - cp += 2+asn1len; - set_uint32(cp, htonl((uint32_t)desc->timestamp)); - cp += 4; - set_uint16(cp, htons((uint16_t)smartlist_len(desc->intro_nodes))); - cp += 2; - for (i=0; i < smartlist_len(desc->intro_nodes); ++i) { - rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i); - char ipoint[HEX_DIGEST_LEN+2]; - const size_t ipoint_len = HEX_DIGEST_LEN+1; - ipoint[0] = '$'; - base16_encode(ipoint+1, HEX_DIGEST_LEN+1, - intro->extend_info->identity_digest, - DIGEST_LEN); - tor_assert(strlen(ipoint) == ipoint_len); - /* Assert that appending ipoint and its NUL won't over overrun the - * buffer. */ - tor_assert(cp + ipoint_len+1 < *str_out + buflen); - memcpy(cp, ipoint, ipoint_len+1); - cp += ipoint_len+1; - } - note_crypto_pk_op(REND_SERVER); - r = crypto_pk_private_sign_digest(key, cp, *str_out, cp-*str_out); - if (r<0) { - tor_free(*str_out); - return -1; - } - cp += r; - *len_out = (size_t)(cp-*str_out); - return 0; -} - /** Parse a service descriptor at <b>str</b> (<b>len</b> bytes). On * success, return a newly alloced service_descriptor_t. On failure, * return NULL. @@ -826,22 +786,27 @@ rend_cache_init(void) /** Helper: free storage held by a single service descriptor cache entry. */ static void -_rend_cache_entry_free(void *p) +rend_cache_entry_free(rend_cache_entry_t *e) { - rend_cache_entry_t *e = p; + if (!e) + return; rend_service_descriptor_free(e->parsed); tor_free(e->desc); tor_free(e); } +static void +_rend_cache_entry_free(void *p) +{ + rend_cache_entry_free(p); +} + /** Free all storage held by the service descriptor cache. */ void rend_cache_free_all(void) { - if (rend_cache) - strmap_free(rend_cache, _rend_cache_entry_free); - if (rend_cache_v2_dir) - digestmap_free(rend_cache_v2_dir, _rend_cache_entry_free); + strmap_free(rend_cache, _rend_cache_entry_free); + digestmap_free(rend_cache_v2_dir, _rend_cache_entry_free); rend_cache = NULL; rend_cache_v2_dir = NULL; } @@ -862,7 +827,7 @@ rend_cache_clean(void) ent = (rend_cache_entry_t*)val; if (ent->parsed->timestamp < cutoff) { iter = strmap_iter_next_rmv(rend_cache, iter); - _rend_cache_entry_free(ent); + rend_cache_entry_free(ent); } else { iter = strmap_iter_next(rend_cache, iter); } @@ -888,9 +853,9 @@ rend_cache_clean_v2_descs_as_dir(void) char key_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; base32_encode(key_base32, sizeof(key_base32), key, DIGEST_LEN); log_info(LD_REND, "Removing descriptor with ID '%s' from cache", - safe_str(key_base32)); + safe_str_client(key_base32)); iter = digestmap_iter_next_rmv(rend_cache_v2_dir, iter); - _rend_cache_entry_free(ent); + rend_cache_entry_free(ent); } else { iter = digestmap_iter_next(rend_cache_v2_dir, iter); } @@ -966,6 +931,11 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e) } if (!*e) return 0; + tor_assert((*e)->parsed && (*e)->parsed->intro_nodes); + /* XXX022 hack for now, to return "not found" if there are no intro + * points remaining. See bug 997. */ + if (smartlist_len((*e)->parsed->intro_nodes) == 0) + return 0; return 1; } @@ -1044,7 +1014,6 @@ rend_cache_store(const char *desc, size_t desc_len, int published) char query[REND_SERVICE_ID_LEN_BASE32+1]; char key[REND_SERVICE_ID_LEN_BASE32+2]; /* 0<query>\0 */ time_t now; - or_options_t *options = get_options(); tor_assert(rend_cache); parsed = rend_parse_service_descriptor(desc,desc_len); if (!parsed) { @@ -1059,13 +1028,15 @@ rend_cache_store(const char *desc, size_t desc_len, int published) now = time(NULL); if (parsed->timestamp < now-REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) { log_fn(LOG_PROTOCOL_WARN, LD_REND, - "Service descriptor %s is too old.", safe_str(query)); + "Service descriptor %s is too old.", + safe_str_client(query)); rend_service_descriptor_free(parsed); return -2; } if (parsed->timestamp > now+REND_CACHE_MAX_SKEW) { log_fn(LOG_PROTOCOL_WARN, LD_REND, - "Service descriptor %s is too far in the future.", safe_str(query)); + "Service descriptor %s is too far in the future.", + safe_str_client(query)); rend_service_descriptor_free(parsed); return -2; } @@ -1073,25 +1044,22 @@ rend_cache_store(const char *desc, size_t desc_len, int published) tor_snprintf(key, sizeof(key), "2%s", query); if (!published && strmap_get_lc(rend_cache, key)) { log_info(LD_REND, "We already have a v2 descriptor for service %s.", - safe_str(query)); + safe_str_client(query)); rend_service_descriptor_free(parsed); return -1; } - /* report novel publication to statistics */ - if (published && options->HSAuthorityRecordStats) { - hs_usage_note_publish_total(query, now); - } tor_snprintf(key, sizeof(key), "0%s", query); e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, key); if (e && e->parsed->timestamp > parsed->timestamp) { log_info(LD_REND,"We already have a newer service descriptor %s with the " - "same ID and version.", safe_str(query)); + "same ID and version.", + safe_str_client(query)); rend_service_descriptor_free(parsed); return 0; } if (e && e->len == desc_len && !memcmp(desc,e->desc,desc_len)) { log_info(LD_REND,"We already have this service descriptor %s.", - safe_str(query)); + safe_str_client(query)); e->received = time(NULL); rend_service_descriptor_free(parsed); return 0; @@ -1099,10 +1067,6 @@ rend_cache_store(const char *desc, size_t desc_len, int published) if (!e) { e = tor_malloc_zero(sizeof(rend_cache_entry_t)); strmap_set_lc(rend_cache, key, e); - /* report novel publication to statistics */ - if (published && options->HSAuthorityRecordStats) { - hs_usage_note_publish_novel(query, now); - } } else { rend_service_descriptor_free(e->parsed); tor_free(e->desc); @@ -1114,7 +1078,7 @@ rend_cache_store(const char *desc, size_t desc_len, int published) memcpy(e->desc, desc, desc_len); log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.", - safe_str(query), (int)desc_len); + safe_str_client(query), (int)desc_len); return 1; } @@ -1165,7 +1129,7 @@ rend_cache_store_v2_desc_as_dir(const char *desc) if (!hid_serv_responsible_for_desc_id(desc_id)) { log_info(LD_REND, "Service descriptor with desc ID %s is not in " "interval that we are responsible for.", - safe_str(desc_id_base32)); + safe_str_client(desc_id_base32)); goto skip; } /* Is descriptor too old? */ @@ -1294,7 +1258,8 @@ rend_cache_store_v2_desc_as_client(const char *desc, /* Decode/decrypt introduction points. */ if (intro_content) { if (rend_query->auth_type != REND_NO_AUTH && - rend_query->descriptor_cookie) { + !tor_mem_is_zero(rend_query->descriptor_cookie, + sizeof(rend_query->descriptor_cookie))) { char *ipos_decrypted = NULL; size_t ipos_decrypted_size; if (rend_decrypt_introduction_points(&ipos_decrypted, @@ -1329,14 +1294,14 @@ rend_cache_store_v2_desc_as_client(const char *desc, /* Is descriptor too old? */ if (parsed->timestamp < now - REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) { log_warn(LD_REND, "Service descriptor with service ID %s is too old.", - safe_str(service_id)); + safe_str_client(service_id)); retval = -2; goto err; } /* Is descriptor too far in the future? */ if (parsed->timestamp > now + REND_CACHE_MAX_SKEW) { log_warn(LD_REND, "Service descriptor with service ID %s is too far in " - "the future.", safe_str(service_id)); + "the future.", safe_str_client(service_id)); retval = -2; goto err; } @@ -1344,7 +1309,7 @@ rend_cache_store_v2_desc_as_client(const char *desc, tor_snprintf(key, sizeof(key), "0%s", service_id); if (strmap_get_lc(rend_cache, key)) { log_info(LD_REND, "We already have a v0 descriptor for service ID %s.", - safe_str(service_id)); + safe_str_client(service_id)); retval = -1; goto err; } @@ -1354,14 +1319,14 @@ rend_cache_store_v2_desc_as_client(const char *desc, if (e && e->parsed->timestamp > parsed->timestamp) { log_info(LD_REND, "We already have a newer service descriptor for " "service ID %s with the same desc ID and version.", - safe_str(service_id)); + safe_str_client(service_id)); retval = 0; goto err; } /* Do we already have this descriptor? */ if (e && !strcmp(desc, e->desc)) { log_info(LD_REND,"We already have this service descriptor %s.", - safe_str(service_id)); + safe_str_client(service_id)); e->received = time(NULL); retval = 0; goto err; @@ -1379,12 +1344,11 @@ rend_cache_store_v2_desc_as_client(const char *desc, strlcpy(e->desc, desc, encoded_size + 1); e->len = encoded_size; log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.", - safe_str(service_id), (int)encoded_size); + safe_str_client(service_id), (int)encoded_size); return 1; err: - if (parsed) - rend_service_descriptor_free(parsed); + rend_service_descriptor_free(parsed); tor_free(intro_content); return retval; } diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h new file mode 100644 index 0000000000..d3313faf5a --- /dev/null +++ b/src/or/rendcommon.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file rendcommon.h + * \brief Header file for rendcommon.c. + **/ + +#ifndef _TOR_RENDCOMMON_H +#define _TOR_RENDCOMMON_H + +/** Free all storage associated with <b>data</b> */ +static INLINE void +rend_data_free(rend_data_t *data) +{ + tor_free(data); +} + +int rend_cmp_service_ids(const char *one, const char *two); + +void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, + int command, size_t length, + const uint8_t *payload); + +void rend_service_descriptor_free(rend_service_descriptor_t *desc); +rend_service_descriptor_t *rend_parse_service_descriptor(const char *str, + size_t len); +int rend_get_service_id(crypto_pk_env_t *pk, char *out); +void rend_encoded_v2_service_descriptor_free( + rend_encoded_v2_service_descriptor_t *desc); +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_free_all(void); +int rend_valid_service_id(const char *query); +int rend_cache_lookup_desc(const char *query, int version, const char **desc, + size_t *desc_len); +int rend_cache_lookup_entry(const char *query, int version, + rend_cache_entry_t **entry_out); +int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc); +int rend_cache_store(const char *desc, size_t desc_len, int published); +int rend_cache_store_v2_desc_as_client(const char *desc, + const rend_data_t *rend_query); +int rend_cache_store_v2_desc_as_dir(const char *desc); +int rend_cache_size(void); +int rend_encode_v2_descriptors(smartlist_t *descs_out, + rend_service_descriptor_t *desc, time_t now, + uint8_t period, rend_auth_type_t auth_type, + crypto_pk_env_t *client_key, + smartlist_t *client_cookies); +int rend_compute_v2_desc_id(char *desc_id_out, const char *service_id, + const char *descriptor_cookie, + time_t now, uint8_t replica); +int rend_id_is_in_interval(const char *a, const char *b, const char *c); +void rend_get_descriptor_id_bytes(char *descriptor_id_out, + const char *service_id, + const char *secret_id_part); + +#endif + diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 23add316a8..bc36a4e117 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -8,6 +8,11 @@ **/ #include "or.h" +#include "circuitlist.h" +#include "config.h" +#include "relay.h" +#include "rendmid.h" +#include "rephist.h" /** Respond to an ESTABLISH_INTRO cell by checking the signed data and * setting the circuit's purpose and service pk digest. diff --git a/src/or/rendmid.h b/src/or/rendmid.h new file mode 100644 index 0000000000..f06dd3d85e --- /dev/null +++ b/src/or/rendmid.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file rendmid.h + * \brief Header file for rendmid.c. + **/ + +#ifndef _TOR_RENDMID_H +#define _TOR_RENDMID_H + +int rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, + size_t request_len); +int rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, + size_t request_len); +int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, + size_t request_len); +int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, + size_t request_len); + +#endif + diff --git a/src/or/rendservice.c b/src/or/rendservice.c index f5917bc973..f06c98337a 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -8,10 +8,23 @@ **/ #include "or.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "directory.h" +#include "networkstatus.h" +#include "rendclient.h" +#include "rendcommon.h" +#include "rendservice.h" +#include "router.h" +#include "relay.h" +#include "rephist.h" +#include "routerlist.h" +#include "routerparse.h" static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro, - const char *pk_digest, - int desc_version); + const char *pk_digest); /** Represents the mapping from a virtual port of a rendezvous service to * a real port on some IP. @@ -42,8 +55,6 @@ typedef struct rend_service_t { /* Fields specified in config file */ char *directory; /**< where in the filesystem it stores it */ smartlist_t *ports; /**< List of rend_service_port_config_t */ - int descriptor_version; /**< Rendezvous descriptor version that will be - * published. */ rend_auth_type_t auth_type; /**< Client authorization type or 0 if no client * authorization is performed. */ smartlist_t *clients; /**< List of rend_authorized_client_t's of @@ -58,7 +69,7 @@ typedef struct rend_service_t { * or are trying to establish. */ time_t intro_period_started; /**< Start of the current period to build * introduction points. */ - int n_intro_circuits_launched; /**< count of intro circuits we have + int n_intro_circuits_launched; /**< Count of intro circuits we have * established in this period. */ rend_service_descriptor_t *desc; /**< Current hidden service descriptor. */ time_t desc_is_dirty; /**< Time at which changes to the hidden service @@ -90,7 +101,8 @@ num_rend_services(void) static void rend_authorized_client_free(rend_authorized_client_t *client) { - if (!client) return; + if (!client) + return; if (client->client_key) crypto_free_pk_env(client->client_key); tor_free(client->client_name); @@ -109,7 +121,9 @@ rend_authorized_client_strmap_item_free(void *authorized_client) static void rend_service_free(rend_service_t *service) { - if (!service) return; + if (!service) + return; + tor_free(service->directory); SMARTLIST_FOREACH(service->ports, void*, p, tor_free(p)); smartlist_free(service->ports); @@ -120,15 +134,14 @@ rend_service_free(rend_service_t *service) rend_intro_point_free(intro);); smartlist_free(service->intro_nodes); } - if (service->desc) - rend_service_descriptor_free(service->desc); + + rend_service_descriptor_free(service->desc); if (service->clients) { SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, c, rend_authorized_client_free(c);); smartlist_free(service->clients); } - if (service->accepted_intros) - digestmap_free(service->accepted_intros, _tor_free); + digestmap_free(service->accepted_intros, _tor_free); tor_free(service); } @@ -137,9 +150,9 @@ rend_service_free(rend_service_t *service) void rend_service_free_all(void) { - if (!rend_service_list) { + if (!rend_service_list) return; - } + SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr, rend_service_free(ptr)); smartlist_free(rend_service_list); @@ -156,36 +169,6 @@ rend_add_service(rend_service_t *service) service->intro_nodes = smartlist_create(); - /* If the service is configured to publish unversioned (v0) and versioned - * descriptors (v2 or higher), split it up into two separate services - * (unless it is configured to perform client authorization). */ - if (service->descriptor_version == -1) { - if (service->auth_type == REND_NO_AUTH) { - rend_service_t *v0_service = tor_malloc_zero(sizeof(rend_service_t)); - v0_service->directory = tor_strdup(service->directory); - v0_service->ports = smartlist_create(); - SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p, { - rend_service_port_config_t *copy = - tor_malloc_zero(sizeof(rend_service_port_config_t)); - memcpy(copy, p, sizeof(rend_service_port_config_t)); - smartlist_add(v0_service->ports, copy); - }); - v0_service->intro_period_started = service->intro_period_started; - v0_service->descriptor_version = 0; /* Unversioned descriptor. */ - v0_service->auth_type = REND_NO_AUTH; - rend_add_service(v0_service); - } - - service->descriptor_version = 2; /* Versioned descriptor. */ - } - - if (service->auth_type != REND_NO_AUTH && !service->descriptor_version) { - log_warn(LD_CONFIG, "Hidden service with client authorization and " - "version 0 descriptors configured; ignoring."); - rend_service_free(service); - return; - } - if (service->auth_type != REND_NO_AUTH && smartlist_len(service->clients) == 0) { log_warn(LD_CONFIG, "Hidden service with client authorization but no " @@ -297,7 +280,7 @@ rend_config_services(or_options_t *options, int validate_only) for (line = options->RendConfigLines; line; line = line->next) { if (!strcasecmp(line->key, "HiddenServiceDir")) { - if (service) { + if (service) { /* register the one we just finished parsing */ if (validate_only) rend_service_free(service); else @@ -307,7 +290,6 @@ rend_config_services(or_options_t *options, int validate_only) service->directory = tor_strdup(line->value); service->ports = smartlist_create(); service->intro_period_started = time(NULL); - service->descriptor_version = -1; /**< All descriptor versions. */ continue; } if (!service) { @@ -433,35 +415,13 @@ rend_config_services(or_options_t *options, int validate_only) return -1; } } else { - smartlist_t *versions; - char *version_str; - int i, version, ver_ok=1, versions_bitmask = 0; tor_assert(!strcasecmp(line->key, "HiddenServiceVersion")); - versions = smartlist_create(); - smartlist_split_string(versions, line->value, ",", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - for (i = 0; i < smartlist_len(versions); i++) { - version_str = smartlist_get(versions, i); - if (strlen(version_str) != 1 || strspn(version_str, "02") != 1) { - log_warn(LD_CONFIG, - "HiddenServiceVersion can only be 0 and/or 2."); - SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp)); - smartlist_free(versions); - rend_service_free(service); - return -1; - } - version = (int)tor_parse_long(version_str, 10, 0, INT_MAX, &ver_ok, - NULL); - if (!ver_ok) - continue; - versions_bitmask |= 1 << version; + if (strcmp(line->value, "2")) { + log_warn(LD_CONFIG, + "The only supported HiddenServiceVersion is 2."); + rend_service_free(service); + return -1; } - /* If exactly one version is set, change descriptor_version to that - * value; otherwise leave it at -1. */ - if (versions_bitmask == 1 << 0) service->descriptor_version = 0; - if (versions_bitmask == 1 << 2) service->descriptor_version = 2; - SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp)); - smartlist_free(versions); } } if (service) { @@ -483,8 +443,7 @@ rend_config_services(or_options_t *options, int validate_only) * probably ok? */ SMARTLIST_FOREACH(rend_service_list, rend_service_t *, new, { SMARTLIST_FOREACH(old_service_list, rend_service_t *, old, { - if (!strcmp(old->directory, new->directory) && - old->descriptor_version == new->descriptor_version) { + if (!strcmp(old->directory, new->directory)) { smartlist_add_all(new->intro_nodes, old->intro_nodes); smartlist_clear(old->intro_nodes); smartlist_add(surviving_services, old); @@ -507,18 +466,16 @@ rend_config_services(or_options_t *options, int validate_only) tor_assert(oc->rend_data); SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, { if (!memcmp(ptr->pk_digest, oc->rend_data->rend_pk_digest, - DIGEST_LEN) && - ptr->descriptor_version == oc->rend_data->rend_desc_version) { + DIGEST_LEN)) { keep_it = 1; break; } }); if (keep_it) continue; - log_info(LD_REND, "Closing intro point %s for service %s version %d.", - safe_str(oc->build_state->chosen_exit->nickname), - oc->rend_data->onion_address, - oc->rend_data->rend_desc_version); + log_info(LD_REND, "Closing intro point %s for service %s.", + safe_str_client(oc->build_state->chosen_exit->nickname), + oc->rend_data->onion_address); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); /* XXXX Is there another reason we should use here? */ } @@ -541,14 +498,13 @@ rend_service_update_descriptor(rend_service_t *service) rend_service_descriptor_t *d; origin_circuit_t *circ; int i; - if (service->desc) { - rend_service_descriptor_free(service->desc); - service->desc = NULL; - } + + rend_service_descriptor_free(service->desc); + service->desc = NULL; + d = service->desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); d->pk = crypto_pk_dup_key(service->private_key); d->timestamp = time(NULL); - d->version = service->descriptor_version; d->intro_nodes = smartlist_create(); /* Support intro protocols 2 and 3. */ d->protocols = (1 << 2) + (1 << 3); @@ -556,7 +512,7 @@ rend_service_update_descriptor(rend_service_t *service) for (i = 0; i < smartlist_len(service->intro_nodes); ++i) { rend_intro_point_t *intro_svc = smartlist_get(service->intro_nodes, i); rend_intro_point_t *intro_desc; - circ = find_intro_circuit(intro_svc, service->pk_digest, d->version); + circ = find_intro_circuit(intro_svc, service->pk_digest); if (!circ || circ->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) continue; @@ -797,17 +753,15 @@ rend_service_load_keys(void) return r; } -/** Return the service whose public key has a digest of <b>digest</b> and - * which publishes the given descriptor <b>version</b>. Return NULL if no - * such service exists. +/** Return the service whose public key has a digest of <b>digest</b>, or + * NULL if no such service exists. */ static rend_service_t * -rend_service_get_by_pk_digest_and_version(const char* digest, - uint8_t version) +rend_service_get_by_pk_digest(const char* digest) { SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s, - if (!memcmp(s->pk_digest,digest,DIGEST_LEN) && - s->descriptor_version == version) return s); + if (!memcmp(s->pk_digest,digest,DIGEST_LEN)) + return s); return NULL; } @@ -944,21 +898,16 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, } /* look up service depending on circuit. */ - service = rend_service_get_by_pk_digest_and_version( - circuit->rend_data->rend_pk_digest, - circuit->rend_data->rend_desc_version); + service = rend_service_get_by_pk_digest( + circuit->rend_data->rend_pk_digest); if (!service) { log_warn(LD_REND, "Got an INTRODUCE2 cell for an unrecognized service %s.", escaped(serviceid)); return -1; } - /* if descriptor version is 2, use intro key instead of service key. */ - if (circuit->rend_data->rend_desc_version == 0) { - intro_key = service->private_key; - } else { - intro_key = circuit->intro_key; - } + /* use intro key instead of service key. */ + intro_key = circuit->intro_key; /* first DIGEST_LEN bytes of request is intro or service pk digest */ crypto_pk_get_digest(intro_key, intro_key_digest); @@ -988,7 +937,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, len = r; if (*buf == 3) { /* Version 3 INTRODUCE2 cell. */ - time_t ts = 0, now = time(NULL); + time_t ts = 0; v3_shift = 1; auth_type = buf[1]; switch (auth_type) { @@ -1082,7 +1031,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, router = router_get_by_nickname(rp_nickname, 0); if (!router) { log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.", - escaped_safe_str(rp_nickname)); + escaped_safe_str_client(rp_nickname)); /* XXXX Add a no-such-router reason? */ reason = END_CIRC_REASON_TORPROTOCOL; goto err; @@ -1157,7 +1106,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, reason = END_CIRC_REASON_INTERNAL; goto err; } - if (crypto_dh_compute_secret(dh, ptr+REND_COOKIE_LEN, DH_KEY_LEN, keys, + if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, ptr+REND_COOKIE_LEN, + DH_KEY_LEN, keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) { log_warn(LD_BUG, "Internal error: couldn't complete DH handshake"); reason = END_CIRC_REASON_INTERNAL; @@ -1167,7 +1117,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, circ_needs_uptime = rend_service_requires_uptime(service); /* help predict this next time */ - rep_hist_note_used_internal(time(NULL), circ_needs_uptime, 1); + rep_hist_note_used_internal(now, circ_needs_uptime, 1); /* Launch a circuit to alice's chosen rendezvous point. */ @@ -1183,14 +1133,16 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (!launched) { /* give up */ log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous " "point %s for service %s.", - escaped_safe_str(extend_info->nickname), serviceid); + escaped_safe_str_client(extend_info->nickname), + serviceid); reason = END_CIRC_REASON_CONNECTFAILED; goto err; } log_info(LD_REND, "Accepted intro; launching circuit to %s " "(cookie %s) for service %s.", - escaped_safe_str(extend_info->nickname), hexcookie, serviceid); + escaped_safe_str_client(extend_info->nickname), + hexcookie, serviceid); tor_assert(launched->build_state); /* Fill in the circuit's state. */ launched->rend_data = tor_malloc_zero(sizeof(rend_data_t)); @@ -1200,11 +1152,10 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, memcpy(launched->rend_data->rend_cookie, r_cookie, REND_COOKIE_LEN); strlcpy(launched->rend_data->onion_address, service->service_id, sizeof(launched->rend_data->onion_address)); - launched->rend_data->rend_desc_version = service->descriptor_version; launched->build_state->pending_final_cpath = cpath = tor_malloc_zero(sizeof(crypt_path_t)); cpath->magic = CRYPT_PATH_MAGIC; - launched->build_state->expiry_time = time(NULL) + MAX_REND_TIMEOUT; + launched->build_state->expiry_time = now + MAX_REND_TIMEOUT; cpath->dh_handshake_state = dh; dh = NULL; @@ -1286,7 +1237,7 @@ rend_service_launch_establish_intro(rend_service_t *service, log_info(LD_REND, "Launching circuit to introduction point %s for service %s", - escaped_safe_str(intro->extend_info->nickname), + escaped_safe_str_client(intro->extend_info->nickname), service->service_id); rep_hist_note_used_internal(time(NULL), 1, 0); @@ -1299,7 +1250,7 @@ rend_service_launch_establish_intro(rend_service_t *service, if (!launched) { log_info(LD_REND, "Can't launch circuit to establish introduction at %s.", - escaped_safe_str(intro->extend_info->nickname)); + escaped_safe_str_client(intro->extend_info->nickname)); return -1; } @@ -1322,18 +1273,16 @@ rend_service_launch_establish_intro(rend_service_t *service, strlcpy(launched->rend_data->onion_address, service->service_id, sizeof(launched->rend_data->onion_address)); memcpy(launched->rend_data->rend_pk_digest, service->pk_digest, DIGEST_LEN); - launched->rend_data->rend_desc_version = service->descriptor_version; - if (service->descriptor_version == 2) - launched->intro_key = crypto_pk_dup_key(intro->intro_key); + launched->intro_key = crypto_pk_dup_key(intro->intro_key); if (launched->_base.state == CIRCUIT_STATE_OPEN) rend_service_intro_has_opened(launched); return 0; } /** Return the number of introduction points that are or have been - * established for the given service address and rendezvous version. */ + * established for the given service address in <b>query</b>. */ static int -count_established_intro_points(const char *query, int rend_version) +count_established_intro_points(const char *query) { int num_ipos = 0; circuit_t *circ; @@ -1344,7 +1293,6 @@ count_established_intro_points(const char *query, int rend_version) circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) { origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ); if (oc->rend_data && - oc->rend_data->rend_desc_version == rend_version && !rend_cmp_service_ids(query, oc->rend_data->onion_address)) num_ipos++; } @@ -1374,9 +1322,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN); - service = rend_service_get_by_pk_digest_and_version( - circuit->rend_data->rend_pk_digest, - circuit->rend_data->rend_desc_version); + service = rend_service_get_by_pk_digest( + circuit->rend_data->rend_pk_digest); if (!service) { log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.", serviceid, circuit->_base.n_circ_id); @@ -1386,8 +1333,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) /* If we already have enough introduction circuits for this service, * redefine this one as a general circuit. */ - if (count_established_intro_points(serviceid, - circuit->rend_data->rend_desc_version) > NUM_INTRO_POINTS) { + if (count_established_intro_points(serviceid) > NUM_INTRO_POINTS) { log_info(LD_CIRC|LD_REND, "We have just finished an introduction " "circuit, but we already have enough. Redefining purpose to " "general."); @@ -1400,13 +1346,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) "Established circuit %d as introduction point for service %s", circuit->_base.n_circ_id, serviceid); - /* If the introduction point will not be used in an unversioned - * descriptor, use the intro key instead of the service key in - * ESTABLISH_INTRO. */ - if (service->descriptor_version == 0) - intro_key = service->private_key; - else - intro_key = circuit->intro_key; + /* Use the intro key instead of the service key in ESTABLISH_INTRO. */ + intro_key = circuit->intro_key; /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */ r = crypto_pk_asn1_encode(intro_key, buf+2, RELAY_PAYLOAD_SIZE-2); @@ -1466,9 +1407,8 @@ rend_service_intro_established(origin_circuit_t *circuit, goto err; } tor_assert(circuit->rend_data); - service = rend_service_get_by_pk_digest_and_version( - circuit->rend_data->rend_pk_digest, - circuit->rend_data->rend_desc_version); + service = rend_service_get_by_pk_digest( + circuit->rend_data->rend_pk_digest); if (!service) { log_warn(LD_REND, "Unknown service on introduction circuit %d.", circuit->_base.n_circ_id); @@ -1518,9 +1458,8 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) "cookie %s for service %s", circuit->_base.n_circ_id, hexcookie, serviceid); - service = rend_service_get_by_pk_digest_and_version( - circuit->rend_data->rend_pk_digest, - circuit->rend_data->rend_desc_version); + service = rend_service_get_by_pk_digest( + circuit->rend_data->rend_pk_digest); if (!service) { log_warn(LD_GENERAL, "Internal error: unrecognized service ID on " "introduction circuit."); @@ -1576,13 +1515,12 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) */ /** Return the (possibly non-open) introduction circuit ending at - * <b>intro</b> for the service whose public key is <b>pk_digest</b> and - * which publishes descriptor of version <b>desc_version</b>. Return - * NULL if no such service is found. + * <b>intro</b> for the service whose public key is <b>pk_digest</b>. + * (<b>desc_version</b> is ignored). Return NULL if no such service is + * found. */ static origin_circuit_t * -find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest, - int desc_version) +find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest) { origin_circuit_t *circ = NULL; @@ -1591,8 +1529,7 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest, CIRCUIT_PURPOSE_S_INTRO))) { if (!memcmp(circ->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN) && - circ->rend_data && - circ->rend_data->rend_desc_version == desc_version) { + circ->rend_data) { return circ; } } @@ -1602,8 +1539,7 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest, CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) { if (!memcmp(circ->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN) && - circ->rend_data && - circ->rend_data->rend_desc_version == desc_version) { + circ->rend_data) { return circ; } } @@ -1636,6 +1572,7 @@ 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; hs_dir = smartlist_get(responsible_dirs, j); if (smartlist_digest_isin(renddesc->successful_uploads, hs_dir->identity_digest)) @@ -1657,15 +1594,18 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, strlen(desc->desc_str), 0); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc->desc_id, DIGEST_LEN); + hs_dir_ip = tor_dup_ip(hs_dir->addr); log_info(LD_REND, "Sending publish request for v2 descriptor for " "service '%s' with descriptor ID '%s' with validity " "of %d seconds to hidden service directory '%s' on " - "port %d.", - safe_str(service_id), - safe_str(desc_id_base32), + "%s:%d.", + safe_str_client(service_id), + safe_str_client(desc_id_base32), seconds_valid, hs_dir->nickname, - hs_dir->dir_port); + hs_dir_ip, + hs_dir->or_port); + tor_free(hs_dir_ip); /* Remember successful upload to this router for next time. */ if (!smartlist_digest_isin(successful_uploads, hs_dir->identity_digest)) smartlist_add(successful_uploads, hs_dir->identity_digest); @@ -1695,9 +1635,8 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, smartlist_free(successful_uploads); } -/** Encode and sign up-to-date v0 and/or v2 service descriptors for - * <b>service</b>, and upload it/them to all the dirservers/to the - * responsible hidden service directories. +/** Encode and sign an up-to-date service descriptor for <b>service</b>, + * and upload it/them to the responsible hidden service directories. */ static void upload_service_descriptor(rend_service_t *service) @@ -1709,35 +1648,8 @@ upload_service_descriptor(rend_service_t *service) rendpostperiod = get_options()->RendPostPeriod; - /* Upload unversioned (v0) descriptor? */ - if (service->descriptor_version == 0 && - get_options()->PublishHidServDescriptors) { - char *desc; - size_t desc_len; - /* Encode the descriptor. */ - if (rend_encode_service_descriptor(service->desc, - service->private_key, - &desc, &desc_len)<0) { - log_warn(LD_BUG, "Internal error: couldn't encode service descriptor; " - "not uploading."); - return; - } - - /* Post it to the dirservers */ - rend_get_service_id(service->desc->pk, serviceid); - log_info(LD_REND, "Sending publish request for hidden service %s", - serviceid); - directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC, - ROUTER_PURPOSE_GENERAL, - HIDSERV_AUTHORITY, desc, desc_len, 0); - tor_free(desc); - service->next_upload_time = now + rendpostperiod; - uploaded = 1; - } - - /* Upload v2 descriptor? */ - if (service->descriptor_version == 2 && - get_options()->PublishHidServDescriptors) { + /* Upload descriptor? */ + if (get_options()->PublishHidServDescriptors) { networkstatus_t *c = networkstatus_get_latest_consensus(); if (c && smartlist_len(c->routerstatus_list) > 0) { int seconds_valid, i, j, num_descs; @@ -1876,8 +1788,7 @@ rend_services_introduce(void) for (j=0; j < smartlist_len(service->intro_nodes); ++j) { intro = smartlist_get(service->intro_nodes, j); router = router_get_by_digest(intro->extend_info->identity_digest); - if (!router || !find_intro_circuit(intro, service->pk_digest, - service->descriptor_version)) { + if (!router || !find_intro_circuit(intro, service->pk_digest)) { log_info(LD_REND,"Giving up on %s as intro point for %s.", intro->extend_info->nickname, service->service_id); if (service->desc) { @@ -1929,7 +1840,7 @@ rend_services_introduce(void) router_crn_flags_t flags = CRN_NEED_UPTIME; if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION) flags |= CRN_ALLOW_INVALID; - router = router_choose_random_node(NULL, intro_routers, + router = router_choose_random_node(intro_routers, options->ExcludeNodes, flags); if (!router) { log_warn(LD_REND, @@ -1941,10 +1852,8 @@ rend_services_introduce(void) smartlist_add(intro_routers, router); intro = tor_malloc_zero(sizeof(rend_intro_point_t)); intro->extend_info = extend_info_from_router(router); - if (service->descriptor_version == 2) { - intro->intro_key = crypto_new_pk_env(); - tor_assert(!crypto_pk_generate_key(intro->intro_key)); - } + intro->intro_key = crypto_new_pk_env(); + tor_assert(!crypto_pk_generate_key(intro->intro_key)); smartlist_add(service->intro_nodes, intro); log_info(LD_REND, "Picked router %s as an intro point for %s.", router->nickname, service->service_id); @@ -2037,8 +1946,7 @@ rend_consider_descriptor_republication(void) for (i=0; i < smartlist_len(rend_service_list); ++i) { service = smartlist_get(rend_service_list, i); - if (service->descriptor_version && service->desc && - !service->desc->all_uploads_performed) { + if (service->desc && !service->desc->all_uploads_performed) { /* If we failed in uploading a descriptor last time, try again *without* * updating the descriptor's contents. */ upload_service_descriptor(service); @@ -2064,10 +1972,9 @@ rend_service_dump_stats(int severity) service->directory); for (j=0; j < smartlist_len(service->intro_nodes); ++j) { intro = smartlist_get(service->intro_nodes, j); - safe_name = safe_str(intro->extend_info->nickname); + safe_name = safe_str_client(intro->extend_info->nickname); - circ = find_intro_circuit(intro, service->pk_digest, - service->descriptor_version); + circ = find_intro_circuit(intro, service->pk_digest); if (!circ) { log(severity, LD_GENERAL, " Intro point %d at %s: no circuit", j, safe_name); @@ -2098,9 +2005,8 @@ rend_service_set_connection_addr_port(edge_connection_t *conn, log_debug(LD_REND,"beginning to hunt for addr/port"); base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, circ->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN); - service = rend_service_get_by_pk_digest_and_version( - circ->rend_data->rend_pk_digest, - circ->rend_data->rend_desc_version); + service = rend_service_get_by_pk_digest( + circ->rend_data->rend_pk_digest); if (!service) { log_warn(LD_REND, "Couldn't find any service associated with pk %s on " "rendezvous circuit %d; closing.", diff --git a/src/or/rendservice.h b/src/or/rendservice.h new file mode 100644 index 0000000000..722cec1561 --- /dev/null +++ b/src/or/rendservice.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file rendservice.h + * \brief Header file for rendservice.c. + **/ + +#ifndef _TOR_RENDSERVICE_H +#define _TOR_RENDSERVICE_H + +int num_rend_services(void); +int rend_config_services(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); +void rend_hsdir_routers_changed(void); +void rend_consider_descriptor_republication(void); + +void rend_service_intro_has_opened(origin_circuit_t *circuit); +int rend_service_intro_established(origin_circuit_t *circuit, + const uint8_t *request, + size_t request_len); +void rend_service_rendezvous_has_opened(origin_circuit_t *circuit); +int rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, + size_t request_len); +void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc); +int rend_service_set_connection_addr_port(edge_connection_t *conn, + origin_circuit_t *circ); +void rend_service_dump_stats(int severity); +void rend_service_free_all(void); + +#endif + diff --git a/src/or/rephist.c b/src/or/rephist.c index 71ec0bd53c..5a57b954fd 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -6,15 +6,21 @@ * \file rephist.c * \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. + * been using, which ports we tend to want, and so on; further, + * exit port statistics and cell statistics. **/ #include "or.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" #include "ht.h" static void bw_arrays_init(void); static void predicted_ports_init(void); -static void hs_usage_init(void); /** Total number of bytes currently allocated in fields used by rephist.c. */ uint64_t rephist_total_alloc=0; @@ -185,7 +191,6 @@ rep_hist_init(void) history_map = digestmap_new(); bw_arrays_init(); predicted_ports_init(); - hs_usage_init(); } /** Helper: note that we are no longer connected to the router with history @@ -795,12 +800,12 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down) static char * rep_hist_format_router_status(or_history_t *hist, time_t now) { - char buf[1024]; char sor_buf[ISO_TIME_LEN+1]; char sod_buf[ISO_TIME_LEN+1]; double wfu; double mtbf; int up = 0, down = 0; + char *cp = NULL; if (hist->start_of_run) { format_iso_time(sor_buf, hist->start_of_run); @@ -813,7 +818,7 @@ rep_hist_format_router_status(or_history_t *hist, time_t now) wfu = get_weighted_fractional_uptime(hist, now); mtbf = get_stability(hist, now); - tor_snprintf(buf, sizeof(buf), + tor_asprintf(&cp, "%s%s%s" "%s%s%s" "wfu %0.3lf\n" @@ -831,8 +836,7 @@ rep_hist_format_router_status(or_history_t *hist, time_t now) hist->weighted_run_length, hist->total_run_weights ); - - return tor_strdup(buf); + return cp; } /** The last stability analysis document that we created, or NULL if we never @@ -1280,13 +1284,21 @@ bw_array_new(void) static bw_array_t *read_array = NULL; /** Recent history of bandwidth observations for write operations. */ static bw_array_t *write_array = NULL; - -/** Set up read_array and write_array. */ +/** Recent history of bandwidth observations for read operations for the + directory protocol. */ +static bw_array_t *dir_read_array = NULL; +/** Recent history of bandwidth observations for write operations for the + directory protocol. */ +static bw_array_t *dir_write_array = NULL; + +/** Set up [dir-]read_array and [dir-]write_array. */ static void bw_arrays_init(void) { read_array = bw_array_new(); write_array = bw_array_new(); + dir_read_array = bw_array_new(); + dir_write_array = bw_array_new(); } /** We read <b>num_bytes</b> more bytes in second <b>when</b>. @@ -1320,6 +1332,24 @@ rep_hist_note_bytes_read(size_t num_bytes, time_t when) add_obs(read_array, when, num_bytes); } +/** We wrote <b>num_bytes</b> more directory bytes in second <b>when</b>. + * (like rep_hist_note_bytes_written() above) + */ +void +rep_hist_note_dir_bytes_written(size_t num_bytes, time_t when) +{ + add_obs(dir_write_array, when, num_bytes); +} + +/** We read <b>num_bytes</b> more directory bytes in second <b>when</b>. + * (like rep_hist_note_bytes_written() above) + */ +void +rep_hist_note_dir_bytes_read(size_t num_bytes, time_t when) +{ + add_obs(dir_read_array, when, num_bytes); +} + /** Helper: Return the largest value in b->maxima. (This is equal to the * most bandwidth used in any NUM_SECS_ROLLING_MEASURE period for the last * NUM_SECS_BW_SUM_IS_VALID seconds.) @@ -1355,9 +1385,9 @@ rep_hist_bandwidth_assess(void) return (int)(U64_TO_DBL(r)/NUM_SECS_ROLLING_MEASURE); } -/** Print the bandwidth history of b (either read_array or write_array) - * into the buffer pointed to by buf. The format is simply comma - * separated numbers, from oldest to newest. +/** Print the bandwidth history of b (either [dir-]read_array or + * [dir-]write_array) into the buffer pointed to by buf. The format is + * simply comma separated numbers, from oldest to newest. * * It returns the number of bytes written. */ @@ -1410,26 +1440,42 @@ rep_hist_fill_bandwidth_history(char *buf, size_t len, bw_array_t *b) * history in its descriptor. */ char * -rep_hist_get_bandwidth_lines(int for_extrainfo) +rep_hist_get_bandwidth_lines(void) { char *buf, *cp; char t[ISO_TIME_LEN+1]; int r; - bw_array_t *b; + bw_array_t *b = NULL; + const char *desc = NULL; size_t len; - /* opt (read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n,n,n... */ - len = (60+20*NUM_TOTALS)*2; + /* opt [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */ + len = (67+21*NUM_TOTALS)*4; buf = tor_malloc_zero(len); cp = buf; - for (r=0;r<2;++r) { - b = r?read_array:write_array; + for (r=0;r<4;++r) { + switch (r) { + case 0: + b = write_array; + desc = "write-history"; + break; + case 1: + b = read_array; + desc = "read-history"; + break; + case 2: + b = dir_write_array; + desc = "dirreq-write-history"; + break; + case 3: + b = dir_read_array; + desc = "dirreq-read-history"; + break; + } tor_assert(b); format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL); - tor_snprintf(cp, len-(cp-buf), "%s%s %s (%d s) ", - for_extrainfo ? "" : "opt ", - r ? "read-history" : "write-history", t, - NUM_SECS_BW_SUM_INTERVAL); + tor_snprintf(cp, len-(cp-buf), "%s %s (%d s) ", + desc, t, NUM_SECS_BW_SUM_INTERVAL); cp += strlen(cp); cp += rep_hist_fill_bandwidth_history(cp, len-(cp-buf), b); strlcat(cp, "\n", len-(cp-buf)); @@ -1444,20 +1490,41 @@ rep_hist_update_state(or_state_t *state) { int len, r; char *buf, *cp; - smartlist_t **s_values; - time_t *s_begins; - int *s_interval; - bw_array_t *b; + smartlist_t **s_values = NULL; + time_t *s_begins = NULL; + int *s_interval = NULL; + bw_array_t *b = NULL; len = 20*NUM_TOTALS+1; buf = tor_malloc_zero(len); - for (r=0;r<2;++r) { - b = r?read_array:write_array; - s_begins = r?&state->BWHistoryReadEnds :&state->BWHistoryWriteEnds; - s_interval= r?&state->BWHistoryReadInterval:&state->BWHistoryWriteInterval; - s_values = r?&state->BWHistoryReadValues :&state->BWHistoryWriteValues; - + for (r=0;r<4;++r) { + switch (r) { + case 0: + b = write_array; + s_begins = &state->BWHistoryWriteEnds; + s_interval = &state->BWHistoryWriteInterval; + s_values = &state->BWHistoryWriteValues; + break; + case 1: + b = read_array; + s_begins = &state->BWHistoryReadEnds; + s_interval = &state->BWHistoryReadInterval; + s_values = &state->BWHistoryReadValues; + break; + case 2: + b = dir_write_array; + s_begins = &state->BWHistoryDirWriteEnds; + s_interval = &state->BWHistoryDirWriteInterval; + s_values = &state->BWHistoryDirWriteValues; + break; + case 3: + b = dir_read_array; + s_begins = &state->BWHistoryDirReadEnds; + s_interval = &state->BWHistoryDirReadInterval; + s_values = &state->BWHistoryDirReadValues; + break; + } if (*s_values) { SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val)); smartlist_free(*s_values); @@ -1497,23 +1564,45 @@ rep_hist_update_state(or_state_t *state) int rep_hist_load_state(or_state_t *state, char **err) { - time_t s_begins, start; + time_t s_begins = 0, start; time_t now = time(NULL); uint64_t v; int r,i,ok; int all_ok = 1; - int s_interval; - smartlist_t *s_values; - bw_array_t *b; + int s_interval = 0; + smartlist_t *s_values = NULL; + bw_array_t *b = NULL; /* Assert they already have been malloced */ tor_assert(read_array && write_array); - for (r=0;r<2;++r) { - b = r?read_array:write_array; - s_begins = r?state->BWHistoryReadEnds:state->BWHistoryWriteEnds; - s_interval = r?state->BWHistoryReadInterval:state->BWHistoryWriteInterval; - s_values = r?state->BWHistoryReadValues:state->BWHistoryWriteValues; + for (r=0;r<4;++r) { + switch (r) { + case 0: + b = write_array; + s_begins = state->BWHistoryWriteEnds; + s_interval = state->BWHistoryWriteInterval; + s_values = state->BWHistoryWriteValues; + break; + case 1: + b = read_array; + s_begins = state->BWHistoryReadEnds; + s_interval = state->BWHistoryReadInterval; + s_values = state->BWHistoryReadValues; + break; + case 2: + b = dir_write_array; + s_begins = state->BWHistoryDirWriteEnds; + s_interval = state->BWHistoryDirWriteInterval; + s_values = state->BWHistoryDirWriteValues; + break; + case 3: + b = dir_read_array; + s_begins = state->BWHistoryDirReadEnds; + s_interval = state->BWHistoryDirReadInterval; + s_values = state->BWHistoryDirReadValues; + break; + } if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) { start = s_begins - s_interval*(smartlist_len(s_values)); if (start > now) @@ -1715,8 +1804,8 @@ rep_hist_get_predicted_internal(time_t now, int *need_uptime, return 0; /* too long ago */ if (predicted_internal_uptime_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now) *need_uptime = 1; - if (predicted_internal_capacity_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now) - *need_capacity = 1; + // Always predict that we need capacity. + *need_capacity = 1; return 1; } @@ -1845,564 +1934,517 @@ dump_pk_ops(int severity) pk_op_counts.n_rend_server_ops); } -/** Free all storage held by the OR/link history caches, by the - * bandwidth history arrays, or by the port history. */ +/*** Exit port statistics ***/ + +/* Some constants */ +/** To what multiple should byte numbers be rounded up? */ +#define EXIT_STATS_ROUND_UP_BYTES 1024 +/** To what multiple should stream counts be rounded up? */ +#define EXIT_STATS_ROUND_UP_STREAMS 4 +/** Number of TCP ports */ +#define EXIT_STATS_NUM_PORTS 65536 +/** Top n ports that will be included in exit stats. */ +#define EXIT_STATS_TOP_N_PORTS 10 + +/* The following data structures are arrays and no fancy smartlists or maps, + * so that all write operations can be done in constant time. This comes at + * the price of some memory (1.25 MB) and linear complexity when writing + * stats for measuring relays. */ +/** Number of bytes read in current period by exit port */ +static uint64_t *exit_bytes_read = NULL; +/** Number of bytes written in current period by exit port */ +static uint64_t *exit_bytes_written = NULL; +/** Number of streams opened in current period by exit port */ +static uint32_t *exit_streams = NULL; + +/** Start time of exit stats or 0 if we're not collecting exit stats. */ +static time_t start_of_exit_stats_interval; + +/** Initialize exit port stats. */ void -rep_hist_free_all(void) +rep_hist_exit_stats_init(time_t now) { - digestmap_free(history_map, free_or_history); - tor_free(read_array); - tor_free(write_array); - tor_free(last_stability_doc); - built_last_stability_doc_at = 0; - predicted_ports_free(); + start_of_exit_stats_interval = now; + exit_bytes_read = tor_malloc_zero(EXIT_STATS_NUM_PORTS * + sizeof(uint64_t)); + exit_bytes_written = tor_malloc_zero(EXIT_STATS_NUM_PORTS * + sizeof(uint64_t)); + exit_streams = tor_malloc_zero(EXIT_STATS_NUM_PORTS * + sizeof(uint32_t)); } -/****************** hidden service usage statistics ******************/ - -/** How large are the intervals for which we track and report hidden service - * use? */ -#define NUM_SECS_HS_USAGE_SUM_INTERVAL (15*60) -/** How far in the past do we remember and publish hidden service use? */ -#define NUM_SECS_HS_USAGE_SUM_IS_VALID (24*60*60) -/** How many hidden service usage intervals do we remember? (derived) */ -#define NUM_TOTALS_HS_USAGE (NUM_SECS_HS_USAGE_SUM_IS_VALID/ \ - NUM_SECS_HS_USAGE_SUM_INTERVAL) - -/** List element containing a service id and the count. */ -typedef struct hs_usage_list_elem_t { - /** Service id of this elem. */ - char service_id[REND_SERVICE_ID_LEN_BASE32+1]; - /** Number of occurrences for the given service id. */ - uint32_t count; - /* Pointer to next list elem */ - struct hs_usage_list_elem_t *next; -} hs_usage_list_elem_t; - -/** Ordered list that stores service ids and the number of observations. It is - * ordered by the number of occurrences in descending order. Its purpose is to - * calculate the frequency distribution when the period is over. */ -typedef struct hs_usage_list_t { - /* Pointer to the first element in the list. */ - hs_usage_list_elem_t *start; - /* Number of total occurrences for all list elements. */ - uint32_t total_count; - /* Number of service ids, i.e. number of list elements. */ - uint32_t total_service_ids; -} hs_usage_list_t; - -/** Tracks service-related observations in the current period and their - * history. */ -typedef struct hs_usage_service_related_observation_t { - /** Ordered list that stores service ids and the number of observations in - * the current period. It is ordered by the number of occurrences in - * descending order. Its purpose is to calculate the frequency distribution - * when the period is over. */ - hs_usage_list_t *list; - /** Circular arrays that store the history of observations. totals stores all - * observations, twenty (ten, five) the number of observations related to a - * service id being accounted for the top 20 (10, 5) percent of all - * observations. */ - uint32_t totals[NUM_TOTALS_HS_USAGE]; - uint32_t five[NUM_TOTALS_HS_USAGE]; - uint32_t ten[NUM_TOTALS_HS_USAGE]; - uint32_t twenty[NUM_TOTALS_HS_USAGE]; -} hs_usage_service_related_observation_t; - -/** Tracks the history of general period-related observations, i.e. those that - * cannot be related to a specific service id. */ -typedef struct hs_usage_general_period_related_observations_t { - /** Circular array that stores the history of observations. */ - uint32_t totals[NUM_TOTALS_HS_USAGE]; -} hs_usage_general_period_related_observations_t; - -/** Keeps information about the current observation period and its relation to - * the histories of observations. */ -typedef struct hs_usage_current_observation_period_t { - /** Where do we write the next history entry? */ - int next_idx; - /** How many values in history have been set ever? (upper bound!) */ - int num_set; - /** When did this period begin? */ - time_t start_of_current_period; - /** When does the next period begin? */ - time_t start_of_next_period; -} hs_usage_current_observation_period_t; - -/** Usage statistics for the current observation period. */ -static hs_usage_current_observation_period_t *current_period = NULL; - -/** Total number of descriptor publish requests in the current observation - * period. */ -static hs_usage_service_related_observation_t *publish_total = NULL; - -/** Number of descriptor publish requests for services that have not been - * seen before in the current observation period. */ -static hs_usage_service_related_observation_t *publish_novel = NULL; - -/** Total number of descriptor fetch requests in the current observation - * period. */ -static hs_usage_service_related_observation_t *fetch_total = NULL; - -/** Number of successful descriptor fetch requests in the current - * observation period. */ -static hs_usage_service_related_observation_t *fetch_successful = NULL; - -/** Number of descriptors stored in the current observation period. */ -static hs_usage_general_period_related_observations_t *descs = NULL; - -/** Creates an empty ordered list element. */ -static hs_usage_list_elem_t * -hs_usage_list_elem_new(void) +/** Reset counters for exit port statistics. */ +void +rep_hist_reset_exit_stats(time_t now) { - hs_usage_list_elem_t *e; - e = tor_malloc_zero(sizeof(hs_usage_list_elem_t)); - rephist_total_alloc += sizeof(hs_usage_list_elem_t); - e->count = 1; - e->next = NULL; - return e; + start_of_exit_stats_interval = now; + memset(exit_bytes_read, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t)); + memset(exit_bytes_written, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t)); + memset(exit_streams, 0, EXIT_STATS_NUM_PORTS * sizeof(uint32_t)); } -/** Creates an empty ordered list. */ -static hs_usage_list_t * -hs_usage_list_new(void) +/** Stop collecting exit port stats in a way that we can re-start doing + * so in rep_hist_exit_stats_init(). */ +void +rep_hist_exit_stats_term(void) { - hs_usage_list_t *l; - l = tor_malloc_zero(sizeof(hs_usage_list_t)); - rephist_total_alloc += sizeof(hs_usage_list_t); - l->start = NULL; - l->total_count = 0; - l->total_service_ids = 0; - return l; + start_of_exit_stats_interval = 0; + tor_free(exit_bytes_read); + tor_free(exit_bytes_written); + tor_free(exit_streams); } -/** Creates an empty structure for storing service-related observations. */ -static hs_usage_service_related_observation_t * -hs_usage_service_related_observation_new(void) -{ - hs_usage_service_related_observation_t *h; - h = tor_malloc_zero(sizeof(hs_usage_service_related_observation_t)); - rephist_total_alloc += sizeof(hs_usage_service_related_observation_t); - h->list = hs_usage_list_new(); - return h; +/** Helper for qsort: compare two ints. */ +static int +_compare_int(const void *x, const void *y) { + return (*(int*)x - *(int*)y); } -/** Creates an empty structure for storing general period-related - * observations. */ -static hs_usage_general_period_related_observations_t * -hs_usage_general_period_related_observations_new(void) -{ - hs_usage_general_period_related_observations_t *p; - p = tor_malloc_zero(sizeof(hs_usage_general_period_related_observations_t)); - rephist_total_alloc+= sizeof(hs_usage_general_period_related_observations_t); - return p; -} +/** Return a newly allocated string containing the exit port statistics + * until <b>now</b>, or NULL if we're not collecting exit stats. */ +char * +rep_hist_format_exit_stats(time_t now) +{ + int i, j, top_elements = 0, cur_min_idx = 0, cur_port; + uint64_t top_bytes[EXIT_STATS_TOP_N_PORTS]; + int top_ports[EXIT_STATS_TOP_N_PORTS]; + uint64_t cur_bytes = 0, other_read = 0, other_written = 0, + total_read = 0, total_written = 0; + uint32_t total_streams = 0, other_streams = 0; + char *buf; + smartlist_t *written_strings, *read_strings, *streams_strings; + char *written_string, *read_string, *streams_string; + char t[ISO_TIME_LEN+1]; + char *result; -/** Creates an empty structure for storing period-specific information. */ -static hs_usage_current_observation_period_t * -hs_usage_current_observation_period_new(void) -{ - hs_usage_current_observation_period_t *c; - time_t now; - c = tor_malloc_zero(sizeof(hs_usage_current_observation_period_t)); - rephist_total_alloc += sizeof(hs_usage_current_observation_period_t); - now = time(NULL); - c->start_of_current_period = now; - c->start_of_next_period = now + NUM_SECS_HS_USAGE_SUM_INTERVAL; - return c; -} + if (!start_of_exit_stats_interval) + return NULL; /* Not initialized. */ -/** Initializes the structures for collecting hidden service usage data. */ -static void -hs_usage_init(void) -{ - current_period = hs_usage_current_observation_period_new(); - publish_total = hs_usage_service_related_observation_new(); - publish_novel = hs_usage_service_related_observation_new(); - fetch_total = hs_usage_service_related_observation_new(); - fetch_successful = hs_usage_service_related_observation_new(); - descs = hs_usage_general_period_related_observations_new(); -} + /* Go through all ports to find the n ports that saw most written and + * read bytes. + * + * Invariant: at the end of the loop for iteration i, + * total_read is the sum of all exit_bytes_read[0..i] + * total_written is the sum of all exit_bytes_written[0..i] + * total_stream is the sum of all exit_streams[0..i] + * + * top_elements = MAX(EXIT_STATS_TOP_N_PORTS, + * #{j | 0 <= j <= i && volume(i) > 0}) + * + * For all 0 <= j < top_elements, + * top_bytes[j] > 0 + * 0 <= top_ports[j] <= 65535 + * top_bytes[j] = volume(top_ports[j]) + * + * There is no j in 0..i and k in 0..top_elements such that: + * volume(j) > top_bytes[k] AND j is not in top_ports[0..top_elements] + * + * There is no j!=cur_min_idx in 0..top_elements such that: + * top_bytes[j] < top_bytes[cur_min_idx] + * + * where volume(x) == exit_bytes_read[x]+exit_bytes_written[x] + * + * Worst case: O(EXIT_STATS_NUM_PORTS * EXIT_STATS_TOP_N_PORTS) + */ + for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { + total_read += exit_bytes_read[i]; + total_written += exit_bytes_written[i]; + total_streams += exit_streams[i]; + cur_bytes = exit_bytes_read[i] + exit_bytes_written[i]; + if (cur_bytes == 0) { + continue; + } + if (top_elements < EXIT_STATS_TOP_N_PORTS) { + top_bytes[top_elements] = cur_bytes; + top_ports[top_elements++] = i; + } else if (cur_bytes > top_bytes[cur_min_idx]) { + top_bytes[cur_min_idx] = cur_bytes; + top_ports[cur_min_idx] = i; + } else { + continue; + } + cur_min_idx = 0; + for (j = 1; j < top_elements; j++) { + if (top_bytes[j] < top_bytes[cur_min_idx]) { + cur_min_idx = j; + } + } + } -/** Clears the given ordered list by resetting its attributes and releasing - * the memory allocated by its elements. */ -static void -hs_usage_list_clear(hs_usage_list_t *lst) -{ - /* walk through elements and free memory */ - hs_usage_list_elem_t *current = lst->start; - hs_usage_list_elem_t *tmp; - while (current != NULL) { - tmp = current->next; - rephist_total_alloc -= sizeof(hs_usage_list_elem_t); - tor_free(current); - current = tmp; + /* Add observations of top ports to smartlists. */ + written_strings = smartlist_create(); + read_strings = smartlist_create(); + streams_strings = smartlist_create(); + other_read = total_read; + other_written = total_written; + other_streams = total_streams; + /* Sort the ports; this puts them out of sync with top_bytes, but we + * won't be using top_bytes again anyway */ + qsort(top_ports, top_elements, sizeof(int), _compare_int); + for (j = 0; j < top_elements; j++) { + cur_port = top_ports[j]; + if (exit_bytes_written[cur_port] > 0) { + uint64_t num = round_uint64_to_next_multiple_of( + exit_bytes_written[cur_port], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + buf = NULL; + tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num)); + smartlist_add(written_strings, buf); + other_written -= exit_bytes_written[cur_port]; + } + if (exit_bytes_read[cur_port] > 0) { + uint64_t num = round_uint64_to_next_multiple_of( + exit_bytes_read[cur_port], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + buf = NULL; + tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num)); + smartlist_add(read_strings, buf); + other_read -= exit_bytes_read[cur_port]; + } + if (exit_streams[cur_port] > 0) { + uint32_t num = round_uint32_to_next_multiple_of( + exit_streams[cur_port], + EXIT_STATS_ROUND_UP_STREAMS); + buf = NULL; + tor_asprintf(&buf, "%d=%u", cur_port, num); + smartlist_add(streams_strings, buf); + other_streams -= exit_streams[cur_port]; + } } - /* reset attributes */ - lst->start = NULL; - lst->total_count = 0; - lst->total_service_ids = 0; - return; -} -/** Frees the memory used by the given list. */ -static void -hs_usage_list_free(hs_usage_list_t *lst) -{ - if (!lst) - return; - hs_usage_list_clear(lst); - rephist_total_alloc -= sizeof(hs_usage_list_t); - tor_free(lst); + /* Add observations of other ports in a single element. */ + other_written = round_uint64_to_next_multiple_of(other_written, + EXIT_STATS_ROUND_UP_BYTES); + other_written /= 1024; + buf = NULL; + tor_asprintf(&buf, "other="U64_FORMAT, U64_PRINTF_ARG(other_written)); + smartlist_add(written_strings, buf); + other_read = round_uint64_to_next_multiple_of(other_read, + EXIT_STATS_ROUND_UP_BYTES); + other_read /= 1024; + buf = NULL; + tor_asprintf(&buf, "other="U64_FORMAT, U64_PRINTF_ARG(other_read)); + smartlist_add(read_strings, buf); + other_streams = round_uint32_to_next_multiple_of(other_streams, + EXIT_STATS_ROUND_UP_STREAMS); + buf = NULL; + tor_asprintf(&buf, "other=%u", other_streams); + smartlist_add(streams_strings, buf); + + /* Join all observations in single strings. */ + written_string = smartlist_join_strings(written_strings, ",", 0, NULL); + read_string = smartlist_join_strings(read_strings, ",", 0, NULL); + streams_string = smartlist_join_strings(streams_strings, ",", 0, NULL); + SMARTLIST_FOREACH(written_strings, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(read_strings, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(streams_strings, char *, cp, tor_free(cp)); + smartlist_free(written_strings); + smartlist_free(read_strings); + smartlist_free(streams_strings); + + /* Put everything together. */ + format_iso_time(t, now); + tor_asprintf(&result, "exit-stats-end %s (%d s)\n" + "exit-kibibytes-written %s\n" + "exit-kibibytes-read %s\n" + "exit-streams-opened %s\n", + t, (unsigned) (now - start_of_exit_stats_interval), + written_string, + read_string, + streams_string); + tor_free(written_string); + tor_free(read_string); + tor_free(streams_string); + return result; } -/** Frees the memory used by the given service-related observations. */ -static void -hs_usage_service_related_observation_free( - hs_usage_service_related_observation_t *s) +/** If 24 hours have passed since the beginning of the current exit port + * stats period, write exit stats to $DATADIR/stats/exit-stats (possibly + * overwriting an existing file) and reset counters. Return when we would + * next want to write exit stats or 0 if we never want to write. */ +time_t +rep_hist_exit_stats_write(time_t now) { - if (!s) - return; - hs_usage_list_free(s->list); - rephist_total_alloc -= sizeof(hs_usage_service_related_observation_t); - tor_free(s); -} + char *statsdir = NULL, *filename = NULL, *str = NULL; -/** Frees the memory used by the given period-specific observations. */ -static void -hs_usage_general_period_related_observations_free( - hs_usage_general_period_related_observations_t *s) -{ - rephist_total_alloc-=sizeof(hs_usage_general_period_related_observations_t); - tor_free(s); -} + if (!start_of_exit_stats_interval) + return 0; /* Not initialized. */ + if (start_of_exit_stats_interval + WRITE_STATS_INTERVAL > now) + goto done; /* Not ready to write. */ -/** Frees the memory used by period-specific information. */ -static void -hs_usage_current_observation_period_free( - hs_usage_current_observation_period_t *s) -{ - rephist_total_alloc -= sizeof(hs_usage_current_observation_period_t); - tor_free(s); -} + log_info(LD_HIST, "Writing exit port statistics to disk."); -/** Frees all memory that was used for collecting hidden service usage data. */ -void -hs_usage_free_all(void) -{ - hs_usage_general_period_related_observations_free(descs); - descs = NULL; - hs_usage_service_related_observation_free(fetch_successful); - hs_usage_service_related_observation_free(fetch_total); - hs_usage_service_related_observation_free(publish_novel); - hs_usage_service_related_observation_free(publish_total); - fetch_successful = fetch_total = publish_novel = publish_total = NULL; - hs_usage_current_observation_period_free(current_period); - current_period = NULL; -} + /* Generate history string. */ + str = rep_hist_format_exit_stats(now); -/** Inserts a new occurrence for the given service id to the given ordered - * list. */ -static void -hs_usage_insert_value(hs_usage_list_t *lst, const char *service_id) -{ - /* search if there is already an elem with same service_id in list */ - hs_usage_list_elem_t *current = lst->start; - hs_usage_list_elem_t *previous = NULL; - while (current != NULL && strcasecmp(current->service_id,service_id)) { - previous = current; - current = current->next; - } - /* found an element with same service_id? */ - if (current == NULL) { - /* not found! append to end (which could also be the end of a zero-length - * list), don't need to sort (1 is smallest value). */ - /* create elem */ - hs_usage_list_elem_t *e = hs_usage_list_elem_new(); - /* update list attributes (one new elem, one new occurrence) */ - lst->total_count++; - lst->total_service_ids++; - /* copy service id to elem */ - strlcpy(e->service_id,service_id,sizeof(e->service_id)); - /* let either l->start or previously last elem point to new elem */ - if (lst->start == NULL) { - /* this is the first elem */ - lst->start = e; - } else { - /* there were elems in the list before */ - previous->next = e; - } - } else { - /* found! add occurrence to elem and consider resorting */ - /* update list attributes (no new elem, but one new occurrence) */ - lst->total_count++; - /* add occurrence to elem */ - current->count++; - /* is it another than the first list elem? and has previous elem fewer - * count than current? then we need to resort */ - if (previous != NULL && previous->count < current->count) { - /* yes! we need to resort */ - /* remove current elem first */ - previous->next = current->next; - /* can we prepend elem to all other elements? */ - if (lst->start->count <= current->count) { - /* yes! prepend elem */ - current->next = lst->start; - lst->start = current; - } else { - /* no! walk through list a second time and insert at correct place */ - hs_usage_list_elem_t *insert_current = lst->start->next; - hs_usage_list_elem_t *insert_previous = lst->start; - while (insert_current != NULL && - insert_current->count > current->count) { - insert_previous = insert_current; - insert_current = insert_current->next; - } - /* insert here */ - current->next = insert_current; - insert_previous->next = current; - } - } - } -} + /* Reset counters. */ + rep_hist_reset_exit_stats(now); -/** Writes the current service-related observations to the history array and - * clears the observations of the current period. */ -static void -hs_usage_write_service_related_observations_to_history( - hs_usage_current_observation_period_t *p, - hs_usage_service_related_observation_t *h) -{ - /* walk through the first 20 % of list elements and calculate frequency - * distributions */ - /* maximum indices for the three frequencies */ - int five_percent_idx = h->list->total_service_ids/20; - int ten_percent_idx = h->list->total_service_ids/10; - int twenty_percent_idx = h->list->total_service_ids/5; - /* temp values */ - uint32_t five_percent = 0; - uint32_t ten_percent = 0; - uint32_t twenty_percent = 0; - /* walk through list */ - hs_usage_list_elem_t *current = h->list->start; - int i=0; - while (current != NULL && i <= twenty_percent_idx) { - twenty_percent += current->count; - if (i <= ten_percent_idx) - ten_percent += current->count; - if (i <= five_percent_idx) - five_percent += current->count; - current = current->next; - i++; + /* Try to write to disk. */ + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) { + log_warn(LD_HIST, "Unable to create stats/ directory!"); + goto done; } - /* copy frequencies */ - h->twenty[p->next_idx] = twenty_percent; - h->ten[p->next_idx] = ten_percent; - h->five[p->next_idx] = five_percent; - /* copy total number of observations */ - h->totals[p->next_idx] = h->list->total_count; - /* free memory of old list */ - hs_usage_list_clear(h->list); -} + filename = get_datadir_fname2("stats", "exit-stats"); + if (write_str_to_file(filename, str, 0) < 0) + log_warn(LD_HIST, "Unable to write exit port statistics to disk!"); -/** Advances to next observation period. */ -static void -hs_usage_advance_current_observation_period(void) -{ - /* aggregate observations to history, including frequency distribution - * arrays */ - hs_usage_write_service_related_observations_to_history( - current_period, publish_total); - hs_usage_write_service_related_observations_to_history( - current_period, publish_novel); - hs_usage_write_service_related_observations_to_history( - current_period, fetch_total); - hs_usage_write_service_related_observations_to_history( - current_period, fetch_successful); - /* write current number of descriptors to descs history */ - descs->totals[current_period->next_idx] = rend_cache_size(); - /* advance to next period */ - current_period->next_idx++; - if (current_period->next_idx == NUM_TOTALS_HS_USAGE) - current_period->next_idx = 0; - if (current_period->num_set < NUM_TOTALS_HS_USAGE) - ++current_period->num_set; - current_period->start_of_current_period=current_period->start_of_next_period; - current_period->start_of_next_period += NUM_SECS_HS_USAGE_SUM_INTERVAL; -} - -/** Checks if the current period is up to date, and if not, advances it. */ -static void -hs_usage_check_if_current_period_is_up_to_date(time_t now) -{ - while (now > current_period->start_of_next_period) { - hs_usage_advance_current_observation_period(); - } + done: + tor_free(str); + tor_free(statsdir); + tor_free(filename); + return start_of_exit_stats_interval + WRITE_STATS_INTERVAL; } -/** Adds a service-related observation, maybe after advancing to next - * observation period. */ -static void -hs_usage_add_service_related_observation( - hs_usage_service_related_observation_t *h, - time_t now, - const char *service_id) +/** Note that we wrote <b>num_written</b> bytes and read <b>num_read</b> + * bytes to/from an exit connection to <b>port</b>. */ +void +rep_hist_note_exit_bytes(uint16_t port, size_t num_written, + size_t num_read) { - if (now < current_period->start_of_current_period) { - /* don't record old data */ - return; - } - /* check if we are up-to-date */ - hs_usage_check_if_current_period_is_up_to_date(now); - /* add observation */ - hs_usage_insert_value(h->list, service_id); + if (!start_of_exit_stats_interval) + return; /* Not initialized. */ + exit_bytes_written[port] += num_written; + exit_bytes_read[port] += num_read; + log_debug(LD_HIST, "Written %lu bytes and read %lu bytes to/from an " + "exit connection to port %d.", + (unsigned long)num_written, (unsigned long)num_read, port); } -/** Adds the observation of storing a rendezvous service descriptor to our - * cache in our role as HS authoritative directory. */ +/** Note that we opened an exit stream to <b>port</b>. */ void -hs_usage_note_publish_total(const char *service_id, time_t now) +rep_hist_note_exit_stream_opened(uint16_t port) { - hs_usage_add_service_related_observation(publish_total, now, service_id); + if (!start_of_exit_stats_interval) + return; /* Not initialized. */ + exit_streams[port]++; + log_debug(LD_HIST, "Opened exit stream to port %d", port); } -/** Adds the observation of storing a novel rendezvous service descriptor to - * our cache in our role as HS authoritative directory. */ +/*** cell statistics ***/ + +/** Start of the current buffer stats interval or 0 if we're not + * collecting buffer statistics. */ +static time_t start_of_buffer_stats_interval; + +/** Initialize buffer stats. */ void -hs_usage_note_publish_novel(const char *service_id, time_t now) +rep_hist_buffer_stats_init(time_t now) { - hs_usage_add_service_related_observation(publish_novel, now, service_id); + start_of_buffer_stats_interval = now; } -/** Adds the observation of being requested for a rendezvous service descriptor - * in our role as HS authoritative directory. */ +typedef struct circ_buffer_stats_t { + uint32_t processed_cells; + double mean_num_cells_in_queue; + double mean_time_cells_in_queue; + uint32_t local_circ_id; +} circ_buffer_stats_t; + +/** Holds stats. */ +smartlist_t *circuits_for_buffer_stats = NULL; + +/** 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 -hs_usage_note_fetch_total(const char *service_id, time_t now) +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; + 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 > + start_of_buffer_stats_interval ? + circ->timestamp_created : + start_of_buffer_stats_interval; + interval_length = (int) (end_of_interval - start_of_interval); + stat = tor_malloc_zero(sizeof(circ_buffer_stats_t)); + stat->processed_cells = orcirc->processed_cells; + /* 1000.0 for s -> ms; 2.0 because of app-ward and exit-ward queues */ + stat->mean_num_cells_in_queue = interval_length == 0 ? 0.0 : + (double) orcirc->total_cell_waiting_time / + (double) interval_length / 1000.0 / 2.0; + stat->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; +} + +/** Sorting helper: return -1, 1, or 0 based on comparison of two + * circ_buffer_stats_t */ +static int +_buffer_stats_compare_entries(const void **_a, const void **_b) { - hs_usage_add_service_related_observation(fetch_total, now, service_id); + const circ_buffer_stats_t *a = *_a, *b = *_b; + if (a->processed_cells < b->processed_cells) + return 1; + else if (a->processed_cells > b->processed_cells) + return -1; + else + return 0; } -/** Adds the observation of being requested for a rendezvous service descriptor - * in our role as HS authoritative directory and being able to answer that - * request successfully. */ +/** Stop collecting cell stats in a way that we can re-start doing so in + * rep_hist_buffer_stats_init(). */ void -hs_usage_note_fetch_successful(const char *service_id, time_t now) +rep_hist_buffer_stats_term(void) { - hs_usage_add_service_related_observation(fetch_successful, now, service_id); + start_of_buffer_stats_interval = 0; + 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); } -/** Writes the given circular array to a string. */ -static size_t -hs_usage_format_history(char *buf, size_t len, uint32_t *data) +/** 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) { - char *cp = buf; /* pointer where we are in the buffer */ - int i, n; - if (current_period->num_set <= current_period->next_idx) { - i = 0; /* not been through circular array */ - } else { - i = current_period->next_idx; + 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 = smartlist_create(); + char *str = NULL, *buf=NULL; + circuit_t *circ; + + 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 current circuits to stats */ + for (circ = _circuit_get_global_list(); circ; circ = circ->next) + rep_hist_buffer_stats_add_circ(circ, now); + /* calculate deciles */ + 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; } - for (n = 0; n < current_period->num_set; ++n,++i) { - if (i >= NUM_TOTALS_HS_USAGE) - i -= NUM_TOTALS_HS_USAGE; - tor_assert(i < NUM_TOTALS_HS_USAGE); - if (n == (current_period->num_set-1)) - tor_snprintf(cp, len-(cp-buf), "%d", data[i]); - else - tor_snprintf(cp, len-(cp-buf), "%d,", data[i]); - cp += strlen(cp); + 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]++; } - return cp-buf; -} - -/** Writes the complete usage history as hidden service authoritative directory - * to a string. */ -static char * -hs_usage_format_statistics(void) -{ - char *buf, *cp, *s = NULL; - char t[ISO_TIME_LEN+1]; - int r; - uint32_t *data = NULL; - size_t len; - len = (70+20*NUM_TOTALS_HS_USAGE)*11; - buf = tor_malloc_zero(len); - cp = buf; - for (r = 0; r < 11; ++r) { - switch (r) { - case 0: - s = (char*) "publish-total-history"; - data = publish_total->totals; - break; - case 1: - s = (char*) "publish-novel-history"; - data = publish_novel->totals; - break; - case 2: - s = (char*) "publish-top-5-percent-history"; - data = publish_total->five; - break; - case 3: - s = (char*) "publish-top-10-percent-history"; - data = publish_total->ten; - break; - case 4: - s = (char*) "publish-top-20-percent-history"; - data = publish_total->twenty; - break; - case 5: - s = (char*) "fetch-total-history"; - data = fetch_total->totals; - break; - case 6: - s = (char*) "fetch-successful-history"; - data = fetch_successful->totals; - break; - case 7: - s = (char*) "fetch-top-5-percent-history"; - data = fetch_total->five; - break; - case 8: - s = (char*) "fetch-top-10-percent-history"; - data = fetch_total->ten; - break; - case 9: - s = (char*) "fetch-top-20-percent-history"; - data = fetch_total->twenty; - break; - case 10: - s = (char*) "desc-total-history"; - data = descs->totals; - break; - } - format_iso_time(t, current_period->start_of_current_period); - tor_snprintf(cp, len-(cp-buf), "%s %s (%d s) ", s, t, - NUM_SECS_HS_USAGE_SUM_INTERVAL); - cp += strlen(cp); - cp += hs_usage_format_history(cp, len-(cp-buf), data); - strlcat(cp, "\n", len-(cp-buf)); - ++cp; + 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) < 0) + goto done; + filename = get_datadir_fname2("stats", "buffer-stats"); + out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, + 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; + 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); } - return 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); + } + 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); + } + 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) + goto done; + finish_writing_to_file(open_file); + open_file = NULL; + start_of_buffer_stats_interval = now; + done: + if (open_file) + abort_writing_to_file(open_file); + tor_free(filename); + tor_free(statsdir); + if (str_build) { + SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); + smartlist_free(str_build); + } + tor_free(str); +#undef SHARES + return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL; } -/** Write current statistics about hidden service usage to file. */ +/** Free all storage held by the OR/link history caches, by the + * bandwidth history arrays, by the port history, or by statistics . */ void -hs_usage_write_statistics_to_file(time_t now) +rep_hist_free_all(void) { - char *buf; - size_t len; - char *fname; - or_options_t *options = get_options(); - /* check if we are up-to-date */ - hs_usage_check_if_current_period_is_up_to_date(now); - buf = hs_usage_format_statistics(); - len = strlen(options->DataDirectory) + 16; - fname = tor_malloc(len); - tor_snprintf(fname, len, "%s"PATH_SEPARATOR"hsusage", - options->DataDirectory); - write_str_to_file(fname,buf,0); - tor_free(buf); - tor_free(fname); + digestmap_free(history_map, free_or_history); + tor_free(read_array); + tor_free(write_array); + tor_free(last_stability_doc); + tor_free(exit_bytes_read); + tor_free(exit_bytes_written); + tor_free(exit_streams); + built_last_stability_doc_at = 0; + predicted_ports_free(); } diff --git a/src/or/rephist.h b/src/or/rephist.h new file mode 100644 index 0000000000..8f5a34dacf --- /dev/null +++ b/src/or/rephist.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file rephist.h + * \brief Header file for rephist.c. + **/ + +#ifndef _TOR_REPHIST_H +#define _TOR_REPHIST_H + +void rep_hist_init(void); +void rep_hist_note_connect_failed(const char* nickname, time_t when); +void rep_hist_note_connect_succeeded(const char* nickname, time_t when); +void rep_hist_note_disconnect(const char* nickname, time_t when); +void rep_hist_note_connection_died(const char* nickname, time_t when); +void rep_hist_note_extend_succeeded(const char *from_name, + const char *to_name); +void rep_hist_note_extend_failed(const char *from_name, const char *to_name); +void rep_hist_dump_stats(time_t now, int severity); +void rep_hist_note_bytes_read(size_t num_bytes, time_t when); +void rep_hist_note_bytes_written(size_t num_bytes, time_t when); + +void rep_hist_note_dir_bytes_read(size_t num_bytes, time_t when); +void rep_hist_note_dir_bytes_written(size_t num_bytes, time_t when); + +int rep_hist_bandwidth_assess(void); +char *rep_hist_get_bandwidth_lines(void); +void rep_hist_update_state(or_state_t *state); +int rep_hist_load_state(or_state_t *state, char **err); +void rep_history_clean(time_t before); + +void rep_hist_note_router_reachable(const char *id, time_t when); +void rep_hist_note_router_unreachable(const char *id, time_t when); +int rep_hist_record_mtbf_data(time_t now, int missing_means_down); +int rep_hist_load_mtbf_data(time_t now); + +time_t rep_hist_downrate_old_runs(time_t now); +double rep_hist_get_stability(const char *id, time_t when); +double rep_hist_get_weighted_fractional_uptime(const char *id, time_t when); +long rep_hist_get_weighted_time_known(const char *id, time_t when); +int rep_hist_have_measured_enough_stability(void); +const char *rep_hist_get_router_stability_doc(time_t now); + +void rep_hist_note_used_port(time_t now, uint16_t port); +smartlist_t *rep_hist_get_predicted_ports(time_t now); +void rep_hist_note_used_resolve(time_t now); +void rep_hist_note_used_internal(time_t now, int need_uptime, + int need_capacity); +int rep_hist_get_predicted_internal(time_t now, int *need_uptime, + int *need_capacity); + +int any_predicted_circuits(time_t now); +int rep_hist_circbuilding_dormant(time_t now); + +void note_crypto_pk_op(pk_op_t operation); +void dump_pk_ops(int severity); + +void rep_hist_free_all(void); + +void rep_hist_exit_stats_init(time_t now); +void rep_hist_reset_exit_stats(time_t now); +void rep_hist_exit_stats_term(void); +char *rep_hist_format_exit_stats(time_t now); +time_t rep_hist_exit_stats_write(time_t now); +void rep_hist_note_exit_bytes(uint16_t port, size_t num_written, + size_t num_read); +void rep_hist_note_exit_stream_opened(uint16_t port); + +void rep_hist_buffer_stats_init(time_t now); +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); + +#endif + diff --git a/src/or/router.c b/src/or/router.c index 8661e7a224..66ef8ec52e 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -7,6 +7,24 @@ #define ROUTER_PRIVATE #include "or.h" +#include "circuitlist.h" +#include "circuituse.h" +#include "config.h" +#include "connection.h" +#include "control.h" +#include "directory.h" +#include "dirserv.h" +#include "dns.h" +#include "geoip.h" +#include "hibernate.h" +#include "main.h" +#include "networkstatus.h" +#include "policies.h" +#include "relay.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" /** * \file router.c @@ -31,11 +49,15 @@ static crypto_pk_env_t *onionkey=NULL; /** Previous private onionskin decryption key: used to decode CREATE cells * generated by clients that have an older version of our descriptor. */ static crypto_pk_env_t *lastonionkey=NULL; -/** Private "identity key": used to sign directory info and TLS +/** Private server "identity key": used to sign directory info and TLS * certificates. Never changes. */ -static crypto_pk_env_t *identitykey=NULL; -/** Digest of identitykey. */ -static char identitykey_digest[DIGEST_LEN]; +static crypto_pk_env_t *server_identitykey=NULL; +/** Digest of server_identitykey. */ +static char server_identitykey_digest[DIGEST_LEN]; +/** Private client "identity key": used to sign bridges' and clients' + * outbound TLS certificates. Regenerated on startup and on IP address + * change. */ +static crypto_pk_env_t *client_identitykey=NULL; /** Signing key used for v3 directory material; only set for authorities. */ static crypto_pk_env_t *authority_signing_key = NULL; /** Key certificate to authenticate v3 directory material; only set for @@ -61,8 +83,7 @@ static void set_onion_key(crypto_pk_env_t *k) { tor_mutex_acquire(key_lock); - if (onionkey) - crypto_free_pk_env(onionkey); + crypto_free_pk_env(onionkey); onionkey = k; onionkey_set_at = time(NULL); tor_mutex_release(key_lock); @@ -106,32 +127,78 @@ get_onion_key_set_at(void) return onionkey_set_at; } -/** Set the current identity key to k. +/** Set the current server identity key to <b>k</b>. */ void -set_identity_key(crypto_pk_env_t *k) +set_server_identity_key(crypto_pk_env_t *k) { - if (identitykey) - crypto_free_pk_env(identitykey); - identitykey = k; - crypto_pk_get_digest(identitykey, identitykey_digest); + crypto_free_pk_env(server_identitykey); + server_identitykey = k; + crypto_pk_get_digest(server_identitykey, server_identitykey_digest); } -/** Returns the current identity key; requires that the identity key has been - * set. +/** Make sure that we have set up our identity keys to match or not match as + * appropriate, and die with an assertion if we have not. */ +static void +assert_identity_keys_ok(void) +{ + tor_assert(client_identitykey); + if (public_server_mode(get_options())) { + /* assert that we have set the client and server keys to be equal */ + tor_assert(server_identitykey); + tor_assert(0==crypto_pk_cmp_keys(client_identitykey, server_identitykey)); + } 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)); + } +} + +/** Returns the current server identity key; requires that the key has + * been set, and that we are running as a Tor server. + */ +crypto_pk_env_t * +get_server_identity_key(void) +{ + tor_assert(server_identitykey); + tor_assert(server_mode(get_options())); + assert_identity_keys_ok(); + return server_identitykey; +} + +/** Return true iff the server identity key has been set. */ +int +server_identity_key_is_set(void) +{ + return server_identitykey != NULL; +} + +/** Set the current client identity key to <b>k</b>. + */ +void +set_client_identity_key(crypto_pk_env_t *k) +{ + crypto_free_pk_env(client_identitykey); + client_identitykey = k; +} + +/** Returns the current client identity key for use on outgoing TLS + * connections; requires that the key has been set. */ crypto_pk_env_t * -get_identity_key(void) +get_tlsclient_identity_key(void) { - tor_assert(identitykey); - return identitykey; + tor_assert(client_identitykey); + assert_identity_keys_ok(); + return client_identitykey; } -/** Return true iff the identity key has been set. */ +/** Return true iff the client identity key has been set. */ int -identity_key_is_set(void) +client_identity_key_is_set(void) { - return identitykey != NULL; + return client_identitykey != NULL; } /** Return the key certificate for this v3 (voting) authority, or NULL @@ -201,8 +268,7 @@ rotate_onion_key(void) } log_info(LD_GENERAL, "Rotating onion key"); tor_mutex_acquire(key_lock); - if (lastonionkey) - crypto_free_pk_env(lastonionkey); + crypto_free_pk_env(lastonionkey); lastonionkey = onionkey; onionkey = prkey; now = time(NULL); @@ -331,10 +397,9 @@ load_authority_keyset(int legacy, crypto_pk_env_t **key_out, goto done; } - if (*key_out) - crypto_free_pk_env(*key_out); - if (*cert_out) - authority_cert_free(*cert_out); + crypto_free_pk_env(*key_out); + authority_cert_free(*cert_out); + *key_out = signing_key; *cert_out = parsed; r = 0; @@ -344,10 +409,8 @@ load_authority_keyset(int legacy, crypto_pk_env_t **key_out, done: tor_free(fname); tor_free(cert); - if (signing_key) - crypto_free_pk_env(signing_key); - if (parsed) - authority_cert_free(parsed); + crypto_free_pk_env(signing_key); + authority_cert_free(parsed); return r; } @@ -442,7 +505,9 @@ init_keys(void) key_lock = tor_mutex_new(); /* There are a couple of paths that put us here before */ - if (crypto_global_init(get_options()->HardwareAccel)) { + if (crypto_global_init(get_options()->HardwareAccel, + get_options()->AccelName, + get_options()->AccelDir)) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } @@ -456,9 +521,12 @@ init_keys(void) crypto_free_pk_env(prkey); return -1; } - set_identity_key(prkey); - /* Create a TLS context; default the client nickname to "client". */ - if (tor_tls_context_new(get_identity_key(), MAX_SSL_KEY_LIFETIME) < 0) { + set_client_identity_key(prkey); + /* Create a TLS context. */ + if (tor_tls_context_init(0, + get_tlsclient_identity_key(), + NULL, + MAX_SSL_KEY_LIFETIME) < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); return -1; } @@ -493,13 +561,28 @@ init_keys(void) } } - /* 1. Read identity key. Make it if none is found. */ + /* 1b. Read identity key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_id_key"); log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR); tor_free(keydir); if (!prkey) return -1; - set_identity_key(prkey); + set_server_identity_key(prkey); + + /* 1c. If we are configured as a bridge, generate a client key; + * otherwise, set the server identity key as our client identity + * key. */ + if (public_server_mode(options)) { + set_client_identity_key(crypto_pk_dup_key(prkey)); /* set above */ + } else { + if (!(prkey = crypto_new_pk_env())) + return -1; + if (crypto_pk_generate_key(prkey)) { + crypto_free_pk_env(prkey); + return -1; + } + set_client_identity_key(prkey); + } /* 2. Read onion key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_onion_key"); @@ -536,7 +619,10 @@ init_keys(void) tor_free(keydir); /* 3. Initialize link key and TLS context. */ - if (tor_tls_context_new(get_identity_key(), MAX_SSL_KEY_LIFETIME) < 0) { + if (tor_tls_context_init(public_server_mode(options), + get_tlsclient_identity_key(), + get_server_identity_key(), + MAX_SSL_KEY_LIFETIME) < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; } @@ -547,7 +633,8 @@ init_keys(void) const char *m = NULL; routerinfo_t *ri; /* We need to add our own fingerprint so it gets recognized. */ - if (dirserv_add_own_fingerprint(options->Nickname, get_identity_key())) { + if (dirserv_add_own_fingerprint(options->Nickname, + get_server_identity_key())) { log_err(LD_GENERAL,"Error adding own fingerprint to approved set"); return -1; } @@ -568,7 +655,8 @@ init_keys(void) /* 5. Dump fingerprint to 'fingerprint' */ keydir = get_datadir_fname("fingerprint"); log_info(LD_GENERAL,"Dumping fingerprint to \"%s\"...",keydir); - if (crypto_pk_get_fingerprint(get_identity_key(), fingerprint, 0)<0) { + if (crypto_pk_get_fingerprint(get_server_identity_key(), + fingerprint, 0) < 0) { log_err(LD_GENERAL,"Error computing fingerprint"); tor_free(keydir); return -1; @@ -606,7 +694,7 @@ init_keys(void) return -1; } /* 6b. [authdirserver only] add own key to approved directories. */ - crypto_pk_get_digest(get_identity_key(), digest); + 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) | @@ -962,6 +1050,28 @@ server_mode(or_options_t *options) return (options->ORPort != 0 || options->ORListenAddress); } +/** Return true iff we are trying to be a non-bridge server. + */ +int +public_server_mode(or_options_t *options) +{ + if (!server_mode(options)) return 0; + return (!options->BridgeRelay); +} + +/** Return true iff the combination of options in <b>options</b> and parameters + * 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) +{ + if (options->RefuseUnknownExits_ != -1) { + return options->RefuseUnknownExits_; + } else { + return networkstatus_get_param(NULL, "refuseunknownexits", 1); + } +} + /** Remember if we've advertised ourselves to the dirservers. */ static int server_is_advertised=0; @@ -989,7 +1099,7 @@ proxy_mode(or_options_t *options) { return (options->SocksPort != 0 || options->SocksListenAddress || options->TransPort != 0 || options->TransListenAddress || - options->NatdPort != 0 || options->NatdListenAddress || + options->NATDPort != 0 || options->NATDListenAddress || options->DNSPort != 0 || options->DNSListenAddress); } @@ -1124,12 +1234,24 @@ router_compare_to_my_exit_policy(edge_connection_t *conn) desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; } +/** Return true iff my exit policy is reject *:*. Return -1 if we don't + * have a descriptor */ +int +router_my_exit_policy_is_reject_star(void) +{ + if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */ + return -1; + + return desc_routerinfo->policy_is_reject_star; +} + /** Return true iff I'm a server and <b>digest</b> is equal to - * my identity digest. */ + * my server identity key digest. */ int router_digest_is_me(const char *digest) { - return identitykey && !memcmp(identitykey_digest, digest, DIGEST_LEN); + return (server_identitykey && + !memcmp(server_identitykey_digest, digest, DIGEST_LEN)); } /** Return true iff I'm a server and <b>digest</b> is equal to @@ -1219,6 +1341,8 @@ static int router_guess_address_from_dir_headers(uint32_t *guess); int router_pick_published_address(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."); @@ -1228,6 +1352,9 @@ 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); return 0; } @@ -1250,7 +1377,7 @@ router_rebuild_descriptor(int force) if (router_pick_published_address(options, &addr) < 0) { /* Stop trying to rebuild our descriptor every second. We'll - * learn that it's time to try again when server_has_changed_ip() + * learn that it's time to try again when ip_address_changed() * marks it dirty. */ desc_clean_since = time(NULL); return -1; @@ -1266,7 +1393,7 @@ router_rebuild_descriptor(int force) ri->cache_info.published_on = time(NULL); ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from * main thread */ - ri->identity_pkey = crypto_pk_dup_key(get_identity_key()); + ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key()); if (crypto_pk_get_digest(ri->identity_pkey, ri->cache_info.identity_digest)<0) { routerinfo_free(ri); @@ -1285,7 +1412,9 @@ router_rebuild_descriptor(int force) policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy, options->ExitPolicyRejectPrivate, - ri->address); + ri->address, !options->BridgeRelay); + ri->policy_is_reject_star = + policy_is_reject_star(ri->exit_policy); if (desc_routerinfo) { /* inherit values */ ri->is_valid = desc_routerinfo->is_valid; @@ -1356,26 +1485,30 @@ router_rebuild_descriptor(int force) ei->cache_info.published_on = ri->cache_info.published_on; memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); - ei->cache_info.signed_descriptor_body = tor_malloc(8192); - if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, 8192, - ei, get_identity_key()) < 0) { + if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body, + ei, get_server_identity_key()) < 0) { log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); - routerinfo_free(ri); extrainfo_free(ei); - return -1; + ei = NULL; + } else { + ei->cache_info.signed_descriptor_len = + strlen(ei->cache_info.signed_descriptor_body); + router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body, + ei->cache_info.signed_descriptor_digest); } - ei->cache_info.signed_descriptor_len = - strlen(ei->cache_info.signed_descriptor_body); - router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body, - ei->cache_info.signed_descriptor_digest); /* Now finish the router descriptor. */ - memcpy(ri->cache_info.extra_info_digest, - ei->cache_info.signed_descriptor_digest, - DIGEST_LEN); + if (ei) { + memcpy(ri->cache_info.extra_info_digest, + ei->cache_info.signed_descriptor_digest, + DIGEST_LEN); + } else { + /* ri was allocated with tor_malloc_zero, so there is no need to + * zero ri->cache_info.extra_info_digest here. */ + } ri->cache_info.signed_descriptor_body = tor_malloc(8192); if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192, - ri, get_identity_key())<0) { + ri, get_server_identity_key()) < 0) { log_warn(LD_BUG, "Couldn't generate router descriptor."); routerinfo_free(ri); extrainfo_free(ei); @@ -1390,7 +1523,7 @@ router_rebuild_descriptor(int force) /* Let bridges serve their own descriptors unencrypted, so they can * pass reachability testing. (If they want to be harder to notice, * they can always leave the DirPort off). */ - if (!options->BridgeRelay) + if (ei && !options->BridgeRelay) ei->cache_info.send_unencrypted = 1; router_get_router_hash(ri->cache_info.signed_descriptor_body, @@ -1399,13 +1532,13 @@ router_rebuild_descriptor(int force) routerinfo_set_country(ri); - tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL)); + if (ei) { + tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL)); + } - if (desc_routerinfo) - routerinfo_free(desc_routerinfo); + routerinfo_free(desc_routerinfo); desc_routerinfo = ri; - if (desc_extrainfo) - extrainfo_free(desc_extrainfo); + extrainfo_free(desc_extrainfo); desc_extrainfo = ei; desc_clean_since = time(NULL); @@ -1586,8 +1719,6 @@ router_guess_address_from_dir_headers(uint32_t *guess) return -1; } -extern const char tor_svn_revision[]; /* from tor_main.c */ - /** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short * string describing the version of Tor and the operating system we're * currently running on. @@ -1618,6 +1749,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, char digest[DIGEST_LEN]; char published[ISO_TIME_LEN+1]; char fingerprint[FINGERPRINT_LEN+1]; + int has_extra_info_digest; char extra_info_digest[HEX_DIGEST_LEN+1]; size_t onion_pkeylen, identity_pkeylen; size_t written; @@ -1646,7 +1778,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, return -1; } - /* PEM-encode the identity key key */ + /* PEM-encode the identity key */ if (crypto_pk_write_public_key_to_string(router->identity_pkey, &identity_pkey,&identity_pkeylen)<0) { log_warn(LD_BUG,"write identity_pkey to string failed!"); @@ -1668,8 +1800,13 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, family_line = tor_strdup(""); } - base16_encode(extra_info_digest, sizeof(extra_info_digest), - router->cache_info.extra_info_digest, DIGEST_LEN); + has_extra_info_digest = + ! tor_digest_is_zero(router->cache_info.extra_info_digest); + + if (has_extra_info_digest) { + base16_encode(extra_info_digest, sizeof(extra_info_digest), + router->cache_info.extra_info_digest, DIGEST_LEN); + } /* Generate the easy portion of the router descriptor. */ result = tor_snprintf(s, maxlen, @@ -1680,7 +1817,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, "opt fingerprint %s\n" "uptime %ld\n" "bandwidth %d %d %d\n" - "opt extra-info-digest %s\n%s" + "%s%s%s%s" "onion-key\n%s" "signing-key\n%s" "%s%s%s%s", @@ -1695,7 +1832,9 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, (int) router->bandwidthrate, (int) router->bandwidthburst, (int) router->bandwidthcapacity, - extra_info_digest, + has_extra_info_digest ? "opt extra-info-digest " : "", + has_extra_info_digest ? extra_info_digest : "", + has_extra_info_digest ? "\n" : "", options->DownloadExtraInfo ? "opt caches-extra-info\n" : "", onion_pkey, identity_pkey, family_line, @@ -1752,7 +1891,8 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, } } - if (written+256 > maxlen) { /* Not enough room for signature. */ + if (written + DIROBJ_MAX_SIG_LEN > maxlen) { + /* Not enough room for signature. */ log_warn(LD_BUG,"not enough room left in descriptor for signature!"); return -1; } @@ -1767,7 +1907,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, note_crypto_pk_op(SIGN_RTR); if (router_append_dirobj_signature(s+written,maxlen-written, - digest,ident_key)<0) { + digest,DIGEST_LEN,ident_key)<0) { log_warn(LD_BUG, "Couldn't sign router descriptor"); return -1; } @@ -1802,11 +1942,62 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, return (int)written+1; } -/** Write the contents of <b>extrainfo</b> to the <b>maxlen</b>-byte string - * <b>s</b>, signing them with <b>ident_key</b>. Return 0 on success, - * negative on failure. */ +/** Load the contents of <b>filename</b>, find the last line starting with + * <b>end_line</b>, ensure that its timestamp is not more than 25 hours in + * the past or more than 1 hour in the future with respect to <b>now</b>, + * and write the file contents starting with that line to *<b>out</b>. + * Return 1 for success, 0 if the file does not exist, or -1 if the file + * does not contain a line matching these criteria or other failure. */ +static int +load_stats_file(const char *filename, const char *end_line, time_t now, + char **out) +{ + int r = -1; + char *fname = get_datadir_fname(filename); + char *contents, *start = NULL, *tmp, timestr[ISO_TIME_LEN+1]; + time_t written; + switch (file_status(fname)) { + case FN_FILE: + /* X022 Find an alternative to reading the whole file to memory. */ + if ((contents = read_file_to_str(fname, 0, NULL))) { + tmp = strstr(contents, end_line); + /* Find last block starting with end_line */ + while (tmp) { + start = tmp; + tmp = strstr(tmp + 1, end_line); + } + if (!start) + goto notfound; + if (strlen(start) < strlen(end_line) + 1 + sizeof(timestr)) + goto notfound; + strlcpy(timestr, start + 1 + strlen(end_line), sizeof(timestr)); + if (parse_iso_time(timestr, &written) < 0) + goto notfound; + if (written < now - (25*60*60) || written > now + (1*60*60)) + goto notfound; + *out = tor_strdup(start); + r = 1; + } + notfound: + tor_free(contents); + break; + case FN_NOENT: + r = 0; + break; + case FN_ERROR: + case FN_DIR: + default: + break; + } + tor_free(fname); + return r; +} + +/** Write the contents of <b>extrainfo</b> and aggregated statistics to + * *<b>s_out</b>, signing them with <b>ident_key</b>. Return 0 on + * success, negative on failure. */ int -extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, +extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, crypto_pk_env_t *ident_key) { or_options_t *options = get_options(); @@ -1815,87 +2006,128 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, char digest[DIGEST_LEN]; char *bandwidth_usage; int result; - size_t len; + static int write_stats_to_extrainfo = 1; + char sig[DIROBJ_MAX_SIG_LEN+1]; + char *s, *pre, *contents, *cp, *s_dup = NULL; + time_t now = time(NULL); + smartlist_t *chunks = smartlist_create(); + extrainfo_t *ei_tmp = NULL; base16_encode(identity, sizeof(identity), extrainfo->cache_info.identity_digest, DIGEST_LEN); format_iso_time(published, extrainfo->cache_info.published_on); - bandwidth_usage = rep_hist_get_bandwidth_lines(1); + bandwidth_usage = rep_hist_get_bandwidth_lines(); - result = tor_snprintf(s, maxlen, - "extra-info %s %s\n" - "published %s\n%s", - extrainfo->nickname, identity, - published, bandwidth_usage); + tor_asprintf(&pre, "extra-info %s %s\npublished %s\n%s", + extrainfo->nickname, identity, + published, bandwidth_usage); tor_free(bandwidth_usage); - if (result<0) - return -1; + smartlist_add(chunks, pre); + + if (options->ExtraInfoStatistics && write_stats_to_extrainfo) { + log_info(LD_GENERAL, "Adding stats to extra-info descriptor."); + if (options->DirReqStatistics && + load_stats_file("stats"PATH_SEPARATOR"dirreq-stats", + "dirreq-stats-end", now, &contents) > 0) { + smartlist_add(chunks, contents); + } + if (options->EntryStatistics && + load_stats_file("stats"PATH_SEPARATOR"entry-stats", + "entry-stats-end", now, &contents) > 0) { + smartlist_add(chunks, contents); + } + if (options->CellStatistics && + load_stats_file("stats"PATH_SEPARATOR"buffer-stats", + "cell-stats-end", now, &contents) > 0) { + smartlist_add(chunks, contents); + } + if (options->ExitPortStatistics && + load_stats_file("stats"PATH_SEPARATOR"exit-stats", + "exit-stats-end", now, &contents) > 0) { + smartlist_add(chunks, contents); + } + } - if (should_record_bridge_info(options)) { - char *geoip_summary = extrainfo_get_client_geoip_summary(time(NULL)); - if (geoip_summary) { - char geoip_start[ISO_TIME_LEN+1]; - format_iso_time(geoip_start, geoip_get_history_start()); - result = tor_snprintf(s+strlen(s), maxlen-strlen(s), - "geoip-start-time %s\n" - "geoip-client-origins %s\n", - geoip_start, geoip_summary); - control_event_clients_seen(geoip_start, geoip_summary); - tor_free(geoip_summary); - if (result<0) - return -1; + if (should_record_bridge_info(options) && write_stats_to_extrainfo) { + const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now); + if (bridge_stats) { + smartlist_add(chunks, tor_strdup(bridge_stats)); } } - len = strlen(s); - strlcat(s+len, "router-signature\n", maxlen-len); - len += strlen(s+len); - if (router_get_extrainfo_hash(s, digest)<0) - return -1; - if (router_append_dirobj_signature(s+len, maxlen-len, digest, ident_key)<0) - return -1; + smartlist_add(chunks, tor_strdup("router-signature\n")); + s = smartlist_join_strings(chunks, "", 0, NULL); + + while (strlen(s) > MAX_EXTRAINFO_UPLOAD_SIZE - DIROBJ_MAX_SIG_LEN) { + /* So long as there are at least two chunks (one for the initial + * extra-info line and one for the router-signature), we can keep removing + * things. */ + if (smartlist_len(chunks) > 2) { + /* We remove the next-to-last element (remember, len-1 is the last + element), since we need to keep the router-signature element. */ + int idx = smartlist_len(chunks) - 2; + char *e = smartlist_get(chunks, idx); + smartlist_del_keeporder(chunks, idx); + log_warn(LD_GENERAL, "We just generated an extra-info descriptor " + "with statistics that exceeds the 50 KB " + "upload limit. Removing last added " + "statistics."); + tor_free(e); + tor_free(s); + s = smartlist_join_strings(chunks, "", 0, NULL); + } else { + log_warn(LD_BUG, "We just generated an extra-info descriptors that " + "exceeds the 50 KB upload limit."); + goto err; + } + } -#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING - { - char *cp, *s_dup; - extrainfo_t *ei_tmp; - cp = s_dup = tor_strdup(s); - ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL); - if (!ei_tmp) { - log_err(LD_BUG, - "We just generated an extrainfo descriptor we can't parse."); - log_err(LD_BUG, "Descriptor was: <<%s>>", s); - tor_free(s_dup); - return -1; + memset(sig, 0, sizeof(sig)); + if (router_get_extrainfo_hash(s, digest) < 0 || + router_append_dirobj_signature(sig, sizeof(sig), digest, DIGEST_LEN, + ident_key) < 0) { + log_warn(LD_BUG, "Could not append signature to extra-info " + "descriptor."); + goto err; + } + smartlist_add(chunks, tor_strdup(sig)); + tor_free(s); + s = smartlist_join_strings(chunks, "", 0, NULL); + + cp = s_dup = tor_strdup(s); + ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL); + if (!ei_tmp) { + if (write_stats_to_extrainfo) { + log_warn(LD_GENERAL, "We just generated an extra-info descriptor " + "with statistics that we can't parse. Not " + "adding statistics to this or any future " + "extra-info descriptors."); + write_stats_to_extrainfo = 0; + result = extrainfo_dump_to_string(s_out, extrainfo, ident_key); + goto done; + } else { + log_warn(LD_BUG, "We just generated an extrainfo descriptor we " + "can't parse."); + goto err; } - tor_free(s_dup); - extrainfo_free(ei_tmp); } -#endif - return (int)strlen(s)+1; -} + *s_out = s; + s = NULL; /* prevent free */ + result = 0; + goto done; -/** Wrapper function for geoip_get_client_history(). It first discards - * any items in the client history that are too old -- it dumps anything - * more than 48 hours old, but it only considers whether to dump at most - * once per 48 hours, so we aren't too precise to an observer (see also - * r14780). - */ -char * -extrainfo_get_client_geoip_summary(time_t now) -{ - static time_t last_purged_at = 0; - int geoip_purge_interval = 48*60*60; -#ifdef ENABLE_GEOIP_STATS - if (get_options()->DirRecordUsageByCountry) - geoip_purge_interval = get_options()->DirRecordUsageRetainIPs; -#endif - if (now > last_purged_at+geoip_purge_interval) { - geoip_remove_old_clients(now-geoip_purge_interval); - last_purged_at = now; - } - return geoip_get_client_history(now, GEOIP_CLIENT_CONNECT); + err: + result = -1; + + done: + tor_free(s); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + tor_free(s_dup); + extrainfo_free(ei_tmp); + + return result; } /** Return true iff <b>s</b> is a legally valid server nickname. */ @@ -2022,26 +2254,17 @@ router_purpose_from_string(const char *s) void router_free_all(void) { - if (onionkey) - crypto_free_pk_env(onionkey); - if (lastonionkey) - crypto_free_pk_env(lastonionkey); - if (identitykey) - crypto_free_pk_env(identitykey); - if (key_lock) - tor_mutex_free(key_lock); - if (desc_routerinfo) - routerinfo_free(desc_routerinfo); - if (desc_extrainfo) - extrainfo_free(desc_extrainfo); - if (authority_signing_key) - crypto_free_pk_env(authority_signing_key); - if (authority_key_certificate) - authority_cert_free(authority_key_certificate); - if (legacy_signing_key) - crypto_free_pk_env(legacy_signing_key); - if (legacy_key_certificate) - authority_cert_free(legacy_key_certificate); + crypto_free_pk_env(onionkey); + crypto_free_pk_env(lastonionkey); + crypto_free_pk_env(server_identitykey); + crypto_free_pk_env(client_identitykey); + tor_mutex_free(key_lock); + routerinfo_free(desc_routerinfo); + extrainfo_free(desc_extrainfo); + crypto_free_pk_env(authority_signing_key); + authority_cert_free(authority_key_certificate); + crypto_free_pk_env(legacy_signing_key); + authority_cert_free(legacy_key_certificate); if (warned_nonexistent_family) { SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp)); diff --git a/src/or/router.h b/src/or/router.h new file mode 100644 index 0000000000..0bfa2d5545 --- /dev/null +++ b/src/or/router.h @@ -0,0 +1,101 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file router.h + * \brief Header file for router.c. + **/ + +#ifndef _TOR_ROUTER_H +#define _TOR_ROUTER_H + +crypto_pk_env_t *get_onion_key(void); +time_t get_onion_key_set_at(void); +void set_server_identity_key(crypto_pk_env_t *k); +crypto_pk_env_t *get_server_identity_key(void); +int server_identity_key_is_set(void); +void set_client_identity_key(crypto_pk_env_t *k); +crypto_pk_env_t *get_tlsclient_identity_key(void); +int client_identity_key_is_set(void); +authority_cert_t *get_my_v3_authority_cert(void); +crypto_pk_env_t *get_my_v3_authority_signing_key(void); +authority_cert_t *get_my_v3_legacy_cert(void); +crypto_pk_env_t *get_my_v3_legacy_signing_key(void); +void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last); +void rotate_onion_key(void); +crypto_pk_env_t *init_key_from_file(const char *fname, int generate, + int severity); +void v3_authority_check_key_expiry(void); + +int init_keys(void); + +int check_whether_orport_reachable(void); +int check_whether_dirport_reachable(void); +void consider_testing_reachability(int test_or, int test_dir); +void router_orport_found_reachable(void); +void router_dirport_found_reachable(void); +void router_perform_bandwidth_test(int num_circs, time_t now); + +int authdir_mode(or_options_t *options); +int authdir_mode_v1(or_options_t *options); +int authdir_mode_v2(or_options_t *options); +int authdir_mode_v3(or_options_t *options); +int authdir_mode_any_main(or_options_t *options); +int authdir_mode_any_nonhidserv(or_options_t *options); +int authdir_mode_handles_descs(or_options_t *options, int purpose); +int authdir_mode_publishes_statuses(or_options_t *options); +int authdir_mode_tests_reachability(or_options_t *options); +int authdir_mode_bridge(or_options_t *options); + +int server_mode(or_options_t *options); +int public_server_mode(or_options_t *options); +int advertised_server_mode(void); +int proxy_mode(or_options_t *options); +void consider_publishable_server(int force); +int should_refuse_unknown_exits(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(void); +void check_descriptor_bandwidth_changed(time_t now); +void check_descriptor_ipaddress_changed(time_t now); +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); +extrainfo_t *router_get_my_extrainfo(void); +const char *router_get_my_descriptor(void); +int router_digest_is_me(const char *digest); +int router_extrainfo_digest_is_me(const char *digest); +int router_is_me(routerinfo_t *router); +int router_fingerprint_is_me(const char *fp); +int router_pick_published_address(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); +int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo, + crypto_pk_env_t *ident_key); +int is_legal_nickname(const char *s); +int is_legal_nickname_or_hexdigest(const char *s); +int is_legal_hexdigest(const char *s); +void router_get_verbose_nickname(char *buf, const routerinfo_t *router); +void routerstatus_get_verbose_nickname(char *buf, + const routerstatus_t *router); +void router_reset_warnings(void); +void router_reset_reachability(void); +void router_free_all(void); + +const char *router_purpose_to_string(uint8_t p); +uint8_t router_purpose_from_string(const char *s); + +#ifdef ROUTER_PRIVATE +/* Used only by router.c and test.c */ +void get_platform_str(char *platform, size_t len); +#endif + +#endif + diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 2fc80738f8..670574a9d3 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -12,6 +12,25 @@ **/ #include "or.h" +#include "circuitbuild.h" +#include "config.h" +#include "connection.h" +#include "control.h" +#include "directory.h" +#include "dirserv.h" +#include "dirvote.h" +#include "geoip.h" +#include "hibernate.h" +#include "main.h" +#include "networkstatus.h" +#include "policies.h" +#include "reasons.h" +#include "rendcommon.h" +#include "rendservice.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" // #define DEBUG_ROUTERLIST @@ -26,8 +45,8 @@ static void mark_all_trusteddirservers_up(void); static int router_nickname_matches(routerinfo_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 void update_consensus_router_descriptor_downloads(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, @@ -156,21 +175,24 @@ already_have_cert(authority_cert_t *cert) /** Load a bunch of new key certificates from the string <b>contents</b>. If * <b>from_store</b> is true, the certificates are from the cache, and we - * don't need to flush them to disk. If <b>from_store</b> is false, we need - * to flush any changed certificates to disk. Return 0 on success, -1 on - * failure. */ + * don't need to flush them to disk. If <b>flush</b> is true, we need + * to flush any changed certificates to disk now. Return 0 on success, -1 + * if any certs fail to parse. */ int trusted_dirs_load_certs_from_string(const char *contents, int from_store, int flush) { trusted_dir_server_t *ds; const char *s, *eos; + int failure_code = 0; for (s = contents; *s; s = eos) { authority_cert_t *cert = authority_cert_parse_from_string(s, &eos); cert_list_t *cl; - if (!cert) + if (!cert) { + failure_code = -1; break; + } ds = trusteddirserver_get_by_v3_auth_digest( cert->cache_info.identity_digest); log_debug(LD_DIR, "Parsed certificate for %s", @@ -181,15 +203,15 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, log_info(LD_DIR, "Skipping %s certificate for %s that we " "already have.", from_store ? "cached" : "downloaded", - ds ? ds->nickname : "??"); + ds ? ds->nickname : "an old or new authority"); /* a duplicate on a download should be treated as a failure, since it * probably means we wanted a different secret key or we are trying to * replace an expired cert that has not in fact been updated. */ if (!from_store) { - log_warn(LD_DIR, "Got a certificate for %s that we already have. " - "Maybe they haven't updated it. Waiting for a while.", - ds ? ds->nickname : "??"); + log_warn(LD_DIR, "Got a certificate for %s, but we already have it. " + "Maybe they haven't updated it. Waiting for a while.", + ds ? ds->nickname : "an old or new authority"); authority_cert_dl_failed(cert->cache_info.identity_digest, 404); } @@ -224,7 +246,7 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, ds->dir_port != cert->dir_port)) { char *a = tor_dup_ip(cert->addr); log_notice(LD_DIR, "Updating address for directory authority %s " - "from %s:%d to %s:%d based on in certificate.", + "from %s:%d to %s:%d based on certificate.", ds->nickname, ds->address, (int)ds->dir_port, a, cert->dir_port); tor_free(a); @@ -241,8 +263,11 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, if (flush) trusted_dirs_flush_certs_to_disk(); + /* call this even if failure_code is <0, since some certs might have + * succeeded. */ networkstatus_note_certs_arrived(); - return 0; + + return failure_code; } /** Save all v3 key certificates to the cached-certs file. */ @@ -415,6 +440,23 @@ authority_cert_dl_failed(const char *id_digest, int status) download_status_failed(&cl->dl_status, status); } +/** Return true iff when we've been getting enough failures when trying to + * download the certificate with ID digest <b>id_digest</b> that we're willing + * to start bugging the user about it. */ +int +authority_cert_dl_looks_uncertain(const char *id_digest) +{ +#define N_AUTH_CERT_DL_FAILURES_TO_BUG_USER 2 + cert_list_t *cl; + int n_failures; + if (!trusted_dir_certs || + !(cl = digestmap_get(trusted_dir_certs, id_digest))) + return 0; + + n_failures = download_status_get_n_failures(&cl->dl_status); + return n_failures >= N_AUTH_CERT_DL_FAILURES_TO_BUG_USER; +} + /** How many times will we try to fetch a certificate before giving up? */ #define MAX_CERT_DL_FAILURES 8 @@ -442,17 +484,18 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now) list_pending_downloads(pending, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); if (status) { - SMARTLIST_FOREACH(status->voters, networkstatus_voter_info_t *, voter, - { - if (tor_digest_is_zero(voter->signing_key_digest)) - continue; /* This authority never signed this consensus, so don't - * go looking for a cert with key digest 0000000000. */ - if (!cache && - !trusteddirserver_get_by_v3_auth_digest(voter->identity_digest)) - continue; /* We are not a cache, and we don't know this authority.*/ - cl = get_cert_list(voter->identity_digest); + SMARTLIST_FOREACH_BEGIN(status->voters, networkstatus_voter_info_t *, + voter) { + if (!smartlist_len(voter->sigs)) + continue; /* This authority never signed this consensus, so don't + * go looking for a cert with key digest 0000000000. */ + if (!cache && + !trusteddirserver_get_by_v3_auth_digest(voter->identity_digest)) + continue; /* We are not a cache, and we don't know this authority.*/ + cl = get_cert_list(voter->identity_digest); + SMARTLIST_FOREACH_BEGIN(voter->sigs, document_signature_t *, sig) { cert = authority_cert_get_by_digests(voter->identity_digest, - voter->signing_key_digest); + sig->signing_key_digest); if (cert) { if (now < cert->expires) download_status_reset(&cl->dl_status); @@ -463,37 +506,36 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now) !digestmap_get(pending, voter->identity_digest)) { log_notice(LD_DIR, "We're missing a certificate from authority " "with signing key %s: launching request.", - hex_str(voter->signing_key_digest, DIGEST_LEN)); - smartlist_add(missing_digests, voter->identity_digest); + hex_str(sig->signing_key_digest, DIGEST_LEN)); + smartlist_add(missing_digests, sig->identity_digest); } - }); + } SMARTLIST_FOREACH_END(sig); + } SMARTLIST_FOREACH_END(voter); } - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, - { - int found = 0; - if (!(ds->type & V3_AUTHORITY)) - continue; - if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest)) - continue; - cl = get_cert_list(ds->v3_identity_digest); - SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert, - { - if (!ftime_definitely_after(now, cert->expires)) { - /* It's not expired, and we weren't looking for something to - * verify a consensus with. Call it done. */ - download_status_reset(&cl->dl_status); - found = 1; - break; - } - }); - if (!found && - download_status_is_ready(&cl->dl_status, now,MAX_CERT_DL_FAILURES) && - !digestmap_get(pending, ds->v3_identity_digest)) { - log_notice(LD_DIR, "No current certificate known for authority %s; " - "launching request.", ds->nickname); - smartlist_add(missing_digests, ds->v3_identity_digest); + SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) { + int found = 0; + if (!(ds->type & V3_AUTHORITY)) + continue; + if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest)) + continue; + cl = get_cert_list(ds->v3_identity_digest); + SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert, { + if (!ftime_definitely_after(now, cert->expires)) { + /* It's not expired, and we weren't looking for something to + * verify a consensus with. Call it done. */ + download_status_reset(&cl->dl_status); + found = 1; + break; } }); + if (!found && + download_status_is_ready(&cl->dl_status, now,MAX_CERT_DL_FAILURES) && + !digestmap_get(pending, ds->v3_identity_digest)) { + log_notice(LD_DIR, "No current certificate known for authority %s; " + "launching request.", ds->nickname); + smartlist_add(missing_digests, ds->v3_identity_digest); + } + } SMARTLIST_FOREACH_END(ds); if (!smartlist_len(missing_digests)) { goto done; @@ -749,8 +791,7 @@ router_rebuild_store(int flags, desc_store_t *store) store->journal_len = 0; store->bytes_dropped = 0; done: - if (signed_descriptors) - smartlist_free(signed_descriptors); + smartlist_free(signed_descriptors); tor_free(fname); tor_free(fname_tmp); if (chunk_list) { @@ -968,8 +1009,9 @@ router_get_trusteddirserver_by_digest(const char *digest) return NULL; } -/** Return the trusted_dir_server_t for the directory authority whose identity - * key hashes to <b>digest</b>, or NULL if no such authority is known. +/** Return the trusted_dir_server_t for the directory authority whose + * v3 identity key hashes to <b>digest</b>, or NULL if no such authority + * is known. */ trusted_dir_server_t * trusteddirserver_get_by_v3_auth_digest(const char *digest) @@ -1089,9 +1131,10 @@ router_pick_directory_server_impl(authority_type_t type, int flags) } SMARTLIST_FOREACH_END(status); if (smartlist_len(tunnel)) { - result = routerstatus_sl_choose_by_bandwidth(tunnel); + result = routerstatus_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR); } else if (smartlist_len(overloaded_tunnel)) { - result = routerstatus_sl_choose_by_bandwidth(overloaded_tunnel); + result = routerstatus_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 * yet. Maybe one day we should. */ @@ -1099,9 +1142,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); + result = routerstatus_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR); } else if (smartlist_len(overloaded_direct)) { - result = routerstatus_sl_choose_by_bandwidth(overloaded_direct); + result = routerstatus_sl_choose_by_bandwidth(overloaded_direct, + WEIGHT_FOR_DIR); } else { result = smartlist_choose(trusted_direct); } @@ -1230,6 +1274,13 @@ mark_all_trusteddirservers_up(void) router_dir_info_changed(); } +/** Return true iff r1 and r2 have the same address and OR port. */ +int +routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2) +{ + return r1->addr == r2->addr && r1->or_port == r2->or_port; +} + /** Reset all internal variables used to count failed downloads of network * status objects. */ void @@ -1521,6 +1572,29 @@ router_get_advertised_bandwidth_capped(routerinfo_t *router) return result; } +/** When weighting bridges, enforce these values as lower and upper + * bound for believable bandwidth, because there is no way for us + * to verify a bridge's bandwidth currently. */ +#define BRIDGE_MIN_BELIEVABLE_BANDWIDTH 20000 /* 20 kB/sec */ +#define BRIDGE_MAX_BELIEVABLE_BANDWIDTH 100000 /* 100 kB/sec */ + +/** Return the smaller of the router's configured BandwidthRate + * and its advertised capacity, making sure to stay within the + * interval between bridge-min-believe-bw and + * bridge-max-believe-bw. */ +static uint32_t +bridge_get_advertised_bandwidth_bounded(routerinfo_t *router) +{ + uint32_t result = router->bandwidthcapacity; + if (result > router->bandwidthrate) + result = router->bandwidthrate; + if (result > BRIDGE_MAX_BELIEVABLE_BANDWIDTH) + result = BRIDGE_MAX_BELIEVABLE_BANDWIDTH; + else if (result < BRIDGE_MIN_BELIEVABLE_BANDWIDTH) + result = BRIDGE_MIN_BELIEVABLE_BANDWIDTH; + return result; +} + /** Return bw*1000, unless bw*1000 would overflow, in which case return * INT32_MAX. */ static INLINE int32_t @@ -1531,6 +1605,219 @@ kb_to_bytes(uint32_t bw) /** Helper function: * choose a random element of smartlist <b>sl</b>, 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 + * <b>rule</b>==NO_WEIGHTING, we're picking a non-exit node: weight + * exit-node's bandwidth less depending on the smallness of the fraction of + * Exit-to-total bandwidth. If <b>rule</b>==WEIGHT_FOR_GUARD, we're picking a + * 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) +{ + int64_t weight_scale; + int64_t rand_bw; + double Wg = -1, Wm = -1, We = -1, Wd = -1; + double Wgb = -1, Wmb = -1, Web = -1, Wdb = -1; + double weighted_bw = 0; + double *bandwidths; + double tmp = 0; + unsigned int i; + int have_unknown = 0; /* true iff sl contains element not in consensus. */ + + /* Can't choose exit and guard at same time */ + tor_assert(rule == NO_WEIGHTING || + rule == WEIGHT_FOR_EXIT || + rule == WEIGHT_FOR_GUARD || + rule == WEIGHT_FOR_MID || + rule == WEIGHT_FOR_DIR); + + if (smartlist_len(sl) == 0) { + log_info(LD_CIRC, + "Empty routerlist passed in to consensus weight node " + "selection for rule %s", + bandwidth_weight_rule_to_string(rule)); + return NULL; + } + + weight_scale = networkstatus_get_param(NULL, "bwweightscale", + BW_WEIGHT_SCALE); + + if (rule == WEIGHT_FOR_GUARD) { + Wg = networkstatus_get_bw_weight(NULL, "Wgg", -1); + Wm = networkstatus_get_bw_weight(NULL, "Wgm", -1); /* Bridges */ + We = 0; + Wd = networkstatus_get_bw_weight(NULL, "Wgd", -1); + + Wgb = networkstatus_get_bw_weight(NULL, "Wgb", -1); + Wmb = networkstatus_get_bw_weight(NULL, "Wmb", -1); + Web = networkstatus_get_bw_weight(NULL, "Web", -1); + Wdb = networkstatus_get_bw_weight(NULL, "Wdb", -1); + } else if (rule == WEIGHT_FOR_MID) { + Wg = networkstatus_get_bw_weight(NULL, "Wmg", -1); + Wm = networkstatus_get_bw_weight(NULL, "Wmm", -1); + We = networkstatus_get_bw_weight(NULL, "Wme", -1); + Wd = networkstatus_get_bw_weight(NULL, "Wmd", -1); + + Wgb = networkstatus_get_bw_weight(NULL, "Wgb", -1); + Wmb = networkstatus_get_bw_weight(NULL, "Wmb", -1); + Web = networkstatus_get_bw_weight(NULL, "Web", -1); + Wdb = networkstatus_get_bw_weight(NULL, "Wdb", -1); + } else if (rule == WEIGHT_FOR_EXIT) { + // Guards CAN be exits if they have weird exit policies + // They are d then I guess... + We = networkstatus_get_bw_weight(NULL, "Wee", -1); + Wm = networkstatus_get_bw_weight(NULL, "Wem", -1); /* Odd exit policies */ + Wd = networkstatus_get_bw_weight(NULL, "Wed", -1); + Wg = networkstatus_get_bw_weight(NULL, "Weg", -1); /* Odd exit policies */ + + Wgb = networkstatus_get_bw_weight(NULL, "Wgb", -1); + Wmb = networkstatus_get_bw_weight(NULL, "Wmb", -1); + Web = networkstatus_get_bw_weight(NULL, "Web", -1); + Wdb = networkstatus_get_bw_weight(NULL, "Wdb", -1); + } else if (rule == WEIGHT_FOR_DIR) { + We = networkstatus_get_bw_weight(NULL, "Wbe", -1); + Wm = networkstatus_get_bw_weight(NULL, "Wbm", -1); + Wd = networkstatus_get_bw_weight(NULL, "Wbd", -1); + Wg = networkstatus_get_bw_weight(NULL, "Wbg", -1); + + Wgb = Wmb = Web = Wdb = weight_scale; + } else if (rule == NO_WEIGHTING) { + Wg = Wm = We = Wd = weight_scale; + Wgb = Wmb = Web = Wdb = weight_scale; + } + + if (Wg < 0 || Wm < 0 || We < 0 || Wd < 0 || Wgb < 0 || Wmb < 0 || Wdb < 0 + || Web < 0) { + log_debug(LD_CIRC, + "Got negative bandwidth weights. Defaulting to old selection" + " algorithm."); + return NULL; // Use old algorithm. + } + + Wg /= weight_scale; + Wm /= weight_scale; + We /= weight_scale; + Wd /= weight_scale; + + Wgb /= weight_scale; + Wmb /= weight_scale; + Web /= weight_scale; + Wdb /= weight_scale; + + 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) { + 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; + is_guard = status->is_possible_guard; + is_dir = (status->dir_port != 0); + if (!status->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. */ + log_warn(LD_BUG, + "Consensus is not listing bandwidths. Defaulting back to " + "old router selection algorithm."); + return NULL; + } + this_bw = kb_to_bytes(status->bandwidth); + if (router_digest_is_me(status->identity_digest)) + is_me = 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; + 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; + } + if (is_guard && is_exit) { + weight = (is_dir ? Wdb*Wd : Wd); + } else if (is_guard) { + weight = (is_dir ? Wgb*Wg : Wg); + } else if (is_exit) { + weight = (is_dir ? Web*We : We); + } else { // middle + weight = (is_dir ? Wmb*Wm : Wm); + } + + bandwidths[i] = weight*this_bw; + weighted_bw += weight*this_bw; + if (is_me) + sl_last_weighted_bw_of_me = weight*this_bw; + } + + /* XXXX022 this is a kludge to expose these values. */ + sl_last_total_weighted_bw = weighted_bw; + + log_debug(LD_CIRC, "Choosing node for rule %s based on weights " + "Wg=%lf Wm=%lf We=%lf Wd=%lf with total bw %lf", + bandwidth_weight_rule_to_string(rule), + Wg, Wm, We, Wd, weighted_bw); + + /* If there is no bandwidth, choose at random */ + if (DBL_TO_U64(weighted_bw) == 0) { + /* Don't warn when using bridges/relays not in the consensus */ + if (!have_unknown) + log_warn(LD_CIRC, + "Weighted bandwidth is %lf in node selection for rule %s", + weighted_bw, bandwidth_weight_rule_to_string(rule)); + tor_free(bandwidths); + return smartlist_choose(sl); + } + + rand_bw = crypto_rand_uint64(DBL_TO_U64(weighted_bw)); + rand_bw++; /* crypto_rand_uint64() counts from 0, and we need to count + * from 1 below. See bug 1203 for details. */ + + /* Last, count through sl until we get to the element we picked */ + tmp = 0.0; + for (i=0; i < (unsigned)smartlist_len(sl); i++) { + tmp += bandwidths[i]; + if (tmp >= rand_bw) + break; + } + + if (i == (unsigned)smartlist_len(sl)) { + /* This was once possible due to round-off error, but shouldn't be able + * to occur any longer. */ + tor_fragile_assert(); + --i; + log_warn(LD_BUG, "Round-off error in computing bandwidth had an effect on " + " which router we chose. Please tell the developers. " + "%lf " U64_FORMAT " %lf", tmp, U64_PRINTF_ARG(rand_bw), + weighted_bw); + } + tor_free(bandwidths); + return smartlist_get(sl, i); +} + +/** Helper function: + * choose a random 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 @@ -1565,11 +1852,24 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, bitarray_t *guard_bits; int me_idx = -1; + // This function does not support WEIGHT_FOR_DIR + // or WEIGHT_FOR_MID + if (rule == WEIGHT_FOR_DIR || rule == WEIGHT_FOR_MID) { + rule = NO_WEIGHTING; + } + /* Can't choose exit and guard at same time */ tor_assert(rule == NO_WEIGHTING || rule == WEIGHT_FOR_EXIT || rule == WEIGHT_FOR_GUARD); + if (smartlist_len(sl) == 0) { + log_info(LD_CIRC, + "Empty routerlist passed in to old node selection for rule %s", + bandwidth_weight_rule_to_string(rule)); + return NULL; + } + /* First count the total bandwidth weight, and make a list * of each value. <0 means "unknown; no routerinfo." We use the * bits of negative values to remember whether the router was fast (-x)&1 @@ -1620,7 +1920,7 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, flags |= is_exit ? 2 : 0; flags |= is_guard ? 4 : 0; } else /* bridge or other descriptor not in our consensus */ - this_bw = router_get_advertised_bandwidth_capped(router); + this_bw = bridge_get_advertised_bandwidth_bounded(router); } if (is_exit) bitarray_set(exit_bits, i); @@ -1628,6 +1928,8 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, bitarray_set(guard_bits, i); if (is_known) { bandwidths[i] = (int32_t) this_bw; // safe since MAX_BELIEVABLE<INT32_MAX + // XXX this is no longer true! We don't always cap the bw anymore. Can + // a consensus make us overflow?-sh tor_assert(bandwidths[i] >= 0); if (is_guard) total_guard_bw += this_bw; @@ -1691,12 +1993,12 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, * For detailed derivation of this formula, see * http://archives.seul.org/or/dev/Jul-2007/msg00056.html */ - if (rule == WEIGHT_FOR_EXIT) + if (rule == WEIGHT_FOR_EXIT || !total_exit_bw) exit_weight = 1.0; else exit_weight = 1.0 - all_bw/(3.0*exit_bw); - if (rule == WEIGHT_FOR_GUARD) + if (rule == WEIGHT_FOR_GUARD || !total_guard_bw) guard_weight = 1.0; else guard_weight = 1.0 - all_bw/(3.0*guard_bw); @@ -1745,6 +2047,8 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, /* Almost done: choose a random value from the bandwidth weights. */ rand_bw = crypto_rand_uint64(total_bw); + rand_bw++; /* crypto_rand_uint64() counts from 0, and we need to count + * from 1 below. See bug 1203 for details. */ /* Last, count through sl until we get to the element we picked */ tmp = 0; @@ -1788,26 +2092,34 @@ routerinfo_t * routerlist_sl_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule) { - return smartlist_choose_by_bandwidth(sl, rule, 0); + 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) +routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, + bandwidth_weight_rule_t rule) { /* We are choosing neither exit nor guard here. Weight accordingly. */ - return smartlist_choose_by_bandwidth(sl, NO_WEIGHTING, 1); + routerstatus_t *ret; + if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 1))) { + return ret; + } else { + return smartlist_choose_by_bandwidth(sl, rule, 1); + } } -/** Return a random running router from the routerlist. If any node - * named in <b>preferred</b> is available, pick one of those. Never +/** 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>, - * even if they are the only nodes - * available. If <b>CRN_STRICT_PREFERRED</b> is set in flags, never pick - * any node besides those in <b>preferred</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. * If <b>CRN_NEED_CAPACITY</b> is set in flags, weight your choice by the @@ -1820,8 +2132,7 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl) * node (that is, possibly discounting exit nodes). */ routerinfo_t * -router_choose_random_node(const char *preferred, - smartlist_t *excludedsmartlist, +router_choose_random_node(smartlist_t *excludedsmartlist, routerset_t *excludedset, router_crn_flags_t flags) { @@ -1829,18 +2140,16 @@ router_choose_random_node(const char *preferred, 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 strict = (flags & CRN_STRICT_PREFERRED) != 0; const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0; - smartlist_t *sl, *excludednodes; + smartlist_t *sl=smartlist_create(), + *excludednodes=smartlist_create(); routerinfo_t *choice = NULL, *r; bandwidth_weight_rule_t rule; tor_assert(!(weight_for_exit && need_guard)); rule = weight_for_exit ? WEIGHT_FOR_EXIT : - (need_guard ? WEIGHT_FOR_GUARD : NO_WEIGHTING); - - excludednodes = smartlist_create(); + (need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID); /* Exclude relays that allow single hop exit circuits, if the user * wants to (such relays might be risky) */ @@ -1857,60 +2166,35 @@ router_choose_random_node(const char *preferred, routerlist_add_family(excludednodes, r); } - /* Try the preferred nodes first. Ignore need_uptime and need_capacity - * and need_guard, since the user explicitly asked for these nodes. */ - if (preferred) { - sl = smartlist_create(); - add_nickname_list_to_smartlist(sl,preferred,1); - smartlist_subtract(sl,excludednodes); - if (excludedsmartlist) - smartlist_subtract(sl,excludedsmartlist); - if (excludedset) - routerset_subtract_routers(sl,excludedset); - choice = smartlist_choose(sl); - smartlist_free(sl); - } - if (!choice && !strict) { - /* Then give up on our preferred choices: any node - * will do that has the required attributes. */ - sl = smartlist_create(); - router_add_running_routers_to_smartlist(sl, allow_invalid, - need_uptime, need_capacity, - need_guard); - smartlist_subtract(sl,excludednodes); - if (excludedsmartlist) - smartlist_subtract(sl,excludedsmartlist); - if (excludedset) - routerset_subtract_routers(sl,excludedset); - - if (need_capacity || need_guard) - choice = routerlist_sl_choose_by_bandwidth(sl, rule); - else - choice = smartlist_choose(sl); - - smartlist_free(sl); - if (!choice && (need_uptime || need_capacity || need_guard)) { - /* try once more -- recurse but with fewer restrictions. */ - log_info(LD_CIRC, - "We couldn't find any live%s%s%s routers; falling back " - "to list of all routers.", - need_capacity?", fast":"", - need_uptime?", stable":"", - need_guard?", guard":""); - flags &= ~ (CRN_NEED_UPTIME|CRN_NEED_CAPACITY|CRN_NEED_GUARD); - choice = router_choose_random_node( - NULL, excludedsmartlist, excludedset, flags); - } + router_add_running_routers_to_smartlist(sl, allow_invalid, + need_uptime, need_capacity, + need_guard); + smartlist_subtract(sl,excludednodes); + if (excludedsmartlist) + smartlist_subtract(sl,excludedsmartlist); + if (excludedset) + routerset_subtract_routers(sl,excludedset); + + // Always weight by bandwidth + choice = routerlist_sl_choose_by_bandwidth(sl, rule); + + smartlist_free(sl); + if (!choice && (need_uptime || need_capacity || need_guard)) { + /* try once more -- recurse but with fewer restrictions. */ + log_info(LD_CIRC, + "We couldn't find any live%s%s%s routers; falling back " + "to list of all routers.", + need_capacity?", fast":"", + need_uptime?", stable":"", + need_guard?", guard":""); + flags &= ~ (CRN_NEED_UPTIME|CRN_NEED_CAPACITY|CRN_NEED_GUARD); + choice = router_choose_random_node( + excludedsmartlist, excludedset, flags); } smartlist_free(excludednodes); if (!choice) { - if (strict) { - log_warn(LD_CIRC, "All preferred nodes were down when trying to choose " - "node, and the Strict[...]Nodes option is set. Failing."); - } else { - log_warn(LD_CIRC, - "No available nodes when trying to choose node. Failing."); - } + log_warn(LD_CIRC, + "No available nodes when trying to choose node. Failing."); } return choice; } @@ -1989,9 +2273,6 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) return router_get_by_hexdigest(nickname); if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME)) return NULL; - if (server_mode(get_options()) && - !strcasecmp(nickname, get_options()->Nickname)) - return router_get_my_routerinfo(); maybedigest = (strlen(nickname) >= HEX_DIGEST_LEN) && (base16_decode(digest,DIGEST_LEN,nickname,HEX_DIGEST_LEN) == 0); @@ -2370,6 +2651,9 @@ extrainfo_free(extrainfo_t *extrainfo) static void signed_descriptor_free(signed_descriptor_t *sd) { + if (!sd) + return; + tor_free(sd->signed_descriptor_body); /* XXXX remove this once more bugs go away. */ @@ -2377,12 +2661,15 @@ signed_descriptor_free(signed_descriptor_t *sd) tor_free(sd); } -/** Extract a signed_descriptor_t from a routerinfo, and free the routerinfo. +/** Extract a signed_descriptor_t from a general routerinfo, and free the + * routerinfo. */ static signed_descriptor_t * signed_descriptor_from_routerinfo(routerinfo_t *ri) { - signed_descriptor_t *sd = tor_malloc_zero(sizeof(signed_descriptor_t)); + signed_descriptor_t *sd; + tor_assert(ri->purpose == ROUTER_PURPOSE_GENERAL); + sd = tor_malloc_zero(sizeof(signed_descriptor_t)); memcpy(sd, &(ri->cache_info), sizeof(signed_descriptor_t)); sd->routerlist_index = -1; ri->cache_info.signed_descriptor_body = NULL; @@ -2401,7 +2688,8 @@ _extrainfo_free(void *e) void routerlist_free(routerlist_t *rl) { - tor_assert(rl); + if (!rl) + return; rimap_free(rl->identity_map, NULL); sdmap_free(rl->desc_digest_map, NULL); sdmap_free(rl->desc_by_eid_map, NULL); @@ -2440,46 +2728,6 @@ dump_routerlist_mem_usage(int severity) "In %d old descriptors: "U64_FORMAT" bytes.", smartlist_len(routerlist->routers), U64_PRINTF_ARG(livedescs), smartlist_len(routerlist->old_routers), U64_PRINTF_ARG(olddescs)); - -#if 0 - { - const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list(); - networkstatus_t *consensus = networkstatus_get_latest_consensus(); - log(severity, LD_DIR, "Now let's look through old_descriptors!"); - SMARTLIST_FOREACH(routerlist->old_routers, signed_descriptor_t *, sd, { - int in_v2 = 0; - int in_v3 = 0; - char published[ISO_TIME_LEN+1]; - char last_valid_until[ISO_TIME_LEN+1]; - char last_served_at[ISO_TIME_LEN+1]; - char id[HEX_DIGEST_LEN+1]; - routerstatus_t *rs; - format_iso_time(published, sd->published_on); - format_iso_time(last_valid_until, sd->last_listed_as_valid_until); - format_iso_time(last_served_at, sd->last_served_at); - base16_encode(id, sizeof(id), sd->identity_digest, DIGEST_LEN); - SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, - { - rs = networkstatus_v2_find_entry(ns, sd->identity_digest); - if (rs && !memcmp(rs->descriptor_digest, - sd->signed_descriptor_digest, DIGEST_LEN)) { - in_v2 = 1; break; - } - }); - if (consensus) { - rs = networkstatus_vote_find_entry(consensus, sd->identity_digest); - if (rs && !memcmp(rs->descriptor_digest, - sd->signed_descriptor_digest, DIGEST_LEN)) - in_v3 = 1; - } - log(severity, LD_DIR, - "Old descriptor for %s (published %s) %sin v2 ns, %sin v3 " - "consensus. Last valid until %s; last served at %s.", - id, published, in_v2 ? "" : "not ", in_v3 ? "" : "not ", - last_valid_until, last_served_at); - }); - } -#endif } /** Debugging helper: If <b>idx</b> is nonnegative, assert that <b>ri</b> is @@ -2512,6 +2760,7 @@ static void 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(); @@ -2521,8 +2770,16 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri) ri_old = rimap_set(rl->identity_map, ri->cache_info.identity_digest, ri); tor_assert(!ri_old); - sdmap_set(rl->desc_digest_map, ri->cache_info.signed_descriptor_digest, - &(ri->cache_info)); + + sd_old = sdmap_set(rl->desc_digest_map, + ri->cache_info.signed_descriptor_digest, + &(ri->cache_info)); + if (sd_old) { + rl->desc_store.bytes_dropped += sd_old->signed_descriptor_len; + sdmap_remove(rl->desc_by_eid_map, sd_old->extra_info_digest); + signed_descriptor_free(sd_old); + } + if (!tor_digest_is_zero(ri->cache_info.extra_info_digest)) sdmap_set(rl->desc_by_eid_map, ri->cache_info.extra_info_digest, &ri->cache_info); @@ -2741,6 +2998,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, routerinfo_t *ri_new) { int idx; + int same_descriptors; routerinfo_t *ri_tmp; extrainfo_t *ei_tmp; @@ -2785,8 +3043,15 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, &ri_new->cache_info); } + same_descriptors = ! memcmp(ri_old->cache_info.signed_descriptor_digest, + ri_new->cache_info.signed_descriptor_digest, + DIGEST_LEN); + if (should_cache_old_descriptors() && - ri_old->purpose == ROUTER_PURPOSE_GENERAL) { + ri_old->purpose == ROUTER_PURPOSE_GENERAL && + !same_descriptors) { + /* ri_old is going to become a signed_descriptor_t and go into + * old_routers */ signed_descriptor_t *sd = signed_descriptor_from_routerinfo(ri_old); smartlist_add(rl->old_routers, sd); sd->routerlist_index = smartlist_len(rl->old_routers)-1; @@ -2794,24 +3059,27 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, if (!tor_digest_is_zero(sd->extra_info_digest)) sdmap_set(rl->desc_by_eid_map, sd->extra_info_digest, sd); } else { - if (memcmp(ri_old->cache_info.signed_descriptor_digest, - ri_new->cache_info.signed_descriptor_digest, - DIGEST_LEN)) { - /* digests don't match; digestmap_set didn't replace */ + /* We're dropping ri_old. */ + if (!same_descriptors) { + /* digests don't match; The sdmap_set above didn't replace */ sdmap_remove(rl->desc_digest_map, ri_old->cache_info.signed_descriptor_digest); - } - ei_tmp = eimap_remove(rl->extra_info_map, - ri_old->cache_info.extra_info_digest); - if (ei_tmp) { - rl->extrainfo_store.bytes_dropped += - ei_tmp->cache_info.signed_descriptor_len; - extrainfo_free(ei_tmp); - } - if (!tor_digest_is_zero(ri_old->cache_info.extra_info_digest)) { - sdmap_remove(rl->desc_by_eid_map, - ri_old->cache_info.extra_info_digest); + if (memcmp(ri_old->cache_info.extra_info_digest, + ri_new->cache_info.extra_info_digest, DIGEST_LEN)) { + ei_tmp = eimap_remove(rl->extra_info_map, + ri_old->cache_info.extra_info_digest); + if (ei_tmp) { + rl->extrainfo_store.bytes_dropped += + ei_tmp->cache_info.signed_descriptor_len; + extrainfo_free(ei_tmp); + } + } + + if (!tor_digest_is_zero(ri_old->cache_info.extra_info_digest)) { + sdmap_remove(rl->desc_by_eid_map, + ri_old->cache_info.extra_info_digest); + } } rl->desc_store.bytes_dropped += ri_old->cache_info.signed_descriptor_len; routerinfo_free(ri_old); @@ -2849,8 +3117,7 @@ routerlist_reparse_old(routerlist_t *rl, signed_descriptor_t *sd) void routerlist_free_all(void) { - if (routerlist) - routerlist_free(routerlist); + routerlist_free(routerlist); routerlist = NULL; if (warned_nicknames) { SMARTLIST_FOREACH(warned_nicknames, char *, cp, tor_free(cp)); @@ -2957,15 +3224,33 @@ 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); + /* Make sure that we haven't already got this exact descriptor. */ if (sdmap_get(routerlist->desc_digest_map, router->cache_info.signed_descriptor_digest)) { - log_info(LD_DIR, - "Dropping descriptor that we already have for router '%s'", - router->nickname); - *msg = "Router descriptor was not new."; - routerinfo_free(router); - return ROUTER_WAS_NOT_NEW; + /* If we have this descriptor already and the new descriptor is a bridge + * descriptor, replace it. If we had a bridge descriptor before and the + * new one is not a bridge descriptor, don't replace it. */ + + /* Only members of routerlist->identity_map can be bridges; we don't + * put bridges in old_routers. */ + const int was_bridge = old_router && + old_router->purpose == ROUTER_PURPOSE_BRIDGE; + + if (routerinfo_is_a_configured_bridge(router) && + router->purpose == ROUTER_PURPOSE_BRIDGE && + !was_bridge) { + log_info(LD_DIR, "Replacing non-bridge descriptor with bridge " + "descriptor for router '%s'", router->nickname); + } else { + log_info(LD_DIR, + "Dropping descriptor that we already have for router '%s'", + router->nickname); + *msg = "Router descriptor was not new."; + routerinfo_free(router); + return ROUTER_WAS_NOT_NEW; + } } if (authdir) { @@ -3002,15 +3287,14 @@ 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, router->cache_info.identity_digest); + networkstatus_v2_find_entry(ns, id_digest); if (rs && !memcmp(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, - router->cache_info.identity_digest); + routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest); if (rs && !memcmp(rs->descriptor_digest, router->cache_info.signed_descriptor_digest, DIGEST_LEN)) { @@ -3032,13 +3316,11 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, } /* If we have a router with the same identity key, choose the newer one. */ - old_router = rimap_get(routerlist->identity_map, - router->cache_info.identity_digest); if (old_router) { if (!in_consensus && (router->cache_info.published_on <= old_router->cache_info.published_on)) { /* Same key, but old. This one is not listed in the consensus. */ - log_debug(LD_DIR, "Skipping not-new descriptor for router '%s'", + log_debug(LD_DIR, "Not-new descriptor for router '%s'", router->nickname); /* Only journal this desc if we'll be serving it. */ if (!from_cache && should_cache_old_descriptors()) @@ -3052,8 +3334,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, log_debug(LD_DIR, "Replacing entry for router '%s/%s' [%s]", router->nickname, old_router->nickname, hex_str(id_digest,DIGEST_LEN)); - if (router->addr == old_router->addr && - router->or_port == old_router->or_port) { + if (routers_have_same_or_addr(router, old_router)) { /* these carry over when the address and orport are unchanged. */ router->last_reachable = old_router->last_reachable; router->testing_since = old_router->testing_since; @@ -3081,9 +3362,10 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, /* We haven't seen a router with this identity before. Add it to the end of * the list. */ routerlist_insert(routerlist, router); - if (!from_cache) + if (!from_cache) { signed_desc_append_to_journal(&router->cache_info, &routerlist->desc_store); + } directory_set_dirty(); return ROUTER_ADDED_SUCCESSFULLY; } @@ -3400,15 +3682,19 @@ routerlist_remove_old_routers(void) /** We just added a new set of descriptors. Take whatever extra steps * we need. */ -static void +void routerlist_descriptors_added(smartlist_t *sl, int from_cache) { tor_assert(sl); control_event_descriptors_changed(sl); - SMARTLIST_FOREACH(sl, routerinfo_t *, ri, + SMARTLIST_FOREACH_BEGIN(sl, routerinfo_t *, ri) { if (ri->purpose == ROUTER_PURPOSE_BRIDGE) learned_bridge_descriptor(ri, from_cache); - ); + if (ri->needs_retest_if_added) { + ri->needs_retest_if_added = 0; + dirserv_single_reachability_test(approx_time(), ri); + } + } SMARTLIST_FOREACH_END(ri); } /** @@ -3739,12 +4025,8 @@ add_trusted_dir_server(const char *nickname, const char *address, if (ent->or_port) ent->fake_status.version_supports_begindir = 1; -/* XX021 - wait until authorities are upgraded */ -#if 0 + ent->fake_status.version_supports_conditional_consensus = 1; -#else - ent->fake_status.version_supports_conditional_consensus = 0; -#endif smartlist_add(trusted_dir_servers, ent); router_dir_info_changed(); @@ -3759,10 +4041,8 @@ authority_cert_free(authority_cert_t *cert) return; tor_free(cert->cache_info.signed_descriptor_body); - if (cert->signing_key) - crypto_free_pk_env(cert->signing_key); - if (cert->identity_key) - crypto_free_pk_env(cert->identity_key); + crypto_free_pk_env(cert->signing_key); + crypto_free_pk_env(cert->identity_key); tor_free(cert); } @@ -3771,6 +4051,9 @@ authority_cert_free(authority_cert_t *cert) static void trusted_dir_server_free(trusted_dir_server_t *ds) { + if (!ds) + return; + tor_free(ds->nickname); tor_free(ds->description); tor_free(ds->address); @@ -3824,7 +4107,7 @@ list_pending_downloads(digestmap_t *result, const char *resource = TO_DIR_CONN(conn)->requested_resource; if (!strcmpstart(resource, prefix)) dir_split_resource_into_fingerprints(resource + p_len, - tmp, NULL, 1, 0); + tmp, NULL, DSR_HEX); } }); SMARTLIST_FOREACH(tmp, char *, d, @@ -3926,7 +4209,7 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) * this number per server. */ #define MIN_DL_PER_REQUEST 4 /** To prevent a single screwy cache from confusing us by selective reply, - * try to split our requests into at least this this many requests. */ + * try to split our requests into at least this many requests. */ #define MIN_REQUESTS 3 /** If we want fewer than this many descriptors, wait until we * want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has @@ -3940,7 +4223,8 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) * 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, time_t now) +launch_router_descriptor_downloads(smartlist_t *downloadable, + routerstatus_t *source, time_t now) { int should_delay = 0, n_downloadable; or_options_t *options = get_options(); @@ -3993,7 +4277,7 @@ launch_router_descriptor_downloads(smartlist_t *downloadable, time_t now) pds_flags |= PDS_NO_EXISTING_SERVERDESC_FETCH; } - n_per_request = (n_downloadable+MIN_REQUESTS-1) / MIN_REQUESTS; + 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 (n_per_request < MIN_DL_PER_REQUEST) @@ -4006,11 +4290,11 @@ launch_router_descriptor_downloads(smartlist_t *downloadable, time_t now) log_info(LD_DIR, "Launching %d request%s for %d router%s, %d at a time", - (n_downloadable+n_per_request-1)/n_per_request, + CEIL_DIV(n_downloadable, n_per_request), 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(NULL, DIR_PURPOSE_FETCH_SERVERDESC, + initiate_descriptor_downloads(source, DIR_PURPOSE_FETCH_SERVERDESC, downloadable, i, i+n_per_request, pds_flags); } @@ -4166,18 +4450,18 @@ update_router_descriptor_cache_downloads_v2(time_t now) digestmap_free(map,NULL); } -/** For any descriptor that we want that's currently listed in the live - * consensus, download it as appropriate. */ -static void -update_consensus_router_descriptor_downloads(time_t now) +/** For any descriptor that we want that's currently listed in + * <b>consensus</b>, download it as appropriate. */ +void +update_consensus_router_descriptor_downloads(time_t now, int is_vote, + networkstatus_t *consensus) { or_options_t *options = get_options(); digestmap_t *map = NULL; smartlist_t *no_longer_old = smartlist_create(); smartlist_t *downloadable = smartlist_create(); + routerstatus_t *source = NULL; int authdir = authdir_mode(options); - networkstatus_t *consensus = - networkstatus_get_reasonably_live_consensus(now); int n_delayed=0, n_have=0, n_would_reject=0, n_wouldnt_use=0, n_inprogress=0, n_in_oldrouters=0; @@ -4186,10 +4470,24 @@ update_consensus_router_descriptor_downloads(time_t now) if (!consensus) goto done; + if (is_vote) { + /* where's it from, so we know whom to ask for descriptors */ + trusted_dir_server_t *ds; + networkstatus_voter_info_t *voter = smartlist_get(consensus->voters, 0); + tor_assert(voter); + ds = trusteddirserver_get_by_v3_auth_digest(voter->identity_digest); + if (ds) + source = &(ds->fake_status); + else + log_warn(LD_DIR, "couldn't lookup source from vote?"); + } + map = digestmap_new(); list_pending_descriptor_downloads(map, 0); - SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs, + SMARTLIST_FOREACH(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; @@ -4224,6 +4522,18 @@ update_consensus_router_descriptor_downloads(time_t now) ++n_wouldnt_use; continue; /* We would never use it ourself. */ } + 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); + format_iso_time(time_bufnew, rs->published_on); + if (oldrouter) + format_iso_time(time_bufold, oldrouter->cache_info.published_on); + log_info(LD_DIR, "Learned about %s (%s vs %s) from %s's vote (%s)", + rs->nickname, time_bufnew, + oldrouter ? time_bufold : "none", + source->nickname, oldrouter ? "known" : "unknown"); + } smartlist_add(downloadable, rs->descriptor_digest); }); @@ -4257,7 +4567,7 @@ update_consensus_router_descriptor_downloads(time_t now) smartlist_len(downloadable), n_delayed, n_have, n_in_oldrouters, n_would_reject, n_wouldnt_use, n_inprogress); - launch_router_descriptor_downloads(downloadable, now); + launch_router_descriptor_downloads(downloadable, source, now); digestmap_free(map, NULL); done: @@ -4282,7 +4592,8 @@ update_router_descriptor_downloads(time_t now) if (directory_fetches_dir_info_early(options)) { update_router_descriptor_cache_downloads_v2(now); } - update_consensus_router_descriptor_downloads(now); + update_consensus_router_descriptor_downloads(now, 0, + networkstatus_get_reasonably_live_consensus(now)); /* XXXX021 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 @@ -4419,16 +4730,21 @@ get_dir_info_status_string(void) /** Iterate over the servers listed in <b>consensus</b>, and count how many of * them seem like ones we'd use, and how many of <em>those</em> we have * descriptors for. Store the former in *<b>num_usable</b> and the latter in - * *<b>num_present</b>. */ + * *<b>num_present</b>. If <b>in_set</b> is non-NULL, only consider those + * routers in <b>in_set</b>. + */ static void count_usable_descriptors(int *num_present, int *num_usable, const networkstatus_t *consensus, - or_options_t *options, time_t now) + or_options_t *options, time_t now, + routerset_t *in_set) { *num_present = 0, *num_usable=0; SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs, { + if (in_set && ! routerset_contains_routerstatus(in_set, rs)) + continue; if (client_would_use_router(rs, now, options)) { ++*num_usable; /* the consensus says we want it. */ if (router_get_by_descriptor_digest(rs->descriptor_digest)) { @@ -4457,7 +4773,7 @@ count_loading_descriptors_progress(void) return 0; /* can't count descriptors if we have no list of them */ count_usable_descriptors(&num_present, &num_usable, - consensus, get_options(), now); + consensus, get_options(), now, NULL); if (num_usable == 0) return 0; /* don't div by 0 */ @@ -4501,22 +4817,39 @@ update_router_have_minimum_dir_info(void) goto done; } - count_usable_descriptors(&num_present, &num_usable, consensus, options, now); + 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); 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"); res = 0; - } else { - res = 1; + goto done; } + /* Check for entry nodes. */ + if (options->EntryNodes) { + count_usable_descriptors(&num_present, &num_usable, consensus, options, + now, options->EntryNodes); + + 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); + res = 0; + goto done; + } + } + + res = 1; + done: if (res && !have_min_dir_info) { log(LOG_NOTICE, LD_DIR, @@ -4529,6 +4862,13 @@ update_router_have_minimum_dir_info(void) log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR, "Our directory information is no longer up-to-date " "enough to build circuits: %s", dir_info_status); + + /* a) make us log when we next complete a circuit, so we know when Tor + * is back up and usable, and b) disable some activities that Tor + * should only do while circuits are working, like reachability tests + * and fetching bridge descriptors only over circuits. */ + can_complete_circuit = 0; + control_event_client_status(LOG_NOTICE, "NOT_ENOUGH_DIR_INFO"); } have_min_dir_info = res; @@ -4814,8 +5154,8 @@ esc_router_info(routerinfo_t *router) static char *info=NULL; char *esc_contact, *esc_platform; size_t len; - if (info) - tor_free(info); + tor_free(info); + if (!router) return NULL; /* we're exiting; just free the memory we use */ @@ -4950,9 +5290,8 @@ void routerset_refresh_countries(routerset_t *target) { int cc; - if (target->countries) { - bitarray_free(target->countries); - } + bitarray_free(target->countries); + if (!geoip_is_loaded()) { target->countries = NULL; target->n_countries = 0; @@ -5026,7 +5365,9 @@ routerset_parse(routerset_t *target, const char *s, const char *description) return r; } -/** DOCDOC */ +/** Called when we change a node set, or when we reload the geoip list: + * recompute all country info in all configuration node sets and in the + * routerlist. */ void refresh_all_country_info(void) { @@ -5194,9 +5535,13 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset, } } -/** Add to <b>target</b> every routerinfo_t from <b>source</b> that is in - * <b>include</b>, but not excluded in a more specific fashion by - * <b>exclude</b>. If <b>running_only</b>, only include running routers. +/** Add to <b>target</b> every routerinfo_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 + * 2) Don't add it if <b>exclude</b> is non-empty and the relay is + * excluded in a more specific fashion by <b>exclude</b>. + * 3) If <b>running_only</b>, don't add non-running routers. */ void routersets_get_disjunction(smartlist_t *target, @@ -5266,35 +5611,15 @@ routerset_equal(const routerset_t *old, const routerset_t *new) }); return 1; - -#if 0 - /* XXXX: This won't work if the names/digests are identical but in a - different order. Checking for exact equality would be heavy going, - is it worth it? -RH*/ - /* This code is totally bogus; sizeof doesn't work even remotely like this - * code seems to think. Let's revert to a string-based comparison for - * now. -NM*/ - if (sizeof(old->names) != sizeof(new->names)) - return 0; - - if (memcmp(old->names,new->names,sizeof(new->names))) - return 0; - if (sizeof(old->digests) != sizeof(new->digests)) - return 0; - if (memcmp(old->digests,new->digests,sizeof(new->digests))) - return 0; - if (sizeof(old->countries) != sizeof(new->countries)) - return 0; - if (memcmp(old->countries,new->countries,sizeof(new->countries))) - return 0; - return 1; -#endif } /** Free all storage held in <b>routerset</b>. */ void routerset_free(routerset_t *routerset) { + if (!routerset) + return; + SMARTLIST_FOREACH(routerset->list, char *, cp, tor_free(cp)); smartlist_free(routerset->list); SMARTLIST_FOREACH(routerset->policies, addr_policy_t *, p, @@ -5305,8 +5630,7 @@ routerset_free(routerset_t *routerset) strmap_free(routerset->names, NULL); digestmap_free(routerset->digests, NULL); - if (routerset->countries) - bitarray_free(routerset->countries); + bitarray_free(routerset->countries); tor_free(routerset); } diff --git a/src/or/routerlist.h b/src/or/routerlist.h new file mode 100644 index 0000000000..574bce7ffc --- /dev/null +++ b/src/or/routerlist.h @@ -0,0 +1,196 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file routerlist.h + * \brief Header file for routerlist.c. + **/ + +#ifndef _TOR_ROUTERLIST_H +#define _TOR_ROUTERLIST_H + +int get_n_authorities(authority_type_t type); +int trusted_dirs_reload_certs(void); +int trusted_dirs_load_certs_from_string(const char *contents, int from_store, + int flush); +void trusted_dirs_flush_certs_to_disk(void); +authority_cert_t *authority_cert_get_newest_by_id(const char *id_digest); +authority_cert_t *authority_cert_get_by_sk_digest(const char *sk_digest); +authority_cert_t *authority_cert_get_by_digests(const char *id_digest, + const char *sk_digest); +void authority_cert_get_all(smartlist_t *certs_out); +void authority_cert_dl_failed(const char *id_digest, int status); +void authority_certs_fetch_missing(networkstatus_t *status, time_t now); +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); +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); +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, + uint16_t port); +int router_is_unreliable(routerinfo_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); + +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); + +routerinfo_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, + int warn_if_unnamed); +int router_digest_version_as_new_as(const char *digest, const char *cutoff); +int router_digest_is_trusted_dir_type(const char *digest, + authority_type_t type); +#define router_digest_is_trusted_dir(d) \ + router_digest_is_trusted_dir_type((d), NO_AUTHORITY) + +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); +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); +routerlist_t *router_get_routerlist(void); +void routerinfo_free(routerinfo_t *router); +void extrainfo_free(extrainfo_t *extrainfo); +void routerlist_free(routerlist_t *rl); +void dump_routerlist_mem_usage(int severity); +void routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old, + time_t now); +void routerlist_free_all(void); +void routerlist_reset_warnings(void); +void router_set_status(const char *digest, int up); + +static int WRA_WAS_ADDED(was_router_added_t s); +static int WRA_WAS_OUTDATED(was_router_added_t s); +static int WRA_WAS_REJECTED(was_router_added_t s); +/** Return true iff the descriptor was added. It might still be necessary to + * check whether the descriptor generator should be notified. + */ +static INLINE int +WRA_WAS_ADDED(was_router_added_t s) { + return s == ROUTER_ADDED_SUCCESSFULLY || s == ROUTER_ADDED_NOTIFY_GENERATOR; +} +/** Return true iff the descriptor was not added because it was either: + * - not in the consensus + * - neither in the consensus nor in any networkstatus document + * - it was outdated. + */ +static INLINE int WRA_WAS_OUTDATED(was_router_added_t s) +{ + return (s == ROUTER_WAS_NOT_NEW || + s == ROUTER_NOT_IN_CONSENSUS || + s == ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS); +} +static INLINE int WRA_WAS_REJECTED(was_router_added_t s) +{ + return (s == ROUTER_AUTHDIR_REJECTS); +} +was_router_added_t router_add_to_routerlist(routerinfo_t *router, + const char **msg, + int from_cache, + int from_fetch); +was_router_added_t router_add_extrainfo_to_routerlist( + extrainfo_t *ei, const char **msg, + int from_cache, int from_fetch); +void routerlist_descriptors_added(smartlist_t *sl, int from_cache); +void routerlist_remove_old_routers(void); +int router_load_single_router(const char *s, uint8_t purpose, int cache, + const char **msg); +int router_load_routers_from_string(const char *s, const char *eos, + saved_location_t saved_location, + smartlist_t *requested_fingerprints, + int descriptor_digests, + const char *prepend_annotations); +void router_load_extrainfo_from_string(const char *s, const char *eos, + saved_location_t saved_location, + smartlist_t *requested_fingerprints, + 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); +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); +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_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, + signed_descriptor_t *sd, + const char **msg); + +void routerlist_assert_ok(routerlist_t *rl); +const char *esc_router_info(routerinfo_t *router); +void routers_sort_by_identity(smartlist_t *routers); + +routerset_t *routerset_new(void); +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_contains_router(const routerset_t *set, routerinfo_t *ri); +int routerset_contains_routerstatus(const routerset_t *set, + routerstatus_t *rs); +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, + int running_only); +void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source, + const routerset_t *include, + const routerset_t *exclude, int running_only); +void routerset_subtract_routers(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, + const char *id); +int hid_serv_acting_as_directory(void); +int hid_serv_responsible_for_desc_id(const char *id); + +#endif + diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 3d8ca14317..1ce105abab 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -10,7 +10,20 @@ **/ #include "or.h" +#include "config.h" +#include "dirserv.h" +#include "dirvote.h" +#include "policies.h" +#include "rendcommon.h" +#include "router.h" +#include "routerlist.h" #include "memarea.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "rephist.h" +#include "routerparse.h" +#undef log +#include <math.h> /****************************************************************************/ @@ -55,6 +68,7 @@ typedef enum { K_S, K_V, K_W, + K_M, K_EVENTDNS, K_EXTRA_INFO, K_EXTRA_INFO_DIGEST, @@ -62,6 +76,31 @@ typedef enum { K_HIDDEN_SERVICE_DIR, K_ALLOW_SINGLE_HOP_EXITS, + K_DIRREQ_END, + K_DIRREQ_V2_IPS, + K_DIRREQ_V3_IPS, + K_DIRREQ_V2_REQS, + K_DIRREQ_V3_REQS, + K_DIRREQ_V2_SHARE, + K_DIRREQ_V3_SHARE, + K_DIRREQ_V2_RESP, + K_DIRREQ_V3_RESP, + K_DIRREQ_V2_DIR, + K_DIRREQ_V3_DIR, + K_DIRREQ_V2_TUN, + K_DIRREQ_V3_TUN, + K_ENTRY_END, + K_ENTRY_IPS, + K_CELL_END, + K_CELL_PROCESSED, + K_CELL_QUEUED, + K_CELL_TIME, + K_CELL_CIRCS, + K_EXIT_END, + K_EXIT_WRITTEN, + K_EXIT_READ, + K_EXIT_OPENED, + K_DIR_KEY_CERTIFICATE_VERSION, K_DIR_IDENTITY_KEY, K_DIR_KEY_PUBLISHED, @@ -78,13 +117,18 @@ typedef enum { K_KNOWN_FLAGS, K_PARAMS, + K_BW_WEIGHTS, K_VOTE_DIGEST, K_CONSENSUS_DIGEST, + K_ADDITIONAL_DIGEST, + K_ADDITIONAL_SIGNATURE, K_CONSENSUS_METHODS, K_CONSENSUS_METHOD, K_LEGACY_DIR_KEY, + K_DIRECTORY_FOOTER, A_PURPOSE, + A_LAST_LISTED, _A_UNKNOWN, R_RENDEZVOUS_SERVICE_DESCRIPTOR, @@ -122,7 +166,7 @@ typedef enum { * type. * * This structure is only allocated in memareas; do not allocate it on - * the heap, or token_free() won't work. + * the heap, or token_clear() won't work. */ typedef struct directory_token_t { directory_keyword tp; /**< Type of the token. */ @@ -258,6 +302,31 @@ static token_rule_t extrainfo_token_table[] = { T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ), T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ), T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ), + T01("dirreq-stats-end", K_DIRREQ_END, ARGS, NO_OBJ ), + T01("dirreq-v2-ips", K_DIRREQ_V2_IPS, ARGS, NO_OBJ ), + T01("dirreq-v3-ips", K_DIRREQ_V3_IPS, ARGS, NO_OBJ ), + T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS, ARGS, NO_OBJ ), + T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS, ARGS, NO_OBJ ), + T01("dirreq-v2-share", K_DIRREQ_V2_SHARE, ARGS, NO_OBJ ), + T01("dirreq-v3-share", K_DIRREQ_V3_SHARE, ARGS, NO_OBJ ), + T01("dirreq-v2-resp", K_DIRREQ_V2_RESP, ARGS, NO_OBJ ), + T01("dirreq-v3-resp", K_DIRREQ_V3_RESP, ARGS, NO_OBJ ), + T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR, ARGS, NO_OBJ ), + T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR, ARGS, NO_OBJ ), + T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN, ARGS, NO_OBJ ), + T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN, ARGS, NO_OBJ ), + T01("entry-stats-end", K_ENTRY_END, ARGS, NO_OBJ ), + T01("entry-ips", K_ENTRY_IPS, ARGS, NO_OBJ ), + T01("cell-stats-end", K_CELL_END, ARGS, NO_OBJ ), + T01("cell-processed-cells", K_CELL_PROCESSED, ARGS, NO_OBJ ), + T01("cell-queued-cells", K_CELL_QUEUED, ARGS, NO_OBJ ), + T01("cell-time-in-queue", K_CELL_TIME, ARGS, NO_OBJ ), + T01("cell-circuits-per-decile", K_CELL_CIRCS, ARGS, NO_OBJ ), + T01("exit-stats-end", K_EXIT_END, ARGS, NO_OBJ ), + T01("exit-kibibytes-written", K_EXIT_WRITTEN, ARGS, NO_OBJ ), + T01("exit-kibibytes-read", K_EXIT_READ, ARGS, NO_OBJ ), + T01("exit-streams-opened", K_EXIT_OPENED, ARGS, NO_OBJ ), + T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ), END_OF_TABLE @@ -267,10 +336,11 @@ static token_rule_t extrainfo_token_table[] = { * documents. */ static token_rule_t rtrstatus_token_table[] = { T01("p", K_P, CONCAT_ARGS, NO_OBJ ), - T1( "r", K_R, GE(8), NO_OBJ ), + T1( "r", K_R, GE(7), NO_OBJ ), T1( "s", K_S, ARGS, NO_OBJ ), T01("v", K_V, CONCAT_ARGS, NO_OBJ ), T01("w", K_W, ARGS, NO_OBJ ), + T0N("m", K_M, CONCAT_ARGS, NO_OBJ ), T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ), END_OF_TABLE }; @@ -375,7 +445,7 @@ static token_rule_t client_keys_token_table[] = { /** List of tokens allowed in V3 networkstatus votes. */ static token_rule_t networkstatus_token_table[] = { - T1("network-status-version", K_NETWORK_STATUS_VERSION, + T1_START("network-status-version", K_NETWORK_STATUS_VERSION, GE(1), NO_OBJ ), T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ), T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ), @@ -403,7 +473,7 @@ static token_rule_t networkstatus_token_table[] = { /** List of tokens allowed in V3 networkstatus consensuses. */ static token_rule_t networkstatus_consensus_token_table[] = { - T1("network-status-version", K_NETWORK_STATUS_VERSION, + T1_START("network-status-version", K_NETWORK_STATUS_VERSION, GE(1), NO_OBJ ), T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ), T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ), @@ -430,17 +500,29 @@ static token_rule_t networkstatus_consensus_token_table[] = { /** List of tokens allowable in the footer of v1/v2 directory/networkstatus * footers. */ static token_rule_t networkstatus_vote_footer_token_table[] = { - T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ), + T01("directory-footer", K_DIRECTORY_FOOTER, NO_ARGS, NO_OBJ ), + T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ), + T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ), END_OF_TABLE }; /** List of tokens allowable in detached networkstatus signature documents. */ static token_rule_t networkstatus_detached_signature_token_table[] = { T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ), + T("additional-digest", K_ADDITIONAL_DIGEST,GE(3), NO_OBJ ), T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ), T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ), T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ), - T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ), + T("additional-signature", K_ADDITIONAL_SIGNATURE, GE(4), NEED_OBJ ), + T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ), + END_OF_TABLE +}; + +static token_rule_t microdesc_token_table[] = { + T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024), + T01("family", K_FAMILY, ARGS, NO_OBJ ), + T01("p", K_P, CONCAT_ARGS, NO_OBJ ), + A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ), END_OF_TABLE }; @@ -453,9 +535,13 @@ static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok); static int router_get_hash_impl(const char *s, size_t s_len, char *digest, const char *start_str, const char *end_str, - char end_char); - -static void token_free(directory_token_t *tok); + char end_char, + digest_algorithm_t alg); +static int router_get_hashes_impl(const char *s, size_t s_len, + digests_t *digests, + const char *start_str, const char *end_str, + char end_char); +static void token_clear(directory_token_t *tok); static smartlist_t *find_all_exitpolicy(smartlist_t *s); static directory_token_t *_find_by_keyword(smartlist_t *s, directory_keyword keyword, @@ -479,6 +565,7 @@ static directory_token_t *get_next_token(memarea_t *area, #define CST_CHECK_AUTHORITY (1<<0) #define CST_NO_CHECK_OBJTYPE (1<<1) static int check_signature_token(const char *digest, + ssize_t digest_len, directory_token_t *tok, crypto_pk_env_t *pkey, int flags, @@ -499,6 +586,34 @@ static int tor_version_same_series(tor_version_t *a, tor_version_t *b); #define DUMP_AREA(a,name) STMT_NIL #endif +/** Last time we dumped a descriptor to disk. */ +static time_t last_desc_dumped = 0; + +/** For debugging purposes, dump unparseable descriptor *<b>desc</b> of + * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more + * than one descriptor to disk per minute. If there is already such a + * file in the data directory, overwrite it. */ +static void +dump_desc(const char *desc, const char *type) +{ + time_t now = time(NULL); + tor_assert(desc); + tor_assert(type); + if (!last_desc_dumped || last_desc_dumped + 60 < now) { + char *debugfile = get_datadir_fname("unparseable-desc"); + size_t filelen = 50 + strlen(type) + strlen(desc); + char *content = tor_malloc_zero(filelen); + tor_snprintf(content, filelen, "Unable to parse descriptor of type " + "%s:\n%s", type, desc); + write_str_to_file(debugfile, content, 0); + log_info(LD_DIR, "Unable to parse descriptor of type %s. See file " + "unparseable-desc in data directory for details.", type); + tor_free(content); + tor_free(debugfile); + last_desc_dumped = now; + } +} + /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in * <b>s</b>. Return 0 on success, -1 on failure. */ @@ -506,7 +621,8 @@ int router_get_dir_hash(const char *s, char *digest) { return router_get_hash_impl(s, strlen(s), digest, - "signed-directory","\ndirectory-signature",'\n'); + "signed-directory","\ndirectory-signature",'\n', + DIGEST_SHA1); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in @@ -516,7 +632,8 @@ int router_get_router_hash(const char *s, size_t s_len, char *digest) { return router_get_hash_impl(s, s_len, digest, - "router ","\nrouter-signature", '\n'); + "router ","\nrouter-signature", '\n', + DIGEST_SHA1); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers @@ -526,7 +643,8 @@ int router_get_runningrouters_hash(const char *s, char *digest) { return router_get_hash_impl(s, strlen(s), digest, - "network-status","\ndirectory-signature", '\n'); + "network-status","\ndirectory-signature", '\n', + DIGEST_SHA1); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status @@ -536,18 +654,31 @@ router_get_networkstatus_v2_hash(const char *s, char *digest) { return router_get_hash_impl(s, strlen(s), digest, "network-status-version","\ndirectory-signature", - '\n'); + '\n', + DIGEST_SHA1); +} + +/** Set <b>digests</b> to all the digests of the consensus document in + * <b>s</b> */ +int +router_get_networkstatus_v3_hashes(const char *s, digests_t *digests) +{ + return router_get_hashes_impl(s,strlen(s),digests, + "network-status-version", + "\ndirectory-signature", + ' '); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status * string in <b>s</b>. Return 0 on success, -1 on failure. */ int -router_get_networkstatus_v3_hash(const char *s, char *digest) +router_get_networkstatus_v3_hash(const char *s, char *digest, + digest_algorithm_t alg) { return router_get_hash_impl(s, strlen(s), digest, "network-status-version", "\ndirectory-signature", - ' '); + ' ', alg); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo @@ -556,7 +687,7 @@ int router_get_extrainfo_hash(const char *s, char *digest) { return router_get_hash_impl(s, strlen(s), digest, "extra-info", - "\nrouter-signature",'\n'); + "\nrouter-signature",'\n', DIGEST_SHA1); } /** Helper: used to generate signatures for routers, directories and @@ -568,14 +699,15 @@ router_get_extrainfo_hash(const char *s, char *digest) */ int router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, - crypto_pk_env_t *private_key) + size_t digest_len, crypto_pk_env_t *private_key) { char *signature; size_t i; + int siglen; signature = tor_malloc(crypto_pk_keysize(private_key)); - if (crypto_pk_private_sign(private_key, signature, digest, DIGEST_LEN) < 0) { - + siglen = crypto_pk_private_sign(private_key, signature, digest, digest_len); + if (siglen < 0) { log_warn(LD_BUG,"Couldn't sign digest."); goto err; } @@ -583,7 +715,7 @@ router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, goto truncated; i = strlen(buf); - if (base64_encode(buf+i, buf_len-i, signature, 128) < 0) { + if (base64_encode(buf+i, buf_len-i, signature, siglen) < 0) { log_warn(LD_BUG,"couldn't base64-encode signature"); goto err; } @@ -690,7 +822,7 @@ router_parse_directory(const char *str) char digest[DIGEST_LEN]; time_t published_on; int r; - const char *end, *cp; + const char *end, *cp, *str_dup = str; smartlist_t *tokens = NULL; crypto_pk_env_t *declared_key = NULL; memarea_t *area = memarea_new(); @@ -726,11 +858,11 @@ router_parse_directory(const char *str) } declared_key = find_dir_signing_key(str, str+strlen(str)); note_crypto_pk_op(VERIFY_DIR); - if (check_signature_token(digest, tok, declared_key, + if (check_signature_token(digest, DIGEST_LEN, tok, declared_key, CST_CHECK_AUTHORITY, "directory")<0) goto err; - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); @@ -763,11 +895,12 @@ router_parse_directory(const char *str) r = 0; goto done; err: + dump_desc(str_dup, "v1 directory"); r = -1; done: if (declared_key) crypto_free_pk_env(declared_key); if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (area) { @@ -789,7 +922,7 @@ router_parse_runningrouters(const char *str) int r = -1; crypto_pk_env_t *declared_key = NULL; smartlist_t *tokens = NULL; - const char *eos = str + strlen(str); + const char *eos = str + strlen(str), *str_dup = str; memarea_t *area = NULL; if (router_get_runningrouters_hash(str, digest)) { @@ -818,7 +951,7 @@ router_parse_runningrouters(const char *str) } declared_key = find_dir_signing_key(str, eos); note_crypto_pk_op(VERIFY_DIR); - if (check_signature_token(digest, tok, declared_key, + if (check_signature_token(digest, DIGEST_LEN, tok, declared_key, CST_CHECK_AUTHORITY, "running-routers") < 0) goto err; @@ -830,9 +963,10 @@ router_parse_runningrouters(const char *str) r = 0; err: + dump_desc(str_dup, "v1 running-routers"); if (declared_key) crypto_free_pk_env(declared_key); if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (area) { @@ -882,7 +1016,7 @@ find_dir_signing_key(const char *str, const char *eos) } done: - if (tok) token_free(tok); + if (tok) token_clear(tok); if (area) { DUMP_AREA(area, "dir-signing-key token"); memarea_drop_all(area); @@ -918,6 +1052,7 @@ dir_signing_key_is_trusted(crypto_pk_env_t *key) */ static int check_signature_token(const char *digest, + ssize_t digest_len, directory_token_t *tok, crypto_pk_env_t *pkey, int flags, @@ -948,14 +1083,14 @@ check_signature_token(const char *digest, signed_digest = tor_malloc(tok->object_size); if (crypto_pk_public_checksig(pkey, signed_digest, tok->object_body, tok->object_size) - != DIGEST_LEN) { + < digest_len) { log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype); tor_free(signed_digest); return -1; } // log_debug(LD_DIR,"Signed %s hash starts %s", doctype, // hex_str(signed_digest,4)); - if (memcmp(digest, signed_digest, DIGEST_LEN)) { + if (memcmp(digest, signed_digest, digest_len)) { log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype); tor_free(signed_digest); return -1; @@ -1141,7 +1276,7 @@ router_parse_entry_from_string(const char *s, const char *end, smartlist_t *tokens = NULL, *exit_policy_tokens = NULL; directory_token_t *tok; struct in_addr in; - const char *start_of_annotations, *cp; + const char *start_of_annotations, *cp, *s_dup = s; size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0; int ok = 1; memarea_t *area = NULL; @@ -1419,7 +1554,7 @@ router_parse_entry_from_string(const char *s, const char *end, verified_digests = digestmap_new(); digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1); #endif - if (check_signature_token(digest, tok, router->identity_pkey, 0, + if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0, "router descriptor") < 0) goto err; @@ -1437,16 +1572,15 @@ router_parse_entry_from_string(const char *s, const char *end, goto done; err: + dump_desc(s_dup, "router descriptor"); routerinfo_free(router); router = NULL; done: if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } - if (exit_policy_tokens) { - smartlist_free(exit_policy_tokens); - } + smartlist_free(exit_policy_tokens); if (area) { DUMP_AREA(area, "routerinfo"); memarea_drop_all(area); @@ -1471,6 +1605,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, crypto_pk_env_t *key = NULL; routerinfo_t *router = NULL; memarea_t *area = NULL; + const char *s_dup = s; if (!end) { end = s + strlen(s); @@ -1545,7 +1680,8 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, if (key) { note_crypto_pk_op(VERIFY_RTR); - if (check_signature_token(digest, tok, key, 0, "extra-info") < 0) + if (check_signature_token(digest, DIGEST_LEN, tok, key, 0, + "extra-info") < 0) goto err; if (router) @@ -1559,12 +1695,12 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, goto done; err: - if (extrainfo) - extrainfo_free(extrainfo); + dump_desc(s_dup, "extra-info descriptor"); + extrainfo_free(extrainfo); extrainfo = NULL; done: if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (area) { @@ -1588,6 +1724,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) size_t len; int found; memarea_t *area = NULL; + const char *s_dup = s; s = eat_whitespace(s); eos = strstr(s, "\ndir-key-certification"); @@ -1612,7 +1749,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) goto err; } if (router_get_hash_impl(s, strlen(s), digest, "dir-key-certificate-version", - "\ndir-key-certification", '\n') < 0) + "\ndir-key-certification", '\n', DIGEST_SHA1) < 0) goto err; tok = smartlist_get(tokens, 0); if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) { @@ -1705,7 +1842,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) } } if (!found) { - if (check_signature_token(digest, tok, cert->identity_key, 0, + if (check_signature_token(digest, DIGEST_LEN, tok, cert->identity_key, 0, "key certificate")) { goto err; } @@ -1714,6 +1851,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) /* XXXX Once all authorities generate cross-certified certificates, * make this field mandatory. */ if (check_signature_token(cert->cache_info.identity_digest, + DIGEST_LEN, tok, cert->signing_key, CST_NO_CHECK_OBJTYPE, @@ -1733,7 +1871,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) if (end_of_string) { *end_of_string = eat_whitespace(eos); } - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); if (area) { DUMP_AREA(area, "authority cert"); @@ -1741,8 +1879,9 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) } return cert; err: + dump_desc(s_dup, "authority cert"); authority_cert_free(cert); - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); if (area) { DUMP_AREA(area, "authority cert"); @@ -1753,23 +1892,28 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) /** Helper: given a string <b>s</b>, return the start of the next router-status * object (starting with "r " at the start of a line). If none is found, - * return the start of the next directory signature. If none is found, return - * the end of the string. */ + * return the start of the directory footer, or the next directory signature. + * If none is found, return the end of the string. */ static INLINE const char * find_start_of_next_routerstatus(const char *s) { - const char *eos = strstr(s, "\nr "); - if (eos) { - const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-signature"); - if (eos2 && eos2 < eos) - return eos2; - else - return eos+1; - } else { - if ((eos = strstr(s, "\ndirectory-signature"))) - return eos+1; - return s + strlen(s); - } + const char *eos, *footer, *sig; + if ((eos = strstr(s, "\nr "))) + ++eos; + else + eos = s + strlen(s); + + footer = tor_memstr(s, eos-s, "\ndirectory-footer"); + sig = tor_memstr(s, eos-s, "\ndirectory-signature"); + + if (footer && sig) + return MIN(footer, sig) + 1; + else if (footer) + return footer+1; + else if (sig) + return sig+1; + else + return eos; } /** Given a string at *<b>s</b>, containing a routerstatus object, and an @@ -1783,22 +1927,29 @@ find_start_of_next_routerstatus(const char *s) * If <b>consensus_method</b> is nonzero, this routerstatus is part of a * consensus, and we should parse it according to the method used to * make that consensus. + * + * Parse according to the syntax used by the consensus flavor <b>flav</b>. **/ static routerstatus_t * routerstatus_parse_entry_from_string(memarea_t *area, const char **s, smartlist_t *tokens, networkstatus_t *vote, vote_routerstatus_t *vote_rs, - int consensus_method) + int consensus_method, + consensus_flavor_t flav) { - const char *eos; + const char *eos, *s_dup = *s; routerstatus_t *rs = NULL; directory_token_t *tok; char timebuf[ISO_TIME_LEN+1]; struct in_addr in; + int offset = 0; tor_assert(tokens); tor_assert(bool_eq(vote, vote_rs)); + if (!consensus_method) + flav = FLAV_NS; + eos = find_start_of_next_routerstatus(*s); if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) { @@ -1810,7 +1961,15 @@ routerstatus_parse_entry_from_string(memarea_t *area, goto err; } tok = find_by_keyword(tokens, K_R); - tor_assert(tok->n_args >= 8); + tor_assert(tok->n_args >= 7); + if (flav == FLAV_NS) { + if (tok->n_args < 8) { + log_warn(LD_DIR, "Too few arguments to r"); + goto err; + } + } else { + offset = -1; + } if (vote_rs) { rs = &vote_rs->status; } else { @@ -1831,29 +1990,34 @@ routerstatus_parse_entry_from_string(memarea_t *area, goto err; } - if (digest_from_base64(rs->descriptor_digest, tok->args[2])) { - log_warn(LD_DIR, "Error decoding descriptor digest %s", - escaped(tok->args[2])); - goto err; + if (flav == FLAV_NS) { + if (digest_from_base64(rs->descriptor_digest, tok->args[2])) { + log_warn(LD_DIR, "Error decoding descriptor digest %s", + escaped(tok->args[2])); + goto err; + } } if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s", - tok->args[3], tok->args[4]) < 0 || + tok->args[3+offset], tok->args[4+offset]) < 0 || parse_iso_time(timebuf, &rs->published_on)<0) { - log_warn(LD_DIR, "Error parsing time '%s %s'", - tok->args[3], tok->args[4]); + log_warn(LD_DIR, "Error parsing time '%s %s' [%d %d]", + tok->args[3+offset], tok->args[4+offset], + offset, (int)flav); goto err; } - if (tor_inet_aton(tok->args[5], &in) == 0) { + if (tor_inet_aton(tok->args[5+offset], &in) == 0) { log_warn(LD_DIR, "Error parsing router address in network-status %s", - escaped(tok->args[5])); + escaped(tok->args[5+offset])); goto err; } rs->addr = ntohl(in.s_addr); - rs->or_port =(uint16_t) tor_parse_long(tok->args[6],10,0,65535,NULL,NULL); - rs->dir_port = (uint16_t) tor_parse_long(tok->args[7],10,0,65535,NULL,NULL); + rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset], + 10,0,65535,NULL,NULL); + rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset], + 10,0,65535,NULL,NULL); tok = find_opt_by_keyword(tokens, K_S); if (tok && vote) { @@ -1939,6 +2103,17 @@ routerstatus_parse_entry_from_string(memarea_t *area, goto err; } rs->has_bandwidth = 1; + } else if (!strcmpstart(tok->args[i], "Measured=")) { + int ok; + rs->measured_bw = + (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, + 10, 0, UINT32_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_DIR, "Invalid Measured Bandwidth %s", + escaped(tok->args[i])); + goto err; + } + rs->has_measured_bw = 1; } } } @@ -1960,16 +2135,29 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->has_exitsummary = 1; } + if (vote_rs) { + SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, t) { + if (t->tp == K_M && t->n_args) { + vote_microdesc_hash_t *line = + tor_malloc(sizeof(vote_microdesc_hash_t)); + line->next = vote_rs->microdesc; + line->microdesc_hash_line = tor_strdup(t->args[0]); + vote_rs->microdesc = line; + } + } SMARTLIST_FOREACH_END(t); + } + if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME)) rs->is_named = 0; goto done; err: + dump_desc(s_dup, "routerstatus entry"); if (rs && !vote_rs) routerstatus_free(rs); rs = NULL; done: - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); if (area) { DUMP_AREA(area, "routerstatus entry"); @@ -1981,8 +2169,8 @@ routerstatus_parse_entry_from_string(memarea_t *area, } /** Helper to sort a smartlist of pointers to routerstatus_t */ -static int -_compare_routerstatus_entries(const void **_a, const void **_b) +int +compare_routerstatus_entries(const void **_a, const void **_b) { const routerstatus_t *a = *_a, *b = *_b; return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN); @@ -2006,7 +2194,7 @@ _free_duplicate_routerstatus_entry(void *e) networkstatus_v2_t * networkstatus_v2_parse_from_string(const char *s) { - const char *eos; + const char *eos, *s_dup = s; smartlist_t *tokens = smartlist_create(); smartlist_t *footer_tokens = smartlist_create(); networkstatus_v2_t *ns = NULL; @@ -2120,17 +2308,17 @@ networkstatus_v2_parse_from_string(const char *s) ns->entries = smartlist_create(); s = eos; - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); while (!strcmpstart(s, "r ")) { routerstatus_t *rs; if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens, - NULL, NULL, 0))) + NULL, NULL, 0, 0))) smartlist_add(ns->entries, rs); } - smartlist_sort(ns->entries, _compare_routerstatus_entries); - smartlist_uniq(ns->entries, _compare_routerstatus_entries, + smartlist_sort(ns->entries, compare_routerstatus_entries); + smartlist_uniq(ns->entries, compare_routerstatus_entries, _free_duplicate_routerstatus_entry); if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) { @@ -2149,19 +2337,19 @@ networkstatus_v2_parse_from_string(const char *s) } note_crypto_pk_op(VERIFY_DIR); - if (check_signature_token(ns_digest, tok, ns->signing_key, 0, + if (check_signature_token(ns_digest, DIGEST_LEN, tok, ns->signing_key, 0, "network-status") < 0) goto err; goto done; err: - if (ns) - networkstatus_v2_free(ns); + dump_desc(s_dup, "v2 networkstatus"); + networkstatus_v2_free(ns); ns = NULL; done: - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); - SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t)); smartlist_free(footer_tokens); if (area) { DUMP_AREA(area, "v2 networkstatus"); @@ -2170,6 +2358,394 @@ networkstatus_v2_parse_from_string(const char *s) return ns; } +/** Verify the bandwidth weights of a network status document */ +int +networkstatus_verify_bw_weights(networkstatus_t *ns) +{ + int64_t weight_scale; + int64_t G=0, M=0, E=0, D=0, T=0; + double Wgg, Wgm, Wgd, Wmg, Wmm, Wme, Wmd, Weg, Wem, Wee, Wed; + double Gtotal=0, Mtotal=0, Etotal=0; + const char *casename = NULL; + int valid = 1; + + weight_scale = networkstatus_get_param(ns, "bwweightscale", BW_WEIGHT_SCALE); + Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1); + Wgm = networkstatus_get_bw_weight(ns, "Wgm", -1); + Wgd = networkstatus_get_bw_weight(ns, "Wgd", -1); + Wmg = networkstatus_get_bw_weight(ns, "Wmg", -1); + Wmm = networkstatus_get_bw_weight(ns, "Wmm", -1); + Wme = networkstatus_get_bw_weight(ns, "Wme", -1); + Wmd = networkstatus_get_bw_weight(ns, "Wmd", -1); + Weg = networkstatus_get_bw_weight(ns, "Weg", -1); + Wem = networkstatus_get_bw_weight(ns, "Wem", -1); + Wee = networkstatus_get_bw_weight(ns, "Wee", -1); + Wed = networkstatus_get_bw_weight(ns, "Wed", -1); + + if (Wgg<0 || Wgm<0 || Wgd<0 || Wmg<0 || Wmm<0 || Wme<0 || Wmd<0 || Weg<0 + || Wem<0 || Wee<0 || Wed<0) { + log_warn(LD_BUG, "No bandwidth weights produced in consensus!"); + return 0; + } + + // First, sanity check basic summing properties that hold for all cases + // We use > 1 as the check for these because they are computed as integers. + // Sometimes there are rounding errors. + if (fabs(Wmm - weight_scale) > 1) { + log_warn(LD_BUG, "Wmm=%lf != "I64_FORMAT, + Wmm, I64_PRINTF_ARG(weight_scale)); + valid = 0; + } + + if (fabs(Wem - Wee) > 1) { + log_warn(LD_BUG, "Wem=%lf != Wee=%lf", Wem, Wee); + valid = 0; + } + + if (fabs(Wgm - Wgg) > 1) { + log_warn(LD_BUG, "Wgm=%lf != Wgg=%lf", Wgm, Wgg); + valid = 0; + } + + if (fabs(Weg - Wed) > 1) { + log_warn(LD_BUG, "Wed=%lf != Weg=%lf", Wed, Weg); + valid = 0; + } + + if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) { + log_warn(LD_BUG, "Wgg=%lf != "I64_FORMAT" - Wmg=%lf", Wgg, + I64_PRINTF_ARG(weight_scale), Wmg); + valid = 0; + } + + if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) { + log_warn(LD_BUG, "Wee=%lf != "I64_FORMAT" - Wme=%lf", Wee, + I64_PRINTF_ARG(weight_scale), Wme); + valid = 0; + } + + if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) { + log_warn(LD_BUG, "Wgd=%lf + Wmd=%lf + Wed=%lf != "I64_FORMAT, + Wgd, Wmd, Wed, I64_PRINTF_ARG(weight_scale)); + valid = 0; + } + + Wgg /= weight_scale; + Wgm /= weight_scale; + Wgd /= weight_scale; + + Wmg /= weight_scale; + Wmm /= weight_scale; + Wme /= weight_scale; + Wmd /= weight_scale; + + Weg /= weight_scale; + Wem /= weight_scale; + Wee /= weight_scale; + Wed /= weight_scale; + + // Then, gather G, M, E, D, T to determine case + SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { + if (rs->has_bandwidth) { + T += rs->bandwidth; + if (rs->is_exit && rs->is_possible_guard) { + D += rs->bandwidth; + Gtotal += Wgd*rs->bandwidth; + Mtotal += Wmd*rs->bandwidth; + Etotal += Wed*rs->bandwidth; + } else if (rs->is_exit) { + E += rs->bandwidth; + Mtotal += Wme*rs->bandwidth; + Etotal += Wee*rs->bandwidth; + } else if (rs->is_possible_guard) { + G += rs->bandwidth; + Gtotal += Wgg*rs->bandwidth; + Mtotal += Wmg*rs->bandwidth; + } else { + M += rs->bandwidth; + Mtotal += Wmm*rs->bandwidth; + } + } else { + log_warn(LD_BUG, "Missing consensus bandwidth for router %s", + rs->nickname); + } + } SMARTLIST_FOREACH_END(rs); + + // Finally, check equality conditions depending upon case 1, 2 or 3 + // Full equality cases: 1, 3b + // Partial equality cases: 2b (E=G), 3a (M=E) + // Fully unknown: 2a + if (3*E >= T && 3*G >= T) { + // Case 1: Neither are scarce + casename = "Case 1"; + if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Etotal, Mtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Etotal, Gtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Mtotal, Gtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + } else if (3*E < T && 3*G < T) { + int64_t R = MIN(E, G); + int64_t S = MAX(E, G); + /* + * Case 2: Both Guards and Exits are scarce + * Balance D between E and G, depending upon + * D capacity and scarcity. Devote no extra + * bandwidth to middle nodes. + */ + if (R+D < S) { // Subcase a + double Rtotal, Stotal; + if (E < G) { + Rtotal = Etotal; + Stotal = Gtotal; + } else { + Rtotal = Gtotal; + Stotal = Etotal; + } + casename = "Case 2a"; + // Rtotal < Stotal + if (Rtotal > Stotal) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Rtotal %lf > Stotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Rtotal, Stotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + // Rtotal < T/3 + if (3*Rtotal > T) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: 3*Rtotal %lf > T " + I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT + " D="I64_FORMAT" T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Rtotal*3, I64_PRINTF_ARG(T), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + // Stotal < T/3 + if (3*Stotal > T) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: 3*Stotal %lf > T " + I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT + " D="I64_FORMAT" T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Stotal*3, I64_PRINTF_ARG(T), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + // Mtotal > T/3 + if (3*Mtotal < T) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: 3*Mtotal %lf < T " + I64_FORMAT". " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Mtotal*3, I64_PRINTF_ARG(T), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + } else { // Subcase b: R+D > S + casename = "Case 2b"; + + /* Check the rare-M redirect case. */ + if (D != 0 && 3*M < T) { + casename = "Case 2b (balanced)"; + if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Etotal, Mtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Etotal, Gtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Mtotal, Gtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + } else { + if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Etotal, Gtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + } + } + } else { // if (E < T/3 || G < T/3) { + int64_t S = MIN(E, G); + int64_t NS = MAX(E, G); + if (3*(S+D) < T) { // Subcase a: + double Stotal; + double NStotal; + if (G < E) { + casename = "Case 3a (G scarce)"; + Stotal = Gtotal; + NStotal = Etotal; + } else { // if (G >= E) { + casename = "Case 3a (E scarce)"; + NStotal = Gtotal; + Stotal = Etotal; + } + // Stotal < T/3 + if (3*Stotal > T) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: 3*Stotal %lf > T " + I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT + " D="I64_FORMAT" T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Stotal*3, I64_PRINTF_ARG(T), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + if (NS >= M) { + if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: NStotal %lf != Mtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, NStotal, Mtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + } else { + // if NS < M, NStotal > T/3 because only one of G or E is scarce + if (3*NStotal < T) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: 3*NStotal %lf < T " + I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT + " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, NStotal*3, I64_PRINTF_ARG(T), + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + } + } else { // Subcase b: S+D >= T/3 + casename = "Case 3b"; + if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Etotal, Mtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Etotal, Gtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) { + log_warn(LD_DIR, + "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. " + "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT + " T="I64_FORMAT". " + "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf", + casename, Mtotal, Gtotal, + I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E), + I64_PRINTF_ARG(D), I64_PRINTF_ARG(T), + Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed); + valid = 0; + } + } + } + + if (valid) + log_notice(LD_DIR, "Bandwidth-weight %s is verified and valid.", + casename); + + return valid; +} /** Parse a v3 networkstatus vote, opinion, or consensus (depending on * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */ @@ -2181,19 +2757,21 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, smartlist_t *rs_tokens = NULL, *footer_tokens = NULL; networkstatus_voter_info_t *voter = NULL; networkstatus_t *ns = NULL; - char ns_digest[DIGEST_LEN]; - const char *cert, *end_of_header, *end_of_footer; + digests_t ns_digests; + const char *cert, *end_of_header, *end_of_footer, *s_dup = s; directory_token_t *tok; int ok; struct in_addr in; int i, inorder, n_signatures = 0; memarea_t *area = NULL, *rs_area = NULL; + consensus_flavor_t flav = FLAV_NS; + tor_assert(s); if (eos_out) *eos_out = NULL; - if (router_get_networkstatus_v3_hash(s, ns_digest)) { + if (router_get_networkstatus_v3_hashes(s, &ns_digests)) { log_warn(LD_DIR, "Unable to compute digest of network-status"); goto err; } @@ -2209,7 +2787,23 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, } ns = tor_malloc_zero(sizeof(networkstatus_t)); - memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN); + memcpy(&ns->digests, &ns_digests, sizeof(ns_digests)); + + tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION); + tor_assert(tok); + if (tok->n_args > 1) { + int flavor = networkstatus_parse_flavor_name(tok->args[1]); + if (flavor < 0) { + log_warn(LD_DIR, "Can't parse document with unknown flavor %s", + escaped(tok->args[2])); + goto err; + } + ns->flavor = flav = flavor; + } + if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) { + log_warn(LD_DIR, "Flavor found on non-consenus networkstatus."); + goto err; + } if (ns_type != NS_TYPE_CONSENSUS) { const char *end_of_cert = NULL; @@ -2363,8 +2957,9 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, if (voter) smartlist_add(ns->voters, voter); voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t)); + voter->sigs = smartlist_create(); if (ns->type != NS_TYPE_CONSENSUS) - memcpy(voter->vote_digest, ns_digest, DIGEST_LEN); + memcpy(voter->vote_digest, ns_digests.d[DIGEST_SHA1], DIGEST_LEN); voter->nickname = tor_strdup(tok->args[0]); if (strlen(tok->args[1]) != HEX_DIGEST_LEN || @@ -2456,7 +3051,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, if (ns->type != NS_TYPE_CONSENSUS) { vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t)); if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns, - rs, 0)) + rs, 0, 0)) smartlist_add(ns->routerstatus_list, rs); else { tor_free(rs->version); @@ -2466,7 +3061,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, routerstatus_t *rs; if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, NULL, NULL, - ns->consensus_method))) + ns->consensus_method, + flav))) smartlist_add(ns->routerstatus_list, rs); } } @@ -2499,14 +3095,73 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, goto err; } - SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok, { + int found_sig = 0; + SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) { + tok = _tok; + if (tok->tp == K_DIRECTORY_SIGNATURE) + found_sig = 1; + else if (found_sig) { + log_warn(LD_DIR, "Extraneous token after first directory-signature"); + goto err; + } + } SMARTLIST_FOREACH_END(_tok); + } + + if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) { + if (tok != smartlist_get(footer_tokens, 0)) { + log_warn(LD_DIR, "Misplaced directory-footer token"); + goto err; + } + } + + tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS); + if (tok) { + ns->weight_params = smartlist_create(); + for (i = 0; i < tok->n_args; ++i) { + int ok=0; + char *eq = strchr(tok->args[i], '='); + if (!eq) { + log_warn(LD_DIR, "Bad element '%s' in weight params", + escaped(tok->args[i])); + goto err; + } + tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i])); + goto err; + } + smartlist_add(ns->weight_params, tor_strdup(tok->args[i])); + } + } + + SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) { char declared_identity[DIGEST_LEN]; networkstatus_voter_info_t *v; + document_signature_t *sig; + const char *id_hexdigest = NULL; + const char *sk_hexdigest = NULL; + digest_algorithm_t alg = DIGEST_SHA1; tok = _tok; if (tok->tp != K_DIRECTORY_SIGNATURE) continue; tor_assert(tok->n_args >= 2); + if (tok->n_args == 2) { + id_hexdigest = tok->args[0]; + sk_hexdigest = tok->args[1]; + } else { + const char *algname = tok->args[0]; + int a; + id_hexdigest = tok->args[1]; + sk_hexdigest = tok->args[2]; + a = crypto_digest_algorithm_parse_name(algname); + if (a<0) { + log_warn(LD_DIR, "Unknown digest algorithm %s; skipping", + escaped(algname)); + continue; + } + alg = a; + } if (!tok->object_type || strcmp(tok->object_type, "SIGNATURE") || @@ -2515,11 +3170,11 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, goto err; } - if (strlen(tok->args[0]) != HEX_DIGEST_LEN || + if (strlen(id_hexdigest) != HEX_DIGEST_LEN || base16_decode(declared_identity, sizeof(declared_identity), - tok->args[0], HEX_DIGEST_LEN) < 0) { + id_hexdigest, HEX_DIGEST_LEN) < 0) { log_warn(LD_DIR, "Error decoding declared identity %s in " - "network-status vote.", escaped(tok->args[0])); + "network-status vote.", escaped(id_hexdigest)); goto err; } if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) { @@ -2527,11 +3182,15 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, "any declared directory source."); goto err; } - if (strlen(tok->args[1]) != HEX_DIGEST_LEN || - base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest), - tok->args[1], HEX_DIGEST_LEN) < 0) { - log_warn(LD_DIR, "Error decoding declared digest %s in " - "network-status vote.", escaped(tok->args[1])); + sig = tor_malloc_zero(sizeof(document_signature_t)); + memcpy(sig->identity_digest, v->identity_digest, DIGEST_LEN); + sig->alg = alg; + if (strlen(sk_hexdigest) != HEX_DIGEST_LEN || + base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest), + sk_hexdigest, HEX_DIGEST_LEN) < 0) { + log_warn(LD_DIR, "Error decoding declared signing key digest %s in " + "network-status vote.", escaped(sk_hexdigest)); + tor_free(sig); goto err; } @@ -2540,35 +3199,49 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, DIGEST_LEN)) { log_warn(LD_DIR, "Digest mismatch between declared and actual on " "network-status vote."); + tor_free(sig); goto err; } } + if (voter_get_sig_by_algorithm(v, sig->alg)) { + /* We already parsed a vote with this algorithm from this voter. Use the + first one. */ + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus " + "that contains two votes from the same voter with the same " + "algorithm. Ignoring the second vote."); + tor_free(sig); + continue; + } + if (ns->type != NS_TYPE_CONSENSUS) { - if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0, - "network-status vote")) + if (check_signature_token(ns_digests.d[DIGEST_SHA1], DIGEST_LEN, + tok, ns->cert->signing_key, 0, + "network-status vote")) { + tor_free(sig); goto err; - v->good_signature = 1; + } + sig->good_signature = 1; } else { - if (tok->object_size >= INT_MAX) + if (tok->object_size >= INT_MAX) { + tor_free(sig); goto err; - /* We already parsed a vote from this voter. Use the first one. */ - if (v->signature) { - log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus " - "that contains two votes from the same voter. Ignoring " - "the second vote."); - continue; } - - v->signature = tor_memdup(tok->object_body, tok->object_size); - v->signature_len = (int) tok->object_size; + sig->signature = tor_memdup(tok->object_body, tok->object_size); + sig->signature_len = (int) tok->object_size; } + smartlist_add(v->sigs, sig); + ++n_signatures; - }); + } SMARTLIST_FOREACH_END(_tok); if (! n_signatures) { log_warn(LD_DIR, "No signatures on networkstatus vote."); goto err; + } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) { + log_warn(LD_DIR, "Received more than one signature on a " + "network-status vote."); + goto err; } if (eos_out) @@ -2576,27 +3249,31 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, goto done; err: - if (ns) - networkstatus_vote_free(ns); + dump_desc(s_dup, "v3 networkstatus"); + networkstatus_vote_free(ns); ns = NULL; done: if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (voter) { + if (voter->sigs) { + SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig, + document_signature_free(sig)); + smartlist_free(voter->sigs); + } tor_free(voter->nickname); tor_free(voter->address); tor_free(voter->contact); - tor_free(voter->signature); tor_free(voter); } if (rs_tokens) { - SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_clear(t)); smartlist_free(rs_tokens); } if (footer_tokens) { - SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t)); smartlist_free(footer_tokens); } if (area) { @@ -2609,6 +3286,35 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, return ns; } +/** Return the digests_t that holds the digests of the + * <b>flavor_name</b>-flavored networkstatus according to the detached + * signatures document <b>sigs</b>, allocating a new digests_t as neeeded. */ +static digests_t * +detached_get_digests(ns_detached_signatures_t *sigs, const char *flavor_name) +{ + digests_t *d = strmap_get(sigs->digests, flavor_name); + if (!d) { + d = tor_malloc_zero(sizeof(digests_t)); + strmap_set(sigs->digests, flavor_name, d); + } + return d; +} + +/** Return the list of signatures of the <b>flavor_name</b>-flavored + * networkstatus according to the detached signatures document <b>sigs</b>, + * allocating a new digests_t as neeeded. */ +static smartlist_t * +detached_get_signatures(ns_detached_signatures_t *sigs, + const char *flavor_name) +{ + smartlist_t *sl = strmap_get(sigs->signatures, flavor_name); + if (!sl) { + sl = smartlist_create(); + strmap_set(sigs->signatures, flavor_name, sl); + } + return sl; +} + /** Parse a detached v3 networkstatus signature document between <b>s</b> and * <b>eos</b> and return the result. Return -1 on failure. */ ns_detached_signatures_t * @@ -2618,10 +3324,13 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) * networkstatus_parse_vote_from_string(). */ directory_token_t *tok; memarea_t *area = NULL; + digests_t *digests; smartlist_t *tokens = smartlist_create(); ns_detached_signatures_t *sigs = tor_malloc_zero(sizeof(ns_detached_signatures_t)); + sigs->digests = strmap_new(); + sigs->signatures = strmap_new(); if (!eos) eos = s + strlen(s); @@ -2633,18 +3342,57 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) goto err; } - tok = find_by_keyword(tokens, K_CONSENSUS_DIGEST); - if (strlen(tok->args[0]) != HEX_DIGEST_LEN) { - log_warn(LD_DIR, "Wrong length on consensus-digest in detached " - "networkstatus signatures"); - goto err; - } - if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN, - tok->args[0], strlen(tok->args[0])) < 0) { - log_warn(LD_DIR, "Bad encoding on on consensus-digest in detached " - "networkstatus signatures"); - goto err; - } + /* Grab all the digest-like tokens. */ + SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) { + const char *algname; + digest_algorithm_t alg; + const char *flavor; + const char *hexdigest; + size_t expected_length; + + tok = _tok; + + if (tok->tp == K_CONSENSUS_DIGEST) { + algname = "sha1"; + alg = DIGEST_SHA1; + flavor = "ns"; + hexdigest = tok->args[0]; + } else if (tok->tp == K_ADDITIONAL_DIGEST) { + int a = crypto_digest_algorithm_parse_name(tok->args[1]); + if (a<0) { + log_warn(LD_DIR, "Unrecognized algorithm name %s", tok->args[0]); + continue; + } + alg = (digest_algorithm_t) a; + flavor = tok->args[0]; + algname = tok->args[1]; + hexdigest = tok->args[2]; + } else { + continue; + } + + expected_length = + (alg == DIGEST_SHA1) ? HEX_DIGEST_LEN : HEX_DIGEST256_LEN; + + if (strlen(hexdigest) != expected_length) { + log_warn(LD_DIR, "Wrong length on consensus-digest in detached " + "networkstatus signatures"); + goto err; + } + digests = detached_get_digests(sigs, flavor); + tor_assert(digests); + if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) { + log_warn(LD_DIR, "Multiple digests for %s with %s on detached " + "signatures document", flavor, algname); + continue; + } + if (base16_decode(digests->d[alg], DIGEST256_LEN, + hexdigest, strlen(hexdigest)) < 0) { + log_warn(LD_DIR, "Bad encoding on consensus-digest in detached " + "networkstatus signatures"); + goto err; + } + } SMARTLIST_FOREACH_END(_tok); tok = find_by_keyword(tokens, K_VALID_AFTER); if (parse_iso_time(tok->args[0], &sigs->valid_after)) { @@ -2664,57 +3412,102 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) goto err; } - sigs->signatures = smartlist_create(); - SMARTLIST_FOREACH(tokens, directory_token_t *, _tok, - { - char id_digest[DIGEST_LEN]; - char sk_digest[DIGEST_LEN]; - networkstatus_voter_info_t *voter; + SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) { + const char *id_hexdigest; + const char *sk_hexdigest; + const char *algname; + const char *flavor; + digest_algorithm_t alg; + + char id_digest[DIGEST_LEN]; + char sk_digest[DIGEST_LEN]; + smartlist_t *siglist; + document_signature_t *sig; + int is_duplicate; - tok = _tok; - if (tok->tp != K_DIRECTORY_SIGNATURE) - continue; + tok = _tok; + if (tok->tp == K_DIRECTORY_SIGNATURE) { tor_assert(tok->n_args >= 2); + flavor = "ns"; + algname = "sha1"; + id_hexdigest = tok->args[0]; + sk_hexdigest = tok->args[1]; + } else if (tok->tp == K_ADDITIONAL_SIGNATURE) { + tor_assert(tok->n_args >= 4); + flavor = tok->args[0]; + algname = tok->args[1]; + id_hexdigest = tok->args[2]; + sk_hexdigest = tok->args[3]; + } else { + continue; + } - if (!tok->object_type || - strcmp(tok->object_type, "SIGNATURE") || - tok->object_size < 128 || tok->object_size > 512) { - log_warn(LD_DIR, "Bad object type or length on directory-signature"); - goto err; + { + int a = crypto_digest_algorithm_parse_name(algname); + if (a<0) { + log_warn(LD_DIR, "Unrecognized algorithm name %s", algname); + continue; } + alg = (digest_algorithm_t) a; + } - if (strlen(tok->args[0]) != HEX_DIGEST_LEN || - base16_decode(id_digest, sizeof(id_digest), - tok->args[0], HEX_DIGEST_LEN) < 0) { - log_warn(LD_DIR, "Error decoding declared identity %s in " - "network-status vote.", escaped(tok->args[0])); - goto err; - } - if (strlen(tok->args[1]) != HEX_DIGEST_LEN || - base16_decode(sk_digest, sizeof(sk_digest), - tok->args[1], HEX_DIGEST_LEN) < 0) { - log_warn(LD_DIR, "Error decoding declared digest %s in " - "network-status vote.", escaped(tok->args[1])); - goto err; - } + if (!tok->object_type || + strcmp(tok->object_type, "SIGNATURE") || + tok->object_size < 128 || tok->object_size > 512) { + log_warn(LD_DIR, "Bad object type or length on directory-signature"); + goto err; + } - voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t)); - memcpy(voter->identity_digest, id_digest, DIGEST_LEN); - memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN); - if (tok->object_size >= INT_MAX) - goto err; - voter->signature = tor_memdup(tok->object_body, tok->object_size); - voter->signature_len = (int) tok->object_size; + if (strlen(id_hexdigest) != HEX_DIGEST_LEN || + base16_decode(id_digest, sizeof(id_digest), + id_hexdigest, HEX_DIGEST_LEN) < 0) { + log_warn(LD_DIR, "Error decoding declared identity %s in " + "network-status vote.", escaped(id_hexdigest)); + goto err; + } + if (strlen(sk_hexdigest) != HEX_DIGEST_LEN || + base16_decode(sk_digest, sizeof(sk_digest), + sk_hexdigest, HEX_DIGEST_LEN) < 0) { + log_warn(LD_DIR, "Error decoding declared signing key digest %s in " + "network-status vote.", escaped(sk_hexdigest)); + goto err; + } - smartlist_add(sigs->signatures, voter); + siglist = detached_get_signatures(sigs, flavor); + is_duplicate = 0; + SMARTLIST_FOREACH(siglist, document_signature_t *, s, { + if (s->alg == alg && + !memcmp(id_digest, s->identity_digest, DIGEST_LEN) && + !memcmp(sk_digest, s->signing_key_digest, DIGEST_LEN)) { + is_duplicate = 1; + } }); + if (is_duplicate) { + log_warn(LD_DIR, "Two signatures with identical keys and algorithm " + "found."); + continue; + } + + sig = tor_malloc_zero(sizeof(document_signature_t)); + sig->alg = alg; + memcpy(sig->identity_digest, id_digest, DIGEST_LEN); + memcpy(sig->signing_key_digest, sk_digest, DIGEST_LEN); + if (tok->object_size >= INT_MAX) { + tor_free(sig); + goto err; + } + sig->signature = tor_memdup(tok->object_body, tok->object_size); + sig->signature_len = (int) tok->object_size; + + smartlist_add(siglist, sig); + } SMARTLIST_FOREACH_END(_tok); goto done; err: ns_detached_signatures_free(sigs); sigs = NULL; done: - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); if (area) { DUMP_AREA(area, "detached signatures"); @@ -2770,7 +3563,7 @@ router_parse_addr_policy_item_from_string(const char *s, int assume_action) err: r = NULL; done: - token_free(tok); + token_clear(tok); if (area) { DUMP_AREA(area, "policy item"); memarea_drop_all(area); @@ -2893,9 +3686,8 @@ assert_addr_policy_ok(smartlist_t *lst) /** Free all resources allocated for <b>tok</b> */ static void -token_free(directory_token_t *tok) +token_clear(directory_token_t *tok) { - tor_assert(tok); if (tok->key) crypto_free_pk_env(tok->key); } @@ -2907,7 +3699,7 @@ token_free(directory_token_t *tok) #define RET_ERR(msg) \ STMT_BEGIN \ - if (tok) token_free(tok); \ + if (tok) token_clear(tok); \ tok = ALLOC_ZERO(sizeof(directory_token_t)); \ tok->tp = _ERR; \ tok->error = STRDUP(msg); \ @@ -3188,7 +3980,7 @@ tokenize_string(memarea_t *area, tok = get_next_token(area, s, end, table); if (tok->tp == _ERR) { log_warn(LD_DIR, "parse error: %s", tok->error); - token_free(tok); + token_clear(tok); return -1; } ++counts[tok->tp]; @@ -3302,17 +4094,11 @@ find_all_exitpolicy(smartlist_t *s) return out; } -/** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first - * occurrence of <b>start_str</b> through the first instance of c after the - * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in - * <b>digest</b>; return 0 on success. - * - * If no such substring exists, return -1. - */ static int -router_get_hash_impl(const char *s, size_t s_len, char *digest, +router_get_hash_impl_helper(const char *s, size_t s_len, const char *start_str, - const char *end_str, char end_c) + const char *end_str, char end_c, + const char **start_out, const char **end_out) { const char *start, *end; start = tor_memstr(s, s_len, start_str); @@ -3339,14 +4125,214 @@ router_get_hash_impl(const char *s, size_t s_len, char *digest, } ++end; - if (crypto_digest(digest, start, end-start)) { - log_warn(LD_BUG,"couldn't compute digest"); + *start_out = start; + *end_out = end; + return 0; +} + +/** Compute the digest of the substring of <b>s</b> taken from the first + * occurrence of <b>start_str</b> through the first instance of c after the + * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in + * <b>digest</b>; return 0 on success. + * + * If no such substring exists, return -1. + */ +static int +router_get_hash_impl(const char *s, size_t s_len, char *digest, + const char *start_str, + const char *end_str, char end_c, + digest_algorithm_t alg) +{ + const char *start=NULL, *end=NULL; + if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c, + &start,&end)<0) return -1; + + if (alg == DIGEST_SHA1) { + if (crypto_digest(digest, start, end-start)) { + log_warn(LD_BUG,"couldn't compute digest"); + return -1; + } + } else { + if (crypto_digest256(digest, start, end-start, alg)) { + log_warn(LD_BUG,"couldn't compute digest"); + return -1; + } } return 0; } +/** As router_get_hash_impl, but compute all hashes. */ +static int +router_get_hashes_impl(const char *s, size_t s_len, digests_t *digests, + const char *start_str, + const char *end_str, char end_c) +{ + const char *start=NULL, *end=NULL; + if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c, + &start,&end)<0) + return -1; + + if (crypto_digest_all(digests, start, end-start)) { + log_warn(LD_BUG,"couldn't compute digests"); + return -1; + } + + return 0; +} + +/** Assuming that s starts with a microdesc, return the start of the + * *NEXT* one. Return NULL on "not found." */ +static const char * +find_start_of_next_microdesc(const char *s, const char *eos) +{ + int started_with_annotations; + s = eat_whitespace_eos(s, eos); + if (!s) + return NULL; + +#define CHECK_LENGTH() STMT_BEGIN \ + if (s+32 > eos) \ + return NULL; \ + STMT_END + +#define NEXT_LINE() STMT_BEGIN \ + s = memchr(s, '\n', eos-s); \ + if (!s || s+1 >= eos) \ + return NULL; \ + s++; \ + STMT_END + + CHECK_LENGTH(); + + started_with_annotations = (*s == '@'); + + if (started_with_annotations) { + /* Start by advancing to the first non-annotation line. */ + while (*s == '@') + NEXT_LINE(); + } + CHECK_LENGTH(); + + /* Now we should be pointed at an onion-key line. If we are, then skip + * it. */ + if (!strcmpstart(s, "onion-key")) + NEXT_LINE(); + + /* Okay, now we're pointed at the first line of the microdescriptor which is + not an annotation or onion-key. The next line that _is_ an annotation or + onion-key is the start of the next microdescriptor. */ + while (s+32 < eos) { + if (*s == '@' || !strcmpstart(s, "onion-key")) + return s; + NEXT_LINE(); + } + return NULL; + +#undef CHECK_LENGTH +#undef NEXT_LINE +} + +/** Parse as many microdescriptors as are found from the string starting at + * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any + * annotations we recognize and ignore ones we don't. If <b>copy_body</b> is + * true, then strdup the bodies of the microdescriptors. Return all newly + * parsed microdescriptors in a newly allocated smartlist_t. */ +smartlist_t * +microdescs_parse_from_string(const char *s, const char *eos, + int allow_annotations, int copy_body) +{ + smartlist_t *tokens; + smartlist_t *result; + microdesc_t *md = NULL; + memarea_t *area; + const char *start = s; + const char *start_of_next_microdesc; + int flags = allow_annotations ? TS_ANNOTATIONS_OK : 0; + + directory_token_t *tok; + + if (!eos) + eos = s + strlen(s); + + s = eat_whitespace_eos(s, eos); + area = memarea_new(); + result = smartlist_create(); + tokens = smartlist_create(); + + while (s < eos) { + start_of_next_microdesc = find_start_of_next_microdesc(s, eos); + if (!start_of_next_microdesc) + start_of_next_microdesc = eos; + + if (tokenize_string(area, s, start_of_next_microdesc, tokens, + microdesc_token_table, flags)) { + log_warn(LD_DIR, "Unparseable microdescriptor"); + goto next; + } + + md = tor_malloc_zero(sizeof(microdesc_t)); + { + const char *cp = tor_memstr(s, start_of_next_microdesc-s, + "onion-key"); + tor_assert(cp); + + md->bodylen = start_of_next_microdesc - cp; + if (copy_body) + md->body = tor_strndup(cp, md->bodylen); + else + md->body = (char*)cp; + md->off = cp - start; + } + + if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) { + if (parse_iso_time(tok->args[0], &md->last_listed)) { + log_warn(LD_DIR, "Bad last-listed time in microdescriptor"); + goto next; + } + } + + tok = find_by_keyword(tokens, K_ONION_KEY); + md->onion_pkey = tok->key; + tok->key = NULL; + + if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) { + int i; + md->family = smartlist_create(); + for (i=0;i<tok->n_args;++i) { + if (!is_legal_nickname_or_hexdigest(tok->args[i])) { + log_warn(LD_DIR, "Illegal nickname %s in family line", + escaped(tok->args[i])); + goto next; + } + smartlist_add(md->family, tor_strdup(tok->args[i])); + } + } + + if ((tok = find_opt_by_keyword(tokens, K_P))) { + md->exitsummary = tor_strdup(tok->args[0]); + } + + crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256); + + smartlist_add(result, md); + + md = NULL; + next: + microdesc_free(md); + + memarea_clear(area); + smartlist_clear(tokens); + s = start_of_next_microdesc; + } + + memarea_drop_all(area); + smartlist_free(tokens); + + return result; +} + /** Parse the Tor version of the platform string <b>platform</b>, * and compare it to the version in <b>cutoff</b>. Return 1 if * the router is at least as new as the cutoff, else return 0. @@ -3371,7 +4357,7 @@ tor_version_as_new_as(const char *platform, const char *cutoff) if (!*start) return 0; s = (char *)find_whitespace(start); /* also finds '\0', which is fine */ s2 = (char*)eat_whitespace(s); - if (!strcmpstart(s2, "(r")) + if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-")) s = (char*)find_whitespace(s2); if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */ @@ -3467,6 +4453,23 @@ tor_version_parse(const char *s, tor_version_t *out) if (!strcmpstart(cp, "(r")) { cp += 2; out->svn_revision = (int) strtol(cp,&eos,10); + } else if (!strcmpstart(cp, "(git-")) { + char *close_paren = strchr(cp, ')'); + int hexlen; + char digest[DIGEST_LEN]; + if (! close_paren) + return -1; + cp += 5; + if (close_paren-cp > HEX_DIGEST_LEN) + return -1; + hexlen = (int)(close_paren-cp); + memset(digest, 0, sizeof(digest)); + if ( hexlen == 0 || (hexlen % 2) == 1) + return -1; + if (base16_decode(digest, hexlen/2, cp, hexlen)) + return -1; + memcpy(out->git_tag, digest, hexlen/2); + out->git_tag_len = hexlen/2; } return 0; @@ -3492,8 +4495,14 @@ tor_version_compare(tor_version_t *a, tor_version_t *b) return i; else if ((i = strcmp(a->status_tag, b->status_tag))) return i; + else if ((i = a->svn_revision - b->svn_revision)) + return i; + else if ((i = a->git_tag_len - b->git_tag_len)) + return i; + else if (a->git_tag_len) + return memcmp(a->git_tag, b->git_tag, a->git_tag_len); else - return a->svn_revision - b->svn_revision; + return 0; } /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series. @@ -3582,7 +4591,7 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, /* Compute descriptor hash for later validation. */ if (router_get_hash_impl(desc, strlen(desc), desc_hash, "rendezvous-service-descriptor ", - "\nsignature", '\n') < 0) { + "\nsignature", '\n', DIGEST_SHA1) < 0) { log_warn(LD_REND, "Couldn't compute descriptor hash."); goto err; } @@ -3701,7 +4710,7 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, /* Parse and verify signature. */ tok = find_by_keyword(tokens, R_SIGNATURE); note_crypto_pk_op(VERIFY_RTR); - if (check_signature_token(desc_hash, tok, result->pk, 0, + if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0, "v2 rendezvous service descriptor") < 0) goto err; /* Verify that descriptor ID belongs to public key and secret ID part. */ @@ -3715,12 +4724,11 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, } goto done; err: - if (result) - rend_service_descriptor_free(result); + rend_service_descriptor_free(result); result = NULL; done: if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (area) @@ -3878,7 +4886,7 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed, eos = eos+1; tor_assert(eos <= intro_points_encoded+intro_points_encoded_size); /* Free tokens and clear token list. */ - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); /* Tokenize string. */ @@ -3951,7 +4959,7 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed, done: /* Free tokens and clear token list. */ - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); if (area) memarea_drop_all(area); @@ -3990,7 +4998,7 @@ rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr) else eos = eos + 1; /* Free tokens and clear token list. */ - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); /* Tokenize string. */ @@ -4062,7 +5070,7 @@ rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr) result = -1; done: /* Free tokens and clear token list. */ - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); if (area) memarea_drop_all(area); diff --git a/src/or/routerparse.h b/src/or/routerparse.h new file mode 100644 index 0000000000..f41743bcfb --- /dev/null +++ b/src/or/routerparse.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file routerpase.h + * \brief Header file for routerparse.c. + **/ + +#ifndef _TOR_ROUTERPARSE_H +#define _TOR_ROUTERPARSE_H + +int router_get_router_hash(const char *s, size_t s_len, char *digest); +int router_get_dir_hash(const char *s, char *digest); +int router_get_runningrouters_hash(const char *s, char *digest); +int router_get_networkstatus_v2_hash(const char *s, char *digest); +int router_get_networkstatus_v3_hash(const char *s, char *digest, + digest_algorithm_t algorithm); +int router_get_networkstatus_v3_hashes(const char *s, digests_t *digests); +int router_get_extrainfo_hash(const char *s, char *digest); +#define DIROBJ_MAX_SIG_LEN 256 +int router_append_dirobj_signature(char *buf, size_t buf_len, + const char *digest, + size_t digest_len, + crypto_pk_env_t *private_key); +int router_parse_list_from_string(const char **s, const char *eos, + smartlist_t *dest, + saved_location_t saved_location, + int is_extrainfo, + int allow_annotations, + const char *prepend_annotations); +int router_parse_runningrouters(const char *str); +int router_parse_directory(const char *str); + +routerinfo_t *router_parse_entry_from_string(const char *s, const char *end, + int cache_copy, + int allow_annotations, + const char *prepend_annotations); +extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end, + int cache_copy, struct digest_ri_map_t *routermap); +addr_policy_t *router_parse_addr_policy_item_from_string(const char *s, + int assume_action); +version_status_t tor_version_is_obsolete(const char *myversion, + const char *versionlist); +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); +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); + +int compare_routerstatus_entries(const void **_a, const void **_b); +networkstatus_v2_t *networkstatus_v2_parse_from_string(const char *s); +int networkstatus_verify_bw_weights(networkstatus_t *ns); +networkstatus_t *networkstatus_parse_vote_from_string(const char *s, + const char **eos_out, + networkstatus_type_t ns_type); +ns_detached_signatures_t *networkstatus_parse_detached_signatures( + const char *s, const char *eos); + +smartlist_t *microdescs_parse_from_string(const char *s, const char *eos, + int allow_annotations, + int copy_body); + +authority_cert_t *authority_cert_parse_from_string(const char *s, + const char **end_of_string); +int rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, + char *desc_id_out, + char **intro_points_encrypted_out, + size_t *intro_points_encrypted_size_out, + size_t *encoded_size_out, + const char **next_out, const char *desc); +int rend_decrypt_introduction_points(char **ipos_decrypted, + size_t *ipos_decrypted_size, + const char *descriptor_cookie, + const char *ipos_encrypted, + size_t ipos_encrypted_size); +int rend_parse_introduction_points(rend_service_descriptor_t *parsed, + const char *intro_points_encoded, + size_t intro_points_encoded_size); +int rend_parse_client_keys(strmap_t *parsed_clients, const char *str); + +void tor_gettimeofday_cache_clear(void); + +#endif + diff --git a/src/or/test.c b/src/or/test.c deleted file mode 100644 index 14ba953544..0000000000 --- a/src/or/test.c +++ /dev/null @@ -1,4911 +0,0 @@ -/* Copyright (c) 2001-2004, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2010, 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_svn_revision[] = ""; - -/** - * \file test.c - * \brief Unit tests for many pieces of the lower level Tor modules. - **/ - -#include "orconfig.h" - -#include <stdio.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif - -#ifdef MS_WINDOWS -/* For mkdir() */ -#include <direct.h> -#else -#include <dirent.h> -#endif - -/* These macros pull in declarations for some functions and structures that - * are typically file-private. */ -#define BUFFERS_PRIVATE -#define CONFIG_PRIVATE -#define CONTROL_PRIVATE -#define CRYPTO_PRIVATE -#define DIRSERV_PRIVATE -#define DIRVOTE_PRIVATE -#define GEOIP_PRIVATE -#define MEMPOOL_PRIVATE -#define ROUTER_PRIVATE - -#include "or.h" -#include "test.h" -#include "torgzip.h" -#include "mempool.h" -#include "memarea.h" - -#ifdef USE_DMALLOC -#include <dmalloc.h> -#include <openssl/crypto.h> -#endif - -/** Set to true if any unit test has failed. Mostly, this is set by the macros - * in test.h */ -int have_failed = 0; - -/** Temporary directory (set up by setup_directory) under which we store all - * our files during testing. */ -static char temp_dir[256]; - -/** Select and create the temporary directory we'll use to run our unit tests. - * Store it in <b>temp_dir</b>. Exit immediately if we can't create it. - * idempotent. */ -static void -setup_directory(void) -{ - static int is_setup = 0; - int r; - if (is_setup) return; - -#ifdef MS_WINDOWS - // XXXX - tor_snprintf(temp_dir, sizeof(temp_dir), - "c:\\windows\\temp\\tor_test_%d", (int)getpid()); - r = mkdir(temp_dir); -#else - tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d", (int) getpid()); - r = mkdir(temp_dir, 0700); -#endif - if (r) { - fprintf(stderr, "Can't create directory %s:", temp_dir); - perror(""); - exit(1); - } - is_setup = 1; -} - -/** Return a filename relative to our testing temporary directory */ -static const char * -get_fname(const char *name) -{ - static char buf[1024]; - setup_directory(); - tor_snprintf(buf,sizeof(buf),"%s/%s",temp_dir,name); - return buf; -} - -/** Remove all files stored under the temporary directory, and the directory - * itself. */ -static void -remove_directory(void) -{ - smartlist_t *elements = tor_listdir(temp_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); - tor_free(tmp); - }); - SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); - smartlist_free(elements); - } - rmdir(temp_dir); -} - -/** Define this if unit tests spend too much time generating public keys*/ -#undef CACHE_GENERATED_KEYS - -static crypto_pk_env_t *pregen_keys[5] = {NULL, NULL, NULL, NULL, NULL}; -#define N_PREGEN_KEYS ((int)(sizeof(pregen_keys)/sizeof(pregen_keys[0]))) - -/** Generate and return a new keypair for use in unit tests. If we're using - * the key cache optimization, we might reuse keys: we only guarantee that - * keys made with distinct values for <b>idx</b> are different. The value of - * <b>idx</b> must be at least 0, and less than N_PREGEN_KEYS. */ -static crypto_pk_env_t * -pk_generate(int idx) -{ -#ifdef CACHE_GENERATED_KEYS - tor_assert(idx < N_PREGEN_KEYS); - if (! pregen_keys[idx]) { - pregen_keys[idx] = crypto_new_pk_env(); - tor_assert(!crypto_pk_generate_key(pregen_keys[idx])); - } - return crypto_pk_dup_key(pregen_keys[idx]); -#else - crypto_pk_env_t *result; - (void) idx; - result = crypto_new_pk_env(); - tor_assert(!crypto_pk_generate_key(result)); - return result; -#endif -} - -/** Free all storage used for the cached key optimization. */ -static void -free_pregenerated_keys(void) -{ - unsigned idx; - for (idx = 0; idx < N_PREGEN_KEYS; ++idx) { - if (pregen_keys[idx]) { - crypto_free_pk_env(pregen_keys[idx]); - pregen_keys[idx] = NULL; - } - } -} - -/** Run unit tests for buffers.c */ -static void -test_buffers(void) -{ - char str[256]; - char str2[256]; - - buf_t *buf = NULL, *buf2 = NULL; - const char *cp; - - int j; - size_t r; - - /**** - * buf_new - ****/ - if (!(buf = buf_new())) - test_fail(); - - //test_eq(buf_capacity(buf), 4096); - test_eq(buf_datalen(buf), 0); - - /**** - * General pointer frobbing - */ - for (j=0;j<256;++j) { - str[j] = (char)j; - } - write_to_buf(str, 256, buf); - write_to_buf(str, 256, buf); - test_eq(buf_datalen(buf), 512); - fetch_from_buf(str2, 200, buf); - test_memeq(str, str2, 200); - test_eq(buf_datalen(buf), 312); - memset(str2, 0, sizeof(str2)); - - fetch_from_buf(str2, 256, buf); - test_memeq(str+200, str2, 56); - test_memeq(str, str2+56, 200); - test_eq(buf_datalen(buf), 56); - memset(str2, 0, sizeof(str2)); - /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add - * another 3584 bytes, we hit the end. */ - for (j=0;j<15;++j) { - write_to_buf(str, 256, buf); - } - assert_buf_ok(buf); - test_eq(buf_datalen(buf), 3896); - fetch_from_buf(str2, 56, buf); - test_eq(buf_datalen(buf), 3840); - test_memeq(str+200, str2, 56); - for (j=0;j<15;++j) { - memset(str2, 0, sizeof(str2)); - fetch_from_buf(str2, 256, buf); - test_memeq(str, str2, 256); - } - test_eq(buf_datalen(buf), 0); - buf_free(buf); - buf = NULL; - - /* Okay, now make sure growing can work. */ - buf = buf_new_with_capacity(16); - //test_eq(buf_capacity(buf), 16); - write_to_buf(str+1, 255, buf); - //test_eq(buf_capacity(buf), 256); - fetch_from_buf(str2, 254, buf); - test_memeq(str+1, str2, 254); - //test_eq(buf_capacity(buf), 256); - assert_buf_ok(buf); - write_to_buf(str, 32, buf); - //test_eq(buf_capacity(buf), 256); - assert_buf_ok(buf); - write_to_buf(str, 256, buf); - assert_buf_ok(buf); - //test_eq(buf_capacity(buf), 512); - test_eq(buf_datalen(buf), 33+256); - fetch_from_buf(str2, 33, buf); - test_eq(*str2, str[255]); - - test_memeq(str2+1, str, 32); - //test_eq(buf_capacity(buf), 512); - test_eq(buf_datalen(buf), 256); - fetch_from_buf(str2, 256, buf); - test_memeq(str, str2, 256); - - /* now try shrinking: case 1. */ - buf_free(buf); - buf = buf_new_with_capacity(33668); - for (j=0;j<67;++j) { - write_to_buf(str,255, buf); - } - //test_eq(buf_capacity(buf), 33668); - test_eq(buf_datalen(buf), 17085); - for (j=0; j < 40; ++j) { - fetch_from_buf(str2, 255,buf); - test_memeq(str2, str, 255); - } - - /* now try shrinking: case 2. */ - buf_free(buf); - buf = buf_new_with_capacity(33668); - for (j=0;j<67;++j) { - write_to_buf(str,255, buf); - } - for (j=0; j < 20; ++j) { - fetch_from_buf(str2, 255,buf); - test_memeq(str2, str, 255); - } - for (j=0;j<80;++j) { - write_to_buf(str,255, buf); - } - //test_eq(buf_capacity(buf),33668); - for (j=0; j < 120; ++j) { - fetch_from_buf(str2, 255,buf); - test_memeq(str2, str, 255); - } - - /* Move from buf to buf. */ - buf_free(buf); - buf = buf_new_with_capacity(4096); - buf2 = buf_new_with_capacity(4096); - for (j=0;j<100;++j) - write_to_buf(str, 255, buf); - test_eq(buf_datalen(buf), 25500); - for (j=0;j<100;++j) { - r = 10; - move_buf_to_buf(buf2, buf, &r); - test_eq(r, 0); - } - test_eq(buf_datalen(buf), 24500); - test_eq(buf_datalen(buf2), 1000); - for (j=0;j<3;++j) { - fetch_from_buf(str2, 255, buf2); - test_memeq(str2, str, 255); - } - r = 8192; /*big move*/ - move_buf_to_buf(buf2, buf, &r); - test_eq(r, 0); - r = 30000; /* incomplete move */ - move_buf_to_buf(buf2, buf, &r); - test_eq(r, 13692); - for (j=0;j<97;++j) { - fetch_from_buf(str2, 255, buf2); - test_memeq(str2, str, 255); - } - buf_free(buf); - buf_free(buf2); - buf = buf2 = NULL; - - buf = buf_new_with_capacity(5); - cp = "Testing. This is a moderately long Testing string."; - for (j = 0; cp[j]; j++) - write_to_buf(cp+j, 1, buf); - test_eq(0, buf_find_string_offset(buf, "Testing", 7)); - test_eq(1, buf_find_string_offset(buf, "esting", 6)); - test_eq(1, buf_find_string_offset(buf, "est", 3)); - test_eq(39, buf_find_string_offset(buf, "ing str", 7)); - test_eq(35, buf_find_string_offset(buf, "Testing str", 11)); - test_eq(32, buf_find_string_offset(buf, "ng ", 3)); - test_eq(43, buf_find_string_offset(buf, "string.", 7)); - test_eq(-1, buf_find_string_offset(buf, "shrdlu", 6)); - test_eq(-1, buf_find_string_offset(buf, "Testing thing", 13)); - test_eq(-1, buf_find_string_offset(buf, "ngx", 3)); - buf_free(buf); - buf = NULL; - -#if 0 - { - int s; - int eof; - int i; - buf_t *buf2; - /**** - * read_to_buf - ****/ - s = open(get_fname("data"), O_WRONLY|O_CREAT|O_TRUNC, 0600); - write(s, str, 256); - close(s); - - s = open(get_fname("data"), O_RDONLY, 0); - eof = 0; - errno = 0; /* XXXX */ - i = read_to_buf(s, 10, buf, &eof); - printf("%s\n", strerror(errno)); - test_eq(i, 10); - test_eq(eof, 0); - //test_eq(buf_capacity(buf), 4096); - test_eq(buf_datalen(buf), 10); - - test_memeq(str, (char*)_buf_peek_raw_buffer(buf), 10); - - /* Test reading 0 bytes. */ - i = read_to_buf(s, 0, buf, &eof); - //test_eq(buf_capacity(buf), 512*1024); - test_eq(buf_datalen(buf), 10); - test_eq(eof, 0); - test_eq(i, 0); - - /* Now test when buffer is filled exactly. */ - buf2 = buf_new_with_capacity(6); - i = read_to_buf(s, 6, buf2, &eof); - //test_eq(buf_capacity(buf2), 6); - test_eq(buf_datalen(buf2), 6); - test_eq(eof, 0); - test_eq(i, 6); - test_memeq(str+10, (char*)_buf_peek_raw_buffer(buf2), 6); - buf_free(buf2); - buf2 = NULL; - - /* Now test when buffer is filled with more data to read. */ - buf2 = buf_new_with_capacity(32); - i = read_to_buf(s, 128, buf2, &eof); - //test_eq(buf_capacity(buf2), 128); - test_eq(buf_datalen(buf2), 32); - test_eq(eof, 0); - test_eq(i, 32); - buf_free(buf2); - buf2 = NULL; - - /* Now read to eof. */ - test_assert(buf_capacity(buf) > 256); - i = read_to_buf(s, 1024, buf, &eof); - test_eq(i, (256-32-10-6)); - test_eq(buf_capacity(buf), MAX_BUF_SIZE); - test_eq(buf_datalen(buf), 256-6-32); - test_memeq(str, (char*)_buf_peek_raw_buffer(buf), 10); /* XXX Check rest. */ - test_eq(eof, 0); - - i = read_to_buf(s, 1024, buf, &eof); - test_eq(i, 0); - test_eq(buf_capacity(buf), MAX_BUF_SIZE); - test_eq(buf_datalen(buf), 256-6-32); - test_eq(eof, 1); - } -#endif - - done: - if (buf) - buf_free(buf); - if (buf2) - buf_free(buf2); -} - -/** Run unit tests for Diffie-Hellman functionality. */ -static void -test_crypto_dh(void) -{ - crypto_dh_env_t *dh1 = crypto_dh_new(); - crypto_dh_env_t *dh2 = crypto_dh_new(); - char p1[DH_BYTES]; - char p2[DH_BYTES]; - char s1[DH_BYTES]; - char s2[DH_BYTES]; - ssize_t s1len, s2len; - - test_eq(crypto_dh_get_bytes(dh1), DH_BYTES); - test_eq(crypto_dh_get_bytes(dh2), DH_BYTES); - - memset(p1, 0, DH_BYTES); - memset(p2, 0, DH_BYTES); - test_memeq(p1, p2, DH_BYTES); - test_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES)); - test_memneq(p1, p2, DH_BYTES); - test_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES)); - test_memneq(p1, p2, DH_BYTES); - - memset(s1, 0, DH_BYTES); - memset(s2, 0xFF, DH_BYTES); - s1len = crypto_dh_compute_secret(dh1, p2, DH_BYTES, s1, 50); - s2len = crypto_dh_compute_secret(dh2, p1, DH_BYTES, s2, 50); - test_assert(s1len > 0); - test_eq(s1len, s2len); - test_memeq(s1, s2, s1len); - - { - /* XXXX Now fabricate some bad values and make sure they get caught, - * Check 0, 1, N-1, >= N, etc. - */ - } - - done: - crypto_dh_free(dh1); - crypto_dh_free(dh2); -} - -/** Run unit tests for our random number generation function and its wrappers. - */ -static void -test_crypto_rng(void) -{ - int i, j, allok; - char data1[100], data2[100]; - - /* Try out RNG. */ - test_assert(! crypto_seed_rng(0)); - crypto_rand(data1, 100); - crypto_rand(data2, 100); - test_memneq(data1,data2,100); - allok = 1; - for (i = 0; i < 100; ++i) { - uint64_t big; - char *host; - j = crypto_rand_int(100); - if (i < 0 || i >= 100) - allok = 0; - big = crypto_rand_uint64(U64_LITERAL(1)<<40); - if (big >= (U64_LITERAL(1)<<40)) - allok = 0; - big = crypto_rand_uint64(U64_LITERAL(5)); - if (big >= 5) - allok = 0; - host = crypto_random_hostname(3,8,"www.",".onion"); - if (strcmpstart(host,"www.") || - strcmpend(host,".onion") || - strlen(host) < 13 || - strlen(host) > 18) - allok = 0; - tor_free(host); - } - test_assert(allok); - done: - ; -} - -/** Run unit tests for our AES functionality */ -static void -test_crypto_aes(void) -{ - char *data1 = NULL, *data2 = NULL, *data3 = NULL; - crypto_cipher_env_t *env1 = NULL, *env2 = NULL; - int i, j; - - data1 = tor_malloc(1024); - data2 = tor_malloc(1024); - data3 = tor_malloc(1024); - - /* Now, test encryption and decryption with stream cipher. */ - data1[0]='\0'; - for (i = 1023; i>0; i -= 35) - strncat(data1, "Now is the time for all good onions", i); - - memset(data2, 0, 1024); - memset(data3, 0, 1024); - env1 = crypto_new_cipher_env(); - test_neq(env1, 0); - env2 = crypto_new_cipher_env(); - test_neq(env2, 0); - j = crypto_cipher_generate_key(env1); - crypto_cipher_set_key(env2, crypto_cipher_get_key(env1)); - crypto_cipher_encrypt_init_cipher(env1); - crypto_cipher_decrypt_init_cipher(env2); - - /* Try encrypting 512 chars. */ - crypto_cipher_encrypt(env1, data2, data1, 512); - crypto_cipher_decrypt(env2, data3, data2, 512); - test_memeq(data1, data3, 512); - test_memneq(data1, data2, 512); - - /* Now encrypt 1 at a time, and get 1 at a time. */ - for (j = 512; j < 560; ++j) { - crypto_cipher_encrypt(env1, data2+j, data1+j, 1); - } - for (j = 512; j < 560; ++j) { - crypto_cipher_decrypt(env2, data3+j, data2+j, 1); - } - test_memeq(data1, data3, 560); - /* Now encrypt 3 at a time, and get 5 at a time. */ - for (j = 560; j < 1024-5; j += 3) { - crypto_cipher_encrypt(env1, data2+j, data1+j, 3); - } - for (j = 560; j < 1024-5; j += 5) { - crypto_cipher_decrypt(env2, data3+j, data2+j, 5); - } - test_memeq(data1, data3, 1024-5); - /* Now make sure that when we encrypt with different chunk sizes, we get - the same results. */ - crypto_free_cipher_env(env2); - env2 = NULL; - - memset(data3, 0, 1024); - env2 = crypto_new_cipher_env(); - test_neq(env2, 0); - crypto_cipher_set_key(env2, crypto_cipher_get_key(env1)); - crypto_cipher_encrypt_init_cipher(env2); - for (j = 0; j < 1024-16; j += 17) { - crypto_cipher_encrypt(env2, data3+j, data1+j, 17); - } - for (j= 0; j < 1024-16; ++j) { - if (data2[j] != data3[j]) { - printf("%d: %d\t%d\n", j, (int) data2[j], (int) data3[j]); - } - } - test_memeq(data2, data3, 1024-16); - crypto_free_cipher_env(env1); - env1 = NULL; - crypto_free_cipher_env(env2); - env2 = NULL; - - /* NIST test vector for aes. */ - env1 = crypto_new_cipher_env(); /* IV starts at 0 */ - crypto_cipher_set_key(env1, "\x80\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00"); - crypto_cipher_encrypt_init_cipher(env1); - crypto_cipher_encrypt(env1, data1, - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", 16); - test_memeq_hex(data1, "0EDD33D3C621E546455BD8BA1418BEC8"); - - /* Now test rollover. All these values are originally from a python - * script. */ - crypto_cipher_set_iv(env1, "\x00\x00\x00\x00\x00\x00\x00\x00" - "\xff\xff\xff\xff\xff\xff\xff\xff"); - memset(data2, 0, 1024); - crypto_cipher_encrypt(env1, data1, data2, 32); - test_memeq_hex(data1, "335fe6da56f843199066c14a00a40231" - "cdd0b917dbc7186908a6bfb5ffd574d3"); - - crypto_cipher_set_iv(env1, "\x00\x00\x00\x00\xff\xff\xff\xff" - "\xff\xff\xff\xff\xff\xff\xff\xff"); - memset(data2, 0, 1024); - crypto_cipher_encrypt(env1, data1, data2, 32); - test_memeq_hex(data1, "e627c6423fa2d77832a02b2794094b73" - "3e63c721df790d2c6469cc1953a3ffac"); - - crypto_cipher_set_iv(env1, "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xff\xff\xff\xff\xff\xff\xff\xff"); - memset(data2, 0, 1024); - crypto_cipher_encrypt(env1, data1, data2, 32); - test_memeq_hex(data1, "2aed2bff0de54f9328efd070bf48f70a" - "0EDD33D3C621E546455BD8BA1418BEC8"); - - /* Now check rollover on inplace cipher. */ - crypto_cipher_set_iv(env1, "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xff\xff\xff\xff\xff\xff\xff\xff"); - crypto_cipher_crypt_inplace(env1, data2, 64); - test_memeq_hex(data2, "2aed2bff0de54f9328efd070bf48f70a" - "0EDD33D3C621E546455BD8BA1418BEC8" - "93e2c5243d6839eac58503919192f7ae" - "1908e67cafa08d508816659c2e693191"); - crypto_cipher_set_iv(env1, "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xff\xff\xff\xff\xff\xff\xff\xff"); - crypto_cipher_crypt_inplace(env1, data2, 64); - test_assert(tor_mem_is_zero(data2, 64)); - - done: - if (env1) - crypto_free_cipher_env(env1); - if (env2) - crypto_free_cipher_env(env2); - tor_free(data1); - tor_free(data2); - tor_free(data3); -} - -/** Run unit tests for our SHA-1 functionality */ -static void -test_crypto_sha(void) -{ - crypto_digest_env_t *d1 = NULL, *d2 = NULL; - int i; - char key[80]; - char digest[20]; - char data[50]; - char d_out1[DIGEST_LEN], d_out2[DIGEST_LEN]; - - /* Test SHA-1 with a test vector from the specification. */ - i = crypto_digest(data, "abc", 3); - test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D"); - - /* Test HMAC-SHA-1 with test cases from RFC2202. */ - - /* Case 1. */ - memset(key, 0x0b, 20); - crypto_hmac_sha1(digest, key, 20, "Hi There", 8); - test_streq(hex_str(digest, 20), - "B617318655057264E28BC0B6FB378C8EF146BE00"); - /* Case 2. */ - crypto_hmac_sha1(digest, "Jefe", 4, "what do ya want for nothing?", 28); - test_streq(hex_str(digest, 20), - "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79"); - - /* Case 4. */ - base16_decode(key, 25, - "0102030405060708090a0b0c0d0e0f10111213141516171819", 50); - memset(data, 0xcd, 50); - crypto_hmac_sha1(digest, key, 25, data, 50); - test_streq(hex_str(digest, 20), - "4C9007F4026250C6BC8414F9BF50C86C2D7235DA"); - - /* Case . */ - memset(key, 0xaa, 80); - crypto_hmac_sha1(digest, key, 80, - "Test Using Larger Than Block-Size Key - Hash Key First", - 54); - test_streq(hex_str(digest, 20), - "AA4AE5E15272D00E95705637CE8A3B55ED402112"); - - /* Incremental digest code. */ - d1 = crypto_new_digest_env(); - test_assert(d1); - crypto_digest_add_bytes(d1, "abcdef", 6); - d2 = crypto_digest_dup(d1); - test_assert(d2); - crypto_digest_add_bytes(d2, "ghijkl", 6); - crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); - crypto_digest(d_out2, "abcdefghijkl", 12); - test_memeq(d_out1, d_out2, DIGEST_LEN); - crypto_digest_assign(d2, d1); - crypto_digest_add_bytes(d2, "mno", 3); - crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); - crypto_digest(d_out2, "abcdefmno", 9); - test_memeq(d_out1, d_out2, DIGEST_LEN); - crypto_digest_get_digest(d1, d_out1, sizeof(d_out1)); - crypto_digest(d_out2, "abcdef", 6); - test_memeq(d_out1, d_out2, DIGEST_LEN); - - done: - if (d1) - crypto_free_digest_env(d1); - if (d2) - crypto_free_digest_env(d2); -} - -/** Run unit tests for our public key crypto functions */ -static void -test_crypto_pk(void) -{ - crypto_pk_env_t *pk1 = NULL, *pk2 = NULL; - char *encoded = NULL; - char data1[1024], data2[1024], data3[1024]; - size_t size; - int i, j, p, len; - - /* Public-key ciphers */ - pk1 = pk_generate(0); - pk2 = crypto_new_pk_env(); - test_assert(pk1 && pk2); - test_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size)); - test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size)); - test_eq(0, crypto_pk_cmp_keys(pk1, pk2)); - - test_eq(128, crypto_pk_keysize(pk1)); - test_eq(128, crypto_pk_keysize(pk2)); - - test_eq(128, crypto_pk_public_encrypt(pk2, data1, "Hello whirled.", 15, - PK_PKCS1_OAEP_PADDING)); - test_eq(128, crypto_pk_public_encrypt(pk1, data2, "Hello whirled.", 15, - PK_PKCS1_OAEP_PADDING)); - /* oaep padding should make encryption not match */ - test_memneq(data1, data2, 128); - test_eq(15, crypto_pk_private_decrypt(pk1, data3, data1, 128, - PK_PKCS1_OAEP_PADDING,1)); - test_streq(data3, "Hello whirled."); - memset(data3, 0, 1024); - test_eq(15, crypto_pk_private_decrypt(pk1, data3, data2, 128, - PK_PKCS1_OAEP_PADDING,1)); - test_streq(data3, "Hello whirled."); - /* Can't decrypt with public key. */ - test_eq(-1, crypto_pk_private_decrypt(pk2, data3, data2, 128, - PK_PKCS1_OAEP_PADDING,1)); - /* Try again with bad padding */ - memcpy(data2+1, "XYZZY", 5); /* This has fails ~ once-in-2^40 */ - test_eq(-1, crypto_pk_private_decrypt(pk1, data3, data2, 128, - PK_PKCS1_OAEP_PADDING,1)); - - /* File operations: save and load private key */ - test_assert(! crypto_pk_write_private_key_to_filename(pk1, - get_fname("pkey1"))); - /* failing case for read: can't read. */ - test_assert(crypto_pk_read_private_key_from_filename(pk2, - get_fname("xyzzy")) < 0); - write_str_to_file(get_fname("xyzzy"), "foobar", 6); - /* Failing case for read: no key. */ - test_assert(crypto_pk_read_private_key_from_filename(pk2, - get_fname("xyzzy")) < 0); - test_assert(! crypto_pk_read_private_key_from_filename(pk2, - get_fname("pkey1"))); - test_eq(15, crypto_pk_private_decrypt(pk2, data3, data1, 128, - PK_PKCS1_OAEP_PADDING,1)); - - /* Now try signing. */ - strlcpy(data1, "Ossifrage", 1024); - test_eq(128, crypto_pk_private_sign(pk1, data2, data1, 10)); - test_eq(10, crypto_pk_public_checksig(pk1, data3, data2, 128)); - test_streq(data3, "Ossifrage"); - /* Try signing digests. */ - test_eq(128, crypto_pk_private_sign_digest(pk1, data2, data1, 10)); - test_eq(20, crypto_pk_public_checksig(pk1, data3, data2, 128)); - test_eq(0, crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128)); - test_eq(-1, crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128)); - /*XXXX test failed signing*/ - - /* Try encoding */ - crypto_free_pk_env(pk2); - pk2 = NULL; - i = crypto_pk_asn1_encode(pk1, data1, 1024); - test_assert(i>0); - pk2 = crypto_pk_asn1_decode(data1, i); - test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); - - /* Try with hybrid encryption wrappers. */ - crypto_rand(data1, 1024); - for (i = 0; i < 3; ++i) { - for (j = 85; j < 140; ++j) { - memset(data2,0,1024); - memset(data3,0,1024); - if (i == 0 && j < 129) - continue; - p = (i==0)?PK_NO_PADDING: - (i==1)?PK_PKCS1_PADDING:PK_PKCS1_OAEP_PADDING; - len = crypto_pk_public_hybrid_encrypt(pk1,data2,data1,j,p,0); - test_assert(len>=0); - len = crypto_pk_private_hybrid_decrypt(pk1,data3,data2,len,p,1); - test_eq(len,j); - test_memeq(data1,data3,j); - } - } - - /* Try copy_full */ - crypto_free_pk_env(pk2); - pk2 = crypto_pk_copy_full(pk1); - test_assert(pk2 != NULL); - test_neq_ptr(pk1, pk2); - test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); - - done: - if (pk1) - crypto_free_pk_env(pk1); - if (pk2) - crypto_free_pk_env(pk2); - tor_free(encoded); -} - -/** Run unit tests for misc crypto functionality. */ -static void -test_crypto(void) -{ - char *data1 = NULL, *data2 = NULL, *data3 = NULL; - int i, j, idx; - - data1 = tor_malloc(1024); - data2 = tor_malloc(1024); - data3 = tor_malloc(1024); - test_assert(data1 && data2 && data3); - - /* Base64 tests */ - memset(data1, 6, 1024); - for (idx = 0; idx < 10; ++idx) { - i = base64_encode(data2, 1024, data1, idx); - test_assert(i >= 0); - j = base64_decode(data3, 1024, data2, i); - test_eq(j,idx); - test_memeq(data3, data1, idx); - } - - strlcpy(data1, "Test string that contains 35 chars.", 1024); - strlcat(data1, " 2nd string that contains 35 chars.", 1024); - - i = base64_encode(data2, 1024, data1, 71); - j = base64_decode(data3, 1024, data2, i); - test_eq(j, 71); - test_streq(data3, data1); - test_assert(data2[i] == '\0'); - - crypto_rand(data1, DIGEST_LEN); - memset(data2, 100, 1024); - digest_to_base64(data2, data1); - test_eq(BASE64_DIGEST_LEN, strlen(data2)); - test_eq(100, data2[BASE64_DIGEST_LEN+2]); - memset(data3, 99, 1024); - test_eq(digest_from_base64(data3, data2), 0); - test_memeq(data1, data3, DIGEST_LEN); - test_eq(99, data3[DIGEST_LEN+1]); - - test_assert(digest_from_base64(data3, "###") < 0); - - /* Base32 tests */ - strlcpy(data1, "5chrs", 1024); - /* bit pattern is: [35 63 68 72 73] -> - * [00110101 01100011 01101000 01110010 01110011] - * By 5s: [00110 10101 10001 10110 10000 11100 10011 10011] - */ - base32_encode(data2, 9, data1, 5); - test_streq(data2, "gvrwq4tt"); - - strlcpy(data1, "\xFF\xF5\x6D\x44\xAE\x0D\x5C\xC9\x62\xC4", 1024); - base32_encode(data2, 30, data1, 10); - test_streq(data2, "772w2rfobvomsywe"); - - /* Base16 tests */ - strlcpy(data1, "6chrs\xff", 1024); - base16_encode(data2, 13, data1, 6); - test_streq(data2, "3663687273FF"); - - strlcpy(data1, "f0d678affc000100", 1024); - i = base16_decode(data2, 8, data1, 16); - test_eq(i,0); - test_memeq(data2, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8); - - /* now try some failing base16 decodes */ - test_eq(-1, base16_decode(data2, 8, data1, 15)); /* odd input len */ - test_eq(-1, base16_decode(data2, 7, data1, 16)); /* dest too short */ - strlcpy(data1, "f0dz!8affc000100", 1024); - test_eq(-1, base16_decode(data2, 8, data1, 16)); - - tor_free(data1); - tor_free(data2); - tor_free(data3); - - /* Add spaces to fingerprint */ - { - data1 = tor_strdup("ABCD1234ABCD56780000ABCD1234ABCD56780000"); - test_eq(strlen(data1), 40); - data2 = tor_malloc(FINGERPRINT_LEN+1); - add_spaces_to_fp(data2, FINGERPRINT_LEN+1, data1); - test_streq(data2, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000"); - tor_free(data1); - tor_free(data2); - } - - /* Check fingerprint */ - { - test_assert(crypto_pk_check_fingerprint_syntax( - "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000")); - test_assert(!crypto_pk_check_fingerprint_syntax( - "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 000")); - test_assert(!crypto_pk_check_fingerprint_syntax( - "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 00000")); - test_assert(!crypto_pk_check_fingerprint_syntax( - "ABCD 1234 ABCD 5678 0000 ABCD1234 ABCD 5678 0000")); - test_assert(!crypto_pk_check_fingerprint_syntax( - "ABCD 1234 ABCD 5678 0000 ABCD1234 ABCD 5678 00000")); - test_assert(!crypto_pk_check_fingerprint_syntax( - "ACD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 00000")); - } - - done: - tor_free(data1); - tor_free(data2); - tor_free(data3); -} - -/** Run unit tests for our secret-to-key passphrase hashing functionality. */ -static void -test_crypto_s2k(void) -{ - char buf[29]; - char buf2[29]; - char *buf3 = NULL; - int i; - - memset(buf, 0, sizeof(buf)); - memset(buf2, 0, sizeof(buf2)); - buf3 = tor_malloc(65536); - memset(buf3, 0, 65536); - - secret_to_key(buf+9, 20, "", 0, buf); - crypto_digest(buf2+9, buf3, 1024); - test_memeq(buf, buf2, 29); - - memcpy(buf,"vrbacrda",8); - memcpy(buf2,"vrbacrda",8); - buf[8] = 96; - buf2[8] = 96; - secret_to_key(buf+9, 20, "12345678", 8, buf); - for (i = 0; i < 65536; i += 16) { - memcpy(buf3+i, "vrbacrda12345678", 16); - } - crypto_digest(buf2+9, buf3, 65536); - test_memeq(buf, buf2, 29); - - done: - tor_free(buf3); -} - -/** Helper: return a tristate based on comparing the strings in *<b>a</b> and - * *<b>b</b>. */ -static int -_compare_strs(const void **a, const void **b) -{ - const char *s1 = *a, *s2 = *b; - return strcmp(s1, s2); -} - -/** Helper: return a tristate based on comparing the strings in *<b>a</b> and - * *<b>b</b>, excluding a's first character, and ignoring case. */ -static int -_compare_without_first_ch(const void *a, const void **b) -{ - const char *s1 = a, *s2 = *b; - return strcasecmp(s1+1, s2); -} - -/** Test basic utility functionality. */ -static void -test_util(void) -{ - struct timeval start, end; - struct tm a_time; - char timestr[RFC1123_TIME_LEN+1]; - char buf[1024]; - time_t t_res; - int i; - uint32_t u32; - uint16_t u16; - char *cp, *k, *v; - const char *str; - - start.tv_sec = 5; - start.tv_usec = 5000; - - end.tv_sec = 5; - end.tv_usec = 5000; - - test_eq(0L, tv_udiff(&start, &end)); - - end.tv_usec = 7000; - - test_eq(2000L, tv_udiff(&start, &end)); - - end.tv_sec = 6; - - test_eq(1002000L, tv_udiff(&start, &end)); - - end.tv_usec = 0; - - test_eq(995000L, tv_udiff(&start, &end)); - - end.tv_sec = 4; - - test_eq(-1005000L, tv_udiff(&start, &end)); - - end.tv_usec = 999990; - start.tv_sec = 1; - start.tv_usec = 500; - - /* The test values here are confirmed to be correct on a platform - * with a working timegm. */ - a_time.tm_year = 2003-1900; - a_time.tm_mon = 7; - a_time.tm_mday = 30; - a_time.tm_hour = 6; - a_time.tm_min = 14; - a_time.tm_sec = 55; - test_eq((time_t) 1062224095UL, tor_timegm(&a_time)); - a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */ - test_eq((time_t) 1093846495UL, tor_timegm(&a_time)); - a_time.tm_mon = 1; /* Try a leap year, in feb. */ - a_time.tm_mday = 10; - test_eq((time_t) 1076393695UL, tor_timegm(&a_time)); - - format_rfc1123_time(timestr, 0); - test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr); - format_rfc1123_time(timestr, (time_t)1091580502UL); - test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr); - - t_res = 0; - i = parse_rfc1123_time(timestr, &t_res); - test_eq(i,0); - test_eq(t_res, (time_t)1091580502UL); - test_eq(-1, parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res)); - tor_gettimeofday(&start); - - /* Tests for corner cases of strl operations */ - test_eq(5, strlcpy(buf, "Hello", 0)); - strlcpy(buf, "Hello", sizeof(buf)); - test_eq(10, strlcat(buf, "Hello", 5)); - - /* Test tor_strstrip() */ - strlcpy(buf, "Testing 1 2 3", sizeof(buf)); - tor_strstrip(buf, ",!"); - test_streq(buf, "Testing 1 2 3"); - strlcpy(buf, "!Testing 1 2 3?", sizeof(buf)); - tor_strstrip(buf, "!? "); - test_streq(buf, "Testing123"); - - /* Test parse_addr_port */ - cp = NULL; u32 = 3; u16 = 3; - test_assert(!parse_addr_port(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_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", - &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_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_eq(cp, NULL); - test_eq(u32, 0x7f000001u); - test_eq(u16, 0); - tor_free(cp); - test_eq(0, addr_mask_get_bits(0x0u)); - test_eq(32, addr_mask_get_bits(0xFFFFFFFFu)); - test_eq(16, addr_mask_get_bits(0xFFFF0000u)); - test_eq(31, addr_mask_get_bits(0xFFFFFFFEu)); - test_eq(1, addr_mask_get_bits(0x80000000u)); - - /* Test tor_parse_long. */ - test_eq(10L, tor_parse_long("10",10,0,100,NULL,NULL)); - test_eq(0L, tor_parse_long("10",10,50,100,NULL,NULL)); - test_eq(-50L, tor_parse_long("-50",10,-100,100,NULL,NULL)); - - /* Test tor_parse_ulong */ - test_eq(10UL, tor_parse_ulong("10",10,0,100,NULL,NULL)); - test_eq(0UL, tor_parse_ulong("10",10,50,100,NULL,NULL)); - - /* Test tor_parse_uint64. */ - test_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp)); - test_assert(i == 1); - test_streq(cp, " x"); - test_assert(U64_LITERAL(12345678901) == - tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp)); - test_assert(i == 1); - test_streq(cp, ""); - test_assert(U64_LITERAL(0) == - tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp)); - test_assert(i == 0); - - /* Test failing snprintf cases */ - test_eq(-1, tor_snprintf(buf, 0, "Foo")); - test_eq(-1, tor_snprintf(buf, 2, "Foo")); - - /* Test printf with uint64 */ - tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x", - U64_PRINTF_ARG(U64_LITERAL(12345678901))); - test_streq(buf, "x!12345678901!x"); - - /* Test parse_config_line_from_str */ - strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n" - "k2\n" - "k3 \n" "\n" " \n" "#comment\n" - "k4#a\n" "k5#abc\n" "k6 val #with comment\n" - "kseven \"a quoted 'string\"\n" - "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n" - , sizeof(buf)); - str = buf; - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k"); - test_streq(v, "v"); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "key value with")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "key"); - test_streq(v, "value with spaces"); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "keykey")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "keykey"); - test_streq(v, "val"); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k2\n")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k2"); - test_streq(v, ""); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k3 \n")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k3"); - test_streq(v, ""); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "#comment")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k4"); - test_streq(v, ""); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k5#abc")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k5"); - test_streq(v, ""); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k6")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k6"); - test_streq(v, "val"); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "kseven")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "kseven"); - test_streq(v, "a quoted \'string"); - tor_free(k); tor_free(v); - test_assert(!strcmpstart(str, "k8 ")); - - str = parse_config_line_from_str(str, &k, &v); - test_streq(k, "k8"); - test_streq(v, "a quoted\n\"str\\ing\t\x01\x01\x01\""); - tor_free(k); tor_free(v); - test_streq(str, ""); - - /* Test for strcmpstart and strcmpend. */ - test_assert(strcmpstart("abcdef", "abcdef")==0); - test_assert(strcmpstart("abcdef", "abc")==0); - test_assert(strcmpstart("abcdef", "abd")<0); - test_assert(strcmpstart("abcdef", "abb")>0); - test_assert(strcmpstart("ab", "abb")<0); - - test_assert(strcmpend("abcdef", "abcdef")==0); - test_assert(strcmpend("abcdef", "def")==0); - test_assert(strcmpend("abcdef", "deg")<0); - test_assert(strcmpend("abcdef", "dee")>0); - test_assert(strcmpend("ab", "abb")<0); - - test_assert(strcasecmpend("AbcDEF", "abcdef")==0); - test_assert(strcasecmpend("abcdef", "dEF")==0); - test_assert(strcasecmpend("abcDEf", "deg")<0); - test_assert(strcasecmpend("abcdef", "DEE")>0); - test_assert(strcasecmpend("ab", "abB")<0); - - /* Test mem_is_zero */ - memset(buf,0,128); - buf[128] = 'x'; - test_assert(tor_digest_is_zero(buf)); - test_assert(tor_mem_is_zero(buf, 10)); - test_assert(tor_mem_is_zero(buf, 20)); - test_assert(tor_mem_is_zero(buf, 128)); - test_assert(!tor_mem_is_zero(buf, 129)); - buf[60] = (char)255; - test_assert(!tor_mem_is_zero(buf, 128)); - buf[0] = (char)1; - test_assert(!tor_mem_is_zero(buf, 10)); - - /* Test inet_ntop */ - { - 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)); - test_streq(tmpbuf, ip); - } - - /* Test 'escaped' */ - test_streq("\"\"", escaped("")); - test_streq("\"abcd\"", escaped("abcd")); - test_streq("\"\\\\\\n\\r\\t\\\"\\'\"", escaped("\\\n\r\t\"\'")); - test_streq("\"z\\001abc\\277d\"", escaped("z\001abc\277d")); - test_assert(NULL == escaped(NULL)); - - /* Test strndup and memdup */ - { - const char *s = "abcdefghijklmnopqrstuvwxyz"; - cp = tor_strndup(s, 30); - test_streq(cp, s); /* same string, */ - test_neq(cp, s); /* but different pointers. */ - tor_free(cp); - - cp = tor_strndup(s, 5); - test_streq(cp, "abcde"); - tor_free(cp); - - s = "a\0b\0c\0d\0e\0"; - cp = tor_memdup(s,10); - test_memeq(cp, s, 10); /* same ram, */ - test_neq(cp, s); /* but different pointers. */ - tor_free(cp); - } - - /* Test str-foo functions */ - cp = tor_strdup("abcdef"); - test_assert(tor_strisnonupper(cp)); - cp[3] = 'D'; - test_assert(!tor_strisnonupper(cp)); - tor_strupper(cp); - test_streq(cp, "ABCDEF"); - test_assert(tor_strisprint(cp)); - cp[3] = 3; - 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)); - test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2); - test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2); - haystack = "ababcad"; - test_eq_ptr(tor_memmem(haystack, 7, "abc", 3), haystack + 2); - test_eq_ptr(tor_memstr(haystack, 7, "abc"), haystack + 2); - test_assert(!tor_memstr(haystack, 7, "fe")); - test_assert(!tor_memstr(haystack, 7, "longerthantheoriginal")); - } - - /* Test wrap_string */ - { - smartlist_t *sl = smartlist_create(); - wrap_string(sl, "This is a test of string wrapping functionality: woot.", - 10, "", ""); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, - "This is a\ntest of\nstring\nwrapping\nfunctional\nity: woot.\n"); - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - wrap_string(sl, "This is a test of string wrapping functionality: woot.", - 16, "### ", "# "); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, - "### This is a\n# test of string\n# wrapping\n# functionality:\n" - "# woot.\n"); - - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_free(sl); - } - - tor_gettimeofday(&start); - /* now make sure time works. */ - tor_gettimeofday(&end); - /* We might've timewarped a little. */ - test_assert(tv_udiff(&start, &end) >= -5000); - - /* Test tor_log2(). */ - test_eq(tor_log2(64), 6); - test_eq(tor_log2(65), 6); - test_eq(tor_log2(63), 5); - test_eq(tor_log2(1), 0); - test_eq(tor_log2(2), 1); - test_eq(tor_log2(3), 1); - test_eq(tor_log2(4), 2); - test_eq(tor_log2(5), 2); - test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55); - test_eq(tor_log2(UINT64_MAX), 63); - - /* Test round_to_power_of_2 */ - test_eq(round_to_power_of_2(120), 128); - test_eq(round_to_power_of_2(128), 128); - test_eq(round_to_power_of_2(130), 128); - test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)), - U64_LITERAL(1)<<55); - test_eq(round_to_power_of_2(0), 2); - - done: - ; -} - -/** Helper: assert that IPv6 addresses <b>a</b> and <b>b</b> are the same. On - * failure, reports an error, describing the addresses as <b>e1</b> and - * <b>e2</b>, and reporting the line number as <b>line</b>. */ -static void -_test_eq_ip6(struct in6_addr *a, struct in6_addr *b, const char *e1, - const char *e2, int line) -{ - int i; - int ok = 1; - for (i = 0; i < 16; ++i) { - if (a->s6_addr[i] != b->s6_addr[i]) { - ok = 0; - break; - } - } - if (ok) { - printf("."); fflush(stdout); - } else { - char buf1[128], *cp1; - char buf2[128], *cp2; - have_failed = 1; - cp1 = buf1; cp2 = buf2; - for (i=0; i<16; ++i) { - tor_snprintf(cp1, sizeof(buf1)-(cp1-buf1), "%02x", a->s6_addr[i]); - tor_snprintf(cp2, sizeof(buf2)-(cp2-buf2), "%02x", b->s6_addr[i]); - cp1 += 2; cp2 += 2; - if ((i%2)==1 && i != 15) { - *cp1++ = ':'; - *cp2++ = ':'; - } - } - *cp1 = *cp2 = '\0'; - printf("Line %d: assertion failed: (%s == %s)\n" - " %s != %s\n", line, e1, e2, buf1, buf2); - fflush(stdout); - } -} - -/** Helper: Assert that two strings both decode as IPv6 addresses with - * tor_inet_pton(), and both decode to the same address. */ -#define test_pton6_same(a,b) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \ - test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \ - _test_eq_ip6(&a1,&a2,#a,#b,__LINE__); \ - STMT_END - -/** Helper: Assert that <b>a</b> is recognized as a bad IPv6 address by - * tor_inet_pton(). */ -#define test_pton6_bad(a) \ - test_eq(0, tor_inet_pton(AF_INET6, a, &a1)) - -/** Helper: assert that <b>a</b>, when parsed by tor_inet_pton() and displayed - * with tor_inet_ntop(), yields <b>b</b>. Also assert that <b>b</b> parses to - * the same value as <b>a</b>. */ -#define test_ntop6_reduces(a,b) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \ - test_streq(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), b); \ - test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \ - _test_eq_ip6(&a1, &a2, a, b, __LINE__); \ - STMT_END - -/** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that - * passes tor_addr_is_internal() with <b>for_listening</b>. */ -#define test_internal_ip(a,for_listening) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ - t1.family = AF_INET6; \ - if (!tor_addr_is_internal(&t1, for_listening)) \ - test_fail_msg( a "was not internal."); \ - STMT_END - -/** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that - * does not pass tor_addr_is_internal() with <b>for_listening</b>. */ -#define test_external_ip(a,for_listening) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ - t1.family = AF_INET6; \ - if (tor_addr_is_internal(&t1, for_listening)) \ - test_fail_msg(a "was not external."); \ - STMT_END - -/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by - * tor_inet_pton(), give addresses that compare in the order defined by - * <b>op</b> with tor_addr_compare(). */ -#define test_addr_compare(a, op, b) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ - test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \ - t1.family = t2.family = AF_INET6; \ - r = tor_addr_compare(&t1,&t2,CMP_SEMANTIC); \ - if (!(r op 0)) \ - test_fail_msg("failed: tor_addr_compare("a","b") "#op" 0"); \ - STMT_END - -/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by - * tor_inet_pton(), give addresses that compare in the order defined by - * <b>op</b> with tor_addr_compare_masked() with <b>m</b> masked. */ -#define test_addr_compare_masked(a, op, b, m) STMT_BEGIN \ - test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ - test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \ - t1.family = t2.family = AF_INET6; \ - r = tor_addr_compare_masked(&t1,&t2,m,CMP_SEMANTIC); \ - if (!(r op 0)) \ - test_fail_msg("failed: tor_addr_compare_masked("a","b","#m") "#op" 0"); \ - STMT_END - -/** Helper: assert that <b>xx</b> is parseable as a masked IPv6 address with - * ports by tor_parse_mask_addr_ports(), with family <b>f</b>, IP address - * as 4 32-bit words <b>ip1...ip4</b>, mask bits as <b>mm</b>, and port range - * as <b>pt1..pt2</b>. */ -#define test_addr_mask_ports_parse(xx, f, ip1, ip2, ip3, ip4, mm, pt1, pt2) \ - STMT_BEGIN \ - test_eq(tor_addr_parse_mask_ports(xx, &t1, &mask, &port1, &port2), f); \ - p1=tor_inet_ntop(AF_INET6, &t1.addr.in6_addr, bug, sizeof(bug)); \ - test_eq(htonl(ip1), tor_addr_to_in6_addr32(&t1)[0]); \ - test_eq(htonl(ip2), tor_addr_to_in6_addr32(&t1)[1]); \ - test_eq(htonl(ip3), tor_addr_to_in6_addr32(&t1)[2]); \ - test_eq(htonl(ip4), tor_addr_to_in6_addr32(&t1)[3]); \ - test_eq(mask, mm); \ - test_eq(port1, pt1); \ - test_eq(port2, pt2); \ - STMT_END - -/** Run unit tests for IPv6 encoding/decoding/manipulation functions. */ -static void -test_util_ip6_helpers(void) -{ - char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN]; - struct in6_addr a1, a2; - tor_addr_t t1, t2; - int r, i; - uint16_t port1, port2; - maskbits_t mask; - const char *p1; - struct sockaddr_storage sa_storage; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - - // struct in_addr b1, b2; - /* Test tor_inet_ntop and tor_inet_pton: IPv6 */ - - /* ==== Converting to and from sockaddr_t. */ - sin = (struct sockaddr_in *)&sa_storage; - sin->sin_family = AF_INET; - sin->sin_port = 9090; - sin->sin_addr.s_addr = htonl(0x7f7f0102); /*127.127.1.2*/ - tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL); - test_eq(tor_addr_family(&t1), AF_INET); - test_eq(tor_addr_to_ipv4h(&t1), 0x7f7f0102); - - memset(&sa_storage, 0, sizeof(sa_storage)); - test_eq(sizeof(struct sockaddr_in), - tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage, - sizeof(sa_storage))); - test_eq(1234, ntohs(sin->sin_port)); - test_eq(0x7f7f0102, ntohl(sin->sin_addr.s_addr)); - - memset(&sa_storage, 0, sizeof(sa_storage)); - sin6 = (struct sockaddr_in6 *)&sa_storage; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(7070); - sin6->sin6_addr.s6_addr[0] = 128; - tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL); - test_eq(tor_addr_family(&t1), AF_INET6); - p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0); - test_streq(p1, "8000::"); - - memset(&sa_storage, 0, sizeof(sa_storage)); - test_eq(sizeof(struct sockaddr_in6), - tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage, - sizeof(sa_storage))); - test_eq(AF_INET6, sin6->sin6_family); - test_eq(9999, ntohs(sin6->sin6_port)); - test_eq(0x80000000, ntohl(S6_ADDR32(sin6->sin6_addr)[0])); - - /* ==== tor_addr_lookup: static cases. (Can't test dns without knowing we - * have a good resolver. */ - test_eq(0, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1)); - test_eq(AF_INET, tor_addr_family(&t1)); - test_eq(tor_addr_to_ipv4h(&t1), 0x7f808182); - - test_eq(0, tor_addr_lookup("9000::5", AF_UNSPEC, &t1)); - test_eq(AF_INET6, tor_addr_family(&t1)); - test_eq(0x90, tor_addr_to_in6_addr8(&t1)[0]); - test_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14)); - test_eq(0x05, tor_addr_to_in6_addr8(&t1)[15]); - - /* === Test pton: valid af_inet6 */ - /* Simple, valid parsing. */ - r = tor_inet_pton(AF_INET6, - "0102:0304:0506:0708:090A:0B0C:0D0E:0F10", &a1); - test_assert(r==1); - for (i=0;i<16;++i) { test_eq(i+1, (int)a1.s6_addr[i]); } - /* ipv4 ending. */ - test_pton6_same("0102:0304:0506:0708:090A:0B0C:0D0E:0F10", - "0102:0304:0506:0708:090A:0B0C:13.14.15.16"); - /* shortened words. */ - test_pton6_same("0001:0099:BEEF:0000:0123:FFFF:0001:0001", - "1:99:BEEF:0:0123:FFFF:1:1"); - /* zeros at the beginning */ - test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001", - "::9:c0a8:1:1"); - test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001", - "::9:c0a8:0.1.0.1"); - /* zeros in the middle. */ - test_pton6_same("fe80:0000:0000:0000:0202:1111:0001:0001", - "fe80::202:1111:1:1"); - /* zeros at the end. */ - test_pton6_same("1000:0001:0000:0007:0000:0000:0000:0000", - "1000:1:0:7::"); - - /* === Test ntop: af_inet6 */ - test_ntop6_reduces("0:0:0:0:0:0:0:0", "::"); - - test_ntop6_reduces("0001:0099:BEEF:0006:0123:FFFF:0001:0001", - "1:99:beef:6:123:ffff:1:1"); - - //test_ntop6_reduces("0:0:0:0:0:0:c0a8:0101", "::192.168.1.1"); - test_ntop6_reduces("0:0:0:0:0:ffff:c0a8:0101", "::ffff:192.168.1.1"); - test_ntop6_reduces("002:0:0000:0:3::4", "2::3:0:0:4"); - test_ntop6_reduces("0:0::1:0:3", "::1:0:3"); - test_ntop6_reduces("008:0::0", "8::"); - test_ntop6_reduces("0:0:0:0:0:ffff::1", "::ffff:0.0.0.1"); - test_ntop6_reduces("abcd:0:0:0:0:0:7f00::", "abcd::7f00:0"); - test_ntop6_reduces("0000:0000:0000:0000:0009:C0A8:0001:0001", - "::9:c0a8:1:1"); - test_ntop6_reduces("fe80:0000:0000:0000:0202:1111:0001:0001", - "fe80::202:1111:1:1"); - test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000", - "1000:1:0:7::"); - - /* === Test pton: invalid in6. */ - test_pton6_bad("foobar."); - test_pton6_bad("55555::"); - test_pton6_bad("9:-60::"); - 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"); - test_pton6_bad("1:2:3:4:5:6:1.2.3.4.5"); - 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("99"); - test_pton6_bad(""); - test_pton6_bad("1::2::3:4"); - test_pton6_bad("a:::b:c"); - test_pton6_bad(":::a:b:c"); - test_pton6_bad("a:b:c:::"); - - /* test internal checking */ - test_external_ip("fbff:ffff::2:7", 0); - test_internal_ip("fc01::2:7", 0); - test_internal_ip("fdff:ffff::f:f", 0); - test_external_ip("fe00::3:f", 0); - - test_external_ip("fe7f:ffff::2:7", 0); - test_internal_ip("fe80::2:7", 0); - test_internal_ip("febf:ffff::f:f", 0); - - test_internal_ip("fec0::2:7:7", 0); - test_internal_ip("feff:ffff::e:7:7", 0); - test_external_ip("ff00::e:7:7", 0); - - test_internal_ip("::", 0); - test_internal_ip("::1", 0); - test_internal_ip("::1", 1); - test_internal_ip("::", 0); - test_external_ip("::", 1); - test_external_ip("::2", 0); - test_external_ip("2001::", 0); - test_external_ip("ffff::", 0); - - test_external_ip("::ffff:0.0.0.0", 1); - test_internal_ip("::ffff:0.0.0.0", 0); - test_internal_ip("::ffff:0.255.255.255", 0); - test_external_ip("::ffff:1.0.0.0", 0); - - test_external_ip("::ffff:9.255.255.255", 0); - test_internal_ip("::ffff:10.0.0.0", 0); - test_internal_ip("::ffff:10.255.255.255", 0); - test_external_ip("::ffff:11.0.0.0", 0); - - test_external_ip("::ffff:126.255.255.255", 0); - test_internal_ip("::ffff:127.0.0.0", 0); - test_internal_ip("::ffff:127.255.255.255", 0); - test_external_ip("::ffff:128.0.0.0", 0); - - test_external_ip("::ffff:172.15.255.255", 0); - test_internal_ip("::ffff:172.16.0.0", 0); - test_internal_ip("::ffff:172.31.255.255", 0); - test_external_ip("::ffff:172.32.0.0", 0); - - test_external_ip("::ffff:192.167.255.255", 0); - test_internal_ip("::ffff:192.168.0.0", 0); - test_internal_ip("::ffff:192.168.255.255", 0); - test_external_ip("::ffff:192.169.0.0", 0); - - test_external_ip("::ffff:169.253.255.255", 0); - test_internal_ip("::ffff:169.254.0.0", 0); - test_internal_ip("::ffff:169.254.255.255", 0); - test_external_ip("::ffff:169.255.0.0", 0); - test_assert(is_internal_IP(0x7f000001, 0)); - - /* tor_addr_compare(tor_addr_t x2) */ - test_addr_compare("ffff::", ==, "ffff::0"); - test_addr_compare("0::3:2:1", <, "0::ffff:0.3.2.1"); - test_addr_compare("0::2:2:1", <, "0::ffff:0.3.2.1"); - test_addr_compare("0::ffff:0.3.2.1", >, "0::0:0:0"); - test_addr_compare("0::ffff:5.2.2.1", <, "::ffff:6.0.0.0"); /* XXXX wrong. */ - tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", &t1, NULL, NULL, NULL); - tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL); - test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0); - tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", &t1, NULL, NULL, NULL); - tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL); - test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0); - - /* test compare_masked */ - test_addr_compare_masked("ffff::", ==, "ffff::0", 128); - test_addr_compare_masked("ffff::", ==, "ffff::0", 64); - 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]")); - 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")); - 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_eq(0, i); - i = tor_addr_parse_reverse_lookup_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", - 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); - test_eq(0, i); - i = tor_addr_parse_reverse_lookup_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, - "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", - AF_UNSPEC, 0); - test_eq(1, i); - 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, - "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, - "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, - "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", - AF_UNSPEC, 0); - test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_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", - AF_UNSPEC, 0); - test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_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, - "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_parse_mask_ports */ - test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6, - 0, 0, 0, 0x0000000f, 17, 47, 95); - //test_addr_parse("[::fefe:4.1.1.7/120]:999-1000"); - //test_addr_parse_check("::fefe:401:107", 120, 999, 1000); - test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6, - 0, 0, 0x0000ffff, 0x04010107, 120, 443, 443); - test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6, - 0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000); - - r=tor_addr_parse_mask_ports("[fefef::]/112", &t1, NULL, NULL, NULL); - test_assert(r == -1); - r=tor_addr_parse_mask_ports("efef::/112", &t1, NULL, NULL, NULL); - test_assert(r == -1); - r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]", &t1, NULL, NULL, NULL); - test_assert(r == -1); - r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL); - test_assert(r == -1); - r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL); - test_assert(r == -1); - /* Test for V4-mapped address with mask < 96. (arguably not valid) */ - r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]", &t1, &mask, NULL, NULL); - test_assert(r == -1); - r=tor_addr_parse_mask_ports("1.1.2.2/33", &t1, &mask, NULL, NULL); - test_assert(r == -1); - r=tor_addr_parse_mask_ports("1.1.2.2/31", &t1, &mask, NULL, NULL); - test_assert(r == AF_INET); - r=tor_addr_parse_mask_ports("[efef::]/112", &t1, &mask, &port1, &port2); - test_assert(r == AF_INET6); - test_assert(port1 == 1); - test_assert(port2 == 65535); - - /* make sure inet address lengths >= max */ - test_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255")); - test_assert(TOR_ADDR_BUF_LEN >= - sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")); - - test_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr)); - - /* get interface addresses */ - r = get_interface_address6(LOG_DEBUG, AF_INET, &t1); - i = get_interface_address6(LOG_DEBUG, AF_INET6, &t2); -#if 0 - tor_inet_ntop(AF_INET, &t1.sa.sin_addr, buf, sizeof(buf)); - printf("\nv4 address: %s (family=%i)", buf, IN_FAMILY(&t1)); - tor_inet_ntop(AF_INET6, &t2.sa6.sin6_addr, buf, sizeof(buf)); - printf("\nv6 address: %s (family=%i)", buf, IN_FAMILY(&t2)); -#endif - - done: - ; -} - -/** Run unit tests for basic dynamic-sized array functionality. */ -static void -test_util_smartlist_basic(void) -{ - smartlist_t *sl; - - /* XXXX test sort_digests, uniq_strings, uniq_digests */ - - /* Test smartlist add, del_keeporder, insert, get. */ - sl = smartlist_create(); - smartlist_add(sl, (void*)1); - smartlist_add(sl, (void*)2); - smartlist_add(sl, (void*)3); - smartlist_add(sl, (void*)4); - smartlist_del_keeporder(sl, 1); - smartlist_insert(sl, 1, (void*)22); - smartlist_insert(sl, 0, (void*)0); - smartlist_insert(sl, 5, (void*)555); - test_eq_ptr((void*)0, smartlist_get(sl,0)); - test_eq_ptr((void*)1, smartlist_get(sl,1)); - test_eq_ptr((void*)22, smartlist_get(sl,2)); - test_eq_ptr((void*)3, smartlist_get(sl,3)); - test_eq_ptr((void*)4, smartlist_get(sl,4)); - test_eq_ptr((void*)555, smartlist_get(sl,5)); - /* Try deleting in the middle. */ - smartlist_del(sl, 1); - test_eq_ptr((void*)555, smartlist_get(sl, 1)); - /* Try deleting at the end. */ - smartlist_del(sl, 4); - test_eq(4, smartlist_len(sl)); - - /* test isin. */ - test_assert(smartlist_isin(sl, (void*)3)); - test_assert(!smartlist_isin(sl, (void*)99)); - - done: - smartlist_free(sl); -} - -/** Run unit tests for smartlist-of-strings functionality. */ -static void -test_util_smartlist_strings(void) -{ - smartlist_t *sl = smartlist_create(); - char *cp=NULL, *cp_alloc=NULL; - size_t sz; - - /* Test split and join */ - test_eq(0, smartlist_len(sl)); - smartlist_split_string(sl, "abc", ":", 0, 0); - test_eq(1, smartlist_len(sl)); - test_streq("abc", smartlist_get(sl, 0)); - smartlist_split_string(sl, "a::bc::", "::", 0, 0); - test_eq(4, smartlist_len(sl)); - test_streq("a", smartlist_get(sl, 1)); - test_streq("bc", smartlist_get(sl, 2)); - test_streq("", smartlist_get(sl, 3)); - cp_alloc = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp_alloc, "abcabc"); - tor_free(cp_alloc); - cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); - test_streq(cp_alloc, "abc!a!bc!"); - tor_free(cp_alloc); - cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); - test_streq(cp_alloc, "abcXYaXYbcXY"); - tor_free(cp_alloc); - cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); - test_streq(cp_alloc, "abcXYaXYbcXYXY"); - tor_free(cp_alloc); - cp_alloc = smartlist_join_strings(sl, "", 1, NULL); - test_streq(cp_alloc, "abcabc"); - tor_free(cp_alloc); - - smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); - test_eq(8, smartlist_len(sl)); - test_streq("", smartlist_get(sl, 4)); - test_streq("def", smartlist_get(sl, 5)); - test_streq(" ", smartlist_get(sl, 6)); - test_streq("ghijk", smartlist_get(sl, 7)); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); - test_eq(3, smartlist_len(sl)); - test_streq("a", smartlist_get(sl,0)); - test_streq("bbd", smartlist_get(sl,1)); - test_streq("cdef", smartlist_get(sl,2)); - smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", - SPLIT_SKIP_SPACE, 0); - test_eq(8, smartlist_len(sl)); - test_streq("z", smartlist_get(sl,3)); - test_streq("zhasd", smartlist_get(sl,4)); - test_streq("", smartlist_get(sl,5)); - test_streq("bnud", smartlist_get(sl,6)); - test_streq("", smartlist_get(sl,7)); - - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - smartlist_split_string(sl, " ab\tc \td ef ", NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(4, smartlist_len(sl)); - test_streq("ab", smartlist_get(sl,0)); - test_streq("c", smartlist_get(sl,1)); - test_streq("d", smartlist_get(sl,2)); - test_streq("ef", smartlist_get(sl,3)); - smartlist_split_string(sl, "ghi\tj", NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(6, smartlist_len(sl)); - test_streq("ghi", smartlist_get(sl,4)); - test_streq("j", smartlist_get(sl,5)); - - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); - test_streq(cp_alloc, ""); - tor_free(cp_alloc); - cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); - test_streq(cp_alloc, "XY"); - tor_free(cp_alloc); - - smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(3, smartlist_len(sl)); - test_streq("z", smartlist_get(sl, 0)); - test_streq("zhasd", smartlist_get(sl, 1)); - test_streq("bnud", smartlist_get(sl, 2)); - smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); - test_eq(5, smartlist_len(sl)); - test_streq("z", smartlist_get(sl, 3)); - test_streq("zhasd <> <> bnud<>", smartlist_get(sl, 4)); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - smartlist_split_string(sl, "abcd\n", "\n", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(1, smartlist_len(sl)); - test_streq("abcd", smartlist_get(sl, 0)); - smartlist_split_string(sl, "efgh", "\n", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - test_eq(2, smartlist_len(sl)); - test_streq("efgh", smartlist_get(sl, 1)); - - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - /* Test swapping, shuffling, and sorting. */ - smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); - test_eq(7, smartlist_len(sl)); - smartlist_sort(sl, _compare_strs); - cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc,"and,arma,by,nickm,onion,router,the"); - tor_free(cp_alloc); - smartlist_swap(sl, 1, 5); - cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc,"and,router,by,nickm,onion,arma,the"); - tor_free(cp_alloc); - smartlist_shuffle(sl); - test_eq(7, smartlist_len(sl)); - test_assert(smartlist_string_isin(sl, "and")); - test_assert(smartlist_string_isin(sl, "router")); - test_assert(smartlist_string_isin(sl, "by")); - test_assert(smartlist_string_isin(sl, "nickm")); - test_assert(smartlist_string_isin(sl, "onion")); - test_assert(smartlist_string_isin(sl, "arma")); - test_assert(smartlist_string_isin(sl, "the")); - - /* Test bsearch. */ - smartlist_sort(sl, _compare_strs); - test_streq("nickm", smartlist_bsearch(sl, "zNicKM", - _compare_without_first_ch)); - test_streq("and", smartlist_bsearch(sl, " AND", _compare_without_first_ch)); - test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", _compare_without_first_ch)); - - /* Test bsearch_idx */ - { - int f; - test_eq(0, smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f)); - test_eq(f, 0); - test_eq(0, smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f)); - test_eq(f, 1); - test_eq(1, smartlist_bsearch_idx(sl," arm",_compare_without_first_ch,&f)); - test_eq(f, 0); - test_eq(1, smartlist_bsearch_idx(sl," arma",_compare_without_first_ch,&f)); - test_eq(f, 1); - test_eq(2, smartlist_bsearch_idx(sl," armb",_compare_without_first_ch,&f)); - test_eq(f, 0); - test_eq(7, smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f)); - test_eq(f, 0); - } - - /* Test reverse() and pop_last() */ - smartlist_reverse(sl); - cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc,"the,router,onion,nickm,by,arma,and"); - tor_free(cp_alloc); - cp_alloc = smartlist_pop_last(sl); - test_streq(cp_alloc, "and"); - tor_free(cp_alloc); - test_eq(smartlist_len(sl), 6); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - cp_alloc = smartlist_pop_last(sl); - test_eq(cp_alloc, NULL); - - /* Test uniq() */ - smartlist_split_string(sl, - "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50", - ",", 0, 0); - smartlist_sort(sl, _compare_strs); - smartlist_uniq(sl, _compare_strs, _tor_free); - cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc, "50,a,canal,man,noon,panama,plan,radar"); - tor_free(cp_alloc); - - /* Test string_isin and isin_case and num_isin */ - test_assert(smartlist_string_isin(sl, "noon")); - test_assert(!smartlist_string_isin(sl, "noonoon")); - test_assert(smartlist_string_isin_case(sl, "nOOn")); - test_assert(!smartlist_string_isin_case(sl, "nooNooN")); - test_assert(smartlist_string_num_isin(sl, 50)); - test_assert(!smartlist_string_num_isin(sl, 60)); - - /* Test smartlist_choose */ - { - int i; - int allsame = 1; - int allin = 1; - void *first = smartlist_choose(sl); - test_assert(smartlist_isin(sl, first)); - for (i = 0; i < 100; ++i) { - void *second = smartlist_choose(sl); - if (second != first) - allsame = 0; - if (!smartlist_isin(sl, second)) - allin = 0; - } - test_assert(!allsame); - test_assert(allin); - } - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - /* Test string_remove and remove and join_strings2 */ - smartlist_split_string(sl, - "Some say the Earth will end in ice and some in fire", - " ", 0, 0); - cp = smartlist_get(sl, 4); - test_streq(cp, "will"); - smartlist_add(sl, cp); - smartlist_remove(sl, cp); - tor_free(cp); - cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); - test_streq(cp_alloc, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); - tor_free(cp_alloc); - smartlist_string_remove(sl, "in"); - cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); - test_streq(cp_alloc, "Some+say+the+Earth+fire+end+some+ice+and"); - test_eq((int)sz, 40); - - done: - - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_free(sl); - tor_free(cp_alloc); -} - -/** Run unit tests for smartlist set manipulation functions. */ -static void -test_util_smartlist_overlap(void) -{ - smartlist_t *sl = smartlist_create(); - smartlist_t *ints = smartlist_create(); - smartlist_t *odds = smartlist_create(); - smartlist_t *evens = smartlist_create(); - smartlist_t *primes = smartlist_create(); - int i; - for (i=1; i < 10; i += 2) - smartlist_add(odds, (void*)(uintptr_t)i); - for (i=0; i < 10; i += 2) - smartlist_add(evens, (void*)(uintptr_t)i); - - /* add_all */ - smartlist_add_all(ints, odds); - smartlist_add_all(ints, evens); - test_eq(smartlist_len(ints), 10); - - smartlist_add(primes, (void*)2); - smartlist_add(primes, (void*)3); - smartlist_add(primes, (void*)5); - smartlist_add(primes, (void*)7); - - /* overlap */ - test_assert(smartlist_overlap(ints, odds)); - test_assert(smartlist_overlap(odds, primes)); - test_assert(smartlist_overlap(evens, primes)); - test_assert(!smartlist_overlap(odds, evens)); - - /* intersect */ - smartlist_add_all(sl, odds); - smartlist_intersect(sl, primes); - test_eq(smartlist_len(sl), 3); - test_assert(smartlist_isin(sl, (void*)3)); - test_assert(smartlist_isin(sl, (void*)5)); - test_assert(smartlist_isin(sl, (void*)7)); - - /* subtract */ - smartlist_add_all(sl, primes); - smartlist_subtract(sl, odds); - test_eq(smartlist_len(sl), 1); - test_assert(smartlist_isin(sl, (void*)2)); - - done: - smartlist_free(odds); - smartlist_free(evens); - smartlist_free(ints); - smartlist_free(primes); - smartlist_free(sl); -} - -/** Run unit tests for smartlist-of-digests functions. */ -static void -test_util_smartlist_digests(void) -{ - smartlist_t *sl = smartlist_create(); - - /* digest_isin. */ - smartlist_add(sl, tor_memdup("AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN)); - smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); - smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); - test_eq(0, smartlist_digest_isin(NULL, "AAAAAAAAAAAAAAAAAAAA")); - test_assert(smartlist_digest_isin(sl, "AAAAAAAAAAAAAAAAAAAA")); - test_assert(smartlist_digest_isin(sl, "\00090AAB2AAAAaasdAAAAA")); - test_eq(0, smartlist_digest_isin(sl, "\00090AAB2AAABaasdAAAAA")); - - /* sort digests */ - smartlist_sort_digests(sl); - test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); - test_memeq(smartlist_get(sl, 1), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); - test_memeq(smartlist_get(sl, 2), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); - test_eq(3, smartlist_len(sl)); - - /* uniq_digests */ - smartlist_uniq_digests(sl); - test_eq(2, smartlist_len(sl)); - test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); - test_memeq(smartlist_get(sl, 1), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); - - done: - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_free(sl); -} - -/** Run unit tests for concatenate-a-smartlist-of-strings functions. */ -static void -test_util_smartlist_join(void) -{ - smartlist_t *sl = smartlist_create(); - smartlist_t *sl2 = smartlist_create(), *sl3 = smartlist_create(), - *sl4 = smartlist_create(); - char *joined=NULL; - /* unique, sorted. */ - smartlist_split_string(sl, - "Abashments Ambush Anchorman Bacon Banks Borscht " - "Bunks Inhumane Insurance Knish Know Manners " - "Maraschinos Stamina Sunbonnets Unicorns Wombats", - " ", 0, 0); - /* non-unique, sorted. */ - smartlist_split_string(sl2, - "Ambush Anchorman Anchorman Anemias Anemias Bacon " - "Crossbowmen Inhumane Insurance Knish Know Manners " - "Manners Maraschinos Wombats Wombats Work", - " ", 0, 0); - SMARTLIST_FOREACH_JOIN(sl, char *, cp1, - sl2, char *, cp2, - strcmp(cp1,cp2), - smartlist_add(sl3, cp2)) { - test_streq(cp1, cp2); - smartlist_add(sl4, cp1); - } SMARTLIST_FOREACH_JOIN_END(cp1, cp2); - - SMARTLIST_FOREACH(sl3, const char *, cp, - test_assert(smartlist_isin(sl2, cp) && - !smartlist_string_isin(sl, cp))); - SMARTLIST_FOREACH(sl4, const char *, cp, - test_assert(smartlist_isin(sl, cp) && - smartlist_string_isin(sl2, cp))); - joined = smartlist_join_strings(sl3, ",", 0, NULL); - test_streq(joined, "Anemias,Anemias,Crossbowmen,Work"); - tor_free(joined); - joined = smartlist_join_strings(sl4, ",", 0, NULL); - test_streq(joined, "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance," - "Knish,Know,Manners,Manners,Maraschinos,Wombats,Wombats"); - tor_free(joined); - - done: - smartlist_free(sl4); - smartlist_free(sl3); - SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); - smartlist_free(sl2); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_free(sl); - tor_free(joined); -} - -/** Run unit tests for bitarray code */ -static void -test_util_bitarray(void) -{ - bitarray_t *ba = NULL; - int i, j, ok=1; - - ba = bitarray_init_zero(1); - test_assert(ba); - test_assert(! bitarray_is_set(ba, 0)); - bitarray_set(ba, 0); - test_assert(bitarray_is_set(ba, 0)); - bitarray_clear(ba, 0); - test_assert(! bitarray_is_set(ba, 0)); - bitarray_free(ba); - - ba = bitarray_init_zero(1023); - for (i = 1; i < 64; ) { - for (j = 0; j < 1023; ++j) { - if (j % i) - bitarray_set(ba, j); - else - bitarray_clear(ba, j); - } - for (j = 0; j < 1023; ++j) { - if (!bool_eq(bitarray_is_set(ba, j), j%i)) - ok = 0; - } - test_assert(ok); - if (i < 7) - ++i; - else if (i == 28) - i = 32; - else - i += 7; - } - - done: - if (ba) - bitarray_free(ba); -} - -/** Run unit tests for digest set code (implemented as a hashtable or as a - * bloom filter) */ -static void -test_util_digestset(void) -{ - smartlist_t *included = smartlist_create(); - char d[DIGEST_LEN]; - int i; - int ok = 1; - int false_positives = 0; - digestset_t *set = NULL; - - for (i = 0; i < 1000; ++i) { - crypto_rand(d, DIGEST_LEN); - smartlist_add(included, tor_memdup(d, DIGEST_LEN)); - } - set = digestset_new(1000); - SMARTLIST_FOREACH(included, const char *, cp, - if (digestset_isin(set, cp)) - ok = 0); - test_assert(ok); - SMARTLIST_FOREACH(included, const char *, cp, - digestset_add(set, cp)); - SMARTLIST_FOREACH(included, const char *, cp, - if (!digestset_isin(set, cp)) - ok = 0); - test_assert(ok); - for (i = 0; i < 1000; ++i) { - crypto_rand(d, DIGEST_LEN); - if (digestset_isin(set, d)) - ++false_positives; - } - test_assert(false_positives < 50); /* Should be far lower. */ - - done: - if (set) - digestset_free(set); - SMARTLIST_FOREACH(included, char *, cp, tor_free(cp)); - smartlist_free(included); -} - -/** mutex for thread test to stop the threads hitting data at the same time. */ -static tor_mutex_t *_thread_test_mutex = NULL; -/** mutexes for the thread test to make sure that the threads have to - * interleave somewhat. */ -static tor_mutex_t *_thread_test_start1 = NULL, - *_thread_test_start2 = NULL; -/** Shared strmap for the thread test. */ -static strmap_t *_thread_test_strmap = NULL; -/** The name of thread1 for the thread test */ -static char *_thread1_name = NULL; -/** The name of thread2 for the thread test */ -static char *_thread2_name = NULL; - -static void _thread_test_func(void* _s) ATTR_NORETURN; - -/** How many iterations have the threads in the unit test run? */ -static int t1_count = 0, t2_count = 0; - -/** Helper function for threading unit tests: This function runs in a - * subthread. It grabs its own mutex (start1 or start2) to make sure that it - * should start, then it repeatedly alters _test_thread_strmap protected by - * _thread_test_mutex. */ -static void -_thread_test_func(void* _s) -{ - char *s = _s; - int i, *count; - tor_mutex_t *m; - char buf[64]; - char **cp; - if (!strcmp(s, "thread 1")) { - m = _thread_test_start1; - cp = &_thread1_name; - count = &t1_count; - } else { - m = _thread_test_start2; - cp = &_thread2_name; - count = &t2_count; - } - tor_mutex_acquire(m); - - tor_snprintf(buf, sizeof(buf), "%lu", tor_get_thread_id()); - *cp = tor_strdup(buf); - - for (i=0; i<10000; ++i) { - tor_mutex_acquire(_thread_test_mutex); - strmap_set(_thread_test_strmap, "last to run", *cp); - ++*count; - tor_mutex_release(_thread_test_mutex); - } - tor_mutex_acquire(_thread_test_mutex); - strmap_set(_thread_test_strmap, s, *cp); - tor_mutex_release(_thread_test_mutex); - - tor_mutex_release(m); - - spawn_exit(); -} - -/** Run unit tests for threading logic. */ -static void -test_util_threads(void) -{ - char *s1 = NULL, *s2 = NULL; - int done = 0, timedout = 0; - time_t started; -#ifndef MS_WINDOWS - struct timeval tv; - tv.tv_sec=0; - tv.tv_usec=10; -#endif -#ifndef TOR_IS_MULTITHREADED - /* Skip this test if we aren't threading. We should be threading most - * everywhere by now. */ - if (1) - return; -#endif - _thread_test_mutex = tor_mutex_new(); - _thread_test_start1 = tor_mutex_new(); - _thread_test_start2 = tor_mutex_new(); - _thread_test_strmap = strmap_new(); - s1 = tor_strdup("thread 1"); - s2 = tor_strdup("thread 2"); - tor_mutex_acquire(_thread_test_start1); - tor_mutex_acquire(_thread_test_start2); - spawn_func(_thread_test_func, s1); - spawn_func(_thread_test_func, s2); - tor_mutex_release(_thread_test_start2); - tor_mutex_release(_thread_test_start1); - started = time(NULL); - while (!done) { - tor_mutex_acquire(_thread_test_mutex); - strmap_assert_ok(_thread_test_strmap); - if (strmap_get(_thread_test_strmap, "thread 1") && - strmap_get(_thread_test_strmap, "thread 2")) { - done = 1; - } else if (time(NULL) > started + 25) { - timedout = done = 1; - } - tor_mutex_release(_thread_test_mutex); -#ifndef MS_WINDOWS - /* Prevent the main thread from starving the worker threads. */ - select(0, NULL, NULL, NULL, &tv); -#endif - } - - tor_mutex_acquire(_thread_test_start1); - tor_mutex_release(_thread_test_start1); - tor_mutex_acquire(_thread_test_start2); - tor_mutex_release(_thread_test_start2); - - tor_mutex_free(_thread_test_mutex); - - if (timedout) { - printf("\nTimed out: %d %d", t1_count, t2_count); - test_assert(strmap_get(_thread_test_strmap, "thread 1")); - test_assert(strmap_get(_thread_test_strmap, "thread 2")); - test_assert(!timedout); - } - - /* different thread IDs. */ - test_assert(strcmp(strmap_get(_thread_test_strmap, "thread 1"), - strmap_get(_thread_test_strmap, "thread 2"))); - test_assert(!strcmp(strmap_get(_thread_test_strmap, "thread 1"), - strmap_get(_thread_test_strmap, "last to run")) || - !strcmp(strmap_get(_thread_test_strmap, "thread 2"), - strmap_get(_thread_test_strmap, "last to run"))); - - done: - tor_free(s1); - tor_free(s2); - tor_free(_thread1_name); - tor_free(_thread2_name); - if (_thread_test_strmap) - strmap_free(_thread_test_strmap, NULL); - if (_thread_test_start1) - tor_mutex_free(_thread_test_start1); - if (_thread_test_start2) - tor_mutex_free(_thread_test_start2); -} - -/** Helper: return a tristate based on comparing two strings. */ -static int -_compare_strings_for_pqueue(const void *s1, const void *s2) -{ - return strcmp((const char*)s1, (const char*)s2); -} - -/** Run unit tests for heap-based priority queue functions. */ -static void -test_util_pqueue(void) -{ - smartlist_t *sl = smartlist_create(); - int (*cmp)(const void *, const void*); -#define OK() smartlist_pqueue_assert_ok(sl, cmp) - - cmp = _compare_strings_for_pqueue; - - smartlist_pqueue_add(sl, cmp, (char*)"cows"); - smartlist_pqueue_add(sl, cmp, (char*)"zebras"); - smartlist_pqueue_add(sl, cmp, (char*)"fish"); - smartlist_pqueue_add(sl, cmp, (char*)"frogs"); - smartlist_pqueue_add(sl, cmp, (char*)"apples"); - smartlist_pqueue_add(sl, cmp, (char*)"squid"); - smartlist_pqueue_add(sl, cmp, (char*)"daschunds"); - smartlist_pqueue_add(sl, cmp, (char*)"eggplants"); - smartlist_pqueue_add(sl, cmp, (char*)"weissbier"); - smartlist_pqueue_add(sl, cmp, (char*)"lobsters"); - smartlist_pqueue_add(sl, cmp, (char*)"roquefort"); - - OK(); - - test_eq(smartlist_len(sl), 11); - test_streq(smartlist_get(sl, 0), "apples"); - test_streq(smartlist_pqueue_pop(sl, cmp), "apples"); - test_eq(smartlist_len(sl), 10); - OK(); - test_streq(smartlist_pqueue_pop(sl, cmp), "cows"); - test_streq(smartlist_pqueue_pop(sl, cmp), "daschunds"); - smartlist_pqueue_add(sl, cmp, (char*)"chinchillas"); - OK(); - smartlist_pqueue_add(sl, cmp, (char*)"fireflies"); - OK(); - test_streq(smartlist_pqueue_pop(sl, cmp), "chinchillas"); - test_streq(smartlist_pqueue_pop(sl, cmp), "eggplants"); - test_streq(smartlist_pqueue_pop(sl, cmp), "fireflies"); - OK(); - test_streq(smartlist_pqueue_pop(sl, cmp), "fish"); - test_streq(smartlist_pqueue_pop(sl, cmp), "frogs"); - test_streq(smartlist_pqueue_pop(sl, cmp), "lobsters"); - test_streq(smartlist_pqueue_pop(sl, cmp), "roquefort"); - OK(); - test_eq(smartlist_len(sl), 3); - test_streq(smartlist_pqueue_pop(sl, cmp), "squid"); - test_streq(smartlist_pqueue_pop(sl, cmp), "weissbier"); - test_streq(smartlist_pqueue_pop(sl, cmp), "zebras"); - test_eq(smartlist_len(sl), 0); - OK(); -#undef OK - - done: - - smartlist_free(sl); -} - -/** Run unit tests for compression functions */ -static void -test_util_gzip(void) -{ - char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2; - const char *ccp2; - size_t len1, len2; - tor_zlib_state_t *state = NULL; - - buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ"); - test_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD); - if (is_gzip_supported()) { - test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, - GZIP_METHOD)); - test_assert(buf2); - test_assert(!memcmp(buf2, "\037\213", 2)); /* Gzip magic. */ - test_assert(detect_compression_method(buf2, len1) == GZIP_METHOD); - - test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, - GZIP_METHOD, 1, LOG_INFO)); - test_assert(buf3); - test_streq(buf1,buf3); - - tor_free(buf2); - tor_free(buf3); - } - - test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, - ZLIB_METHOD)); - test_assert(buf2); - test_assert(!memcmp(buf2, "\x78\xDA", 2)); /* deflate magic. */ - test_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD); - - test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, - ZLIB_METHOD, 1, LOG_INFO)); - test_assert(buf3); - test_streq(buf1,buf3); - - /* Check whether we can uncompress concatenated, compressed strings. */ - tor_free(buf3); - buf2 = tor_realloc(buf2, len1*2); - memcpy(buf2+len1, buf2, len1); - test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2, - ZLIB_METHOD, 1, LOG_INFO)); - test_eq(len2, (strlen(buf1)+1)*2); - test_memeq(buf3, - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0", - (strlen(buf1)+1)*2); - - tor_free(buf1); - tor_free(buf2); - tor_free(buf3); - - /* Check whether we can uncompress partial strings. */ - buf1 = - 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); - /* when we allow an incomplete string, we should succeed.*/ - tor_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)); - - /* when we demand a complete string, this must fail. */ - tor_free(buf3); - tor_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16, - ZLIB_METHOD, 1, LOG_INFO)); - tor_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); - cp1 = buf1 = tor_malloc(1024); - len1 = 1024; - ccp2 = "ABCDEFGHIJABCDEFGHIJ"; - len2 = 21; - test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0) - == TOR_ZLIB_OK); - test_eq(len2, 0); /* Make sure we compressed it all. */ - test_assert(cp1 > buf1); - - len2 = 0; - cp2 = cp1; - test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1) - == TOR_ZLIB_DONE); - test_eq(len2, 0); - test_assert(cp1 > cp2); /* Make sure we really added something. */ - - tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1, - ZLIB_METHOD, 1, LOG_WARN)); - test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/ - - done: - if (state) - tor_zlib_free(state); - tor_free(buf2); - tor_free(buf3); - tor_free(buf1); -} - -/** Run unit tests for string-to-void* map functions */ -static void -test_util_strmap(void) -{ - strmap_t *map; - strmap_iter_t *iter; - const char *k; - void *v; - char *visited = NULL; - smartlist_t *found_keys = NULL; - - map = strmap_new(); - test_assert(map); - test_eq(strmap_size(map), 0); - test_assert(strmap_isempty(map)); - v = strmap_set(map, "K1", (void*)99); - test_eq(v, NULL); - test_assert(!strmap_isempty(map)); - v = strmap_set(map, "K2", (void*)101); - test_eq(v, NULL); - v = strmap_set(map, "K1", (void*)100); - test_eq(v, (void*)99); - test_eq_ptr(strmap_get(map,"K1"), (void*)100); - test_eq_ptr(strmap_get(map,"K2"), (void*)101); - test_eq_ptr(strmap_get(map,"K-not-there"), NULL); - strmap_assert_ok(map); - - v = strmap_remove(map,"K2"); - strmap_assert_ok(map); - test_eq_ptr(v, (void*)101); - test_eq_ptr(strmap_get(map,"K2"), NULL); - test_eq_ptr(strmap_remove(map,"K2"), NULL); - - strmap_set(map, "K2", (void*)101); - strmap_set(map, "K3", (void*)102); - strmap_set(map, "K4", (void*)103); - test_eq(strmap_size(map), 4); - strmap_assert_ok(map); - strmap_set(map, "K5", (void*)104); - strmap_set(map, "K6", (void*)105); - strmap_assert_ok(map); - - /* Test iterator. */ - iter = strmap_iter_init(map); - found_keys = smartlist_create(); - while (!strmap_iter_done(iter)) { - strmap_iter_get(iter,&k,&v); - smartlist_add(found_keys, tor_strdup(k)); - test_eq_ptr(v, strmap_get(map, k)); - - if (!strcmp(k, "K2")) { - iter = strmap_iter_next_rmv(map,iter); - } else { - iter = strmap_iter_next(map,iter); - } - } - - /* Make sure we removed K2, but not the others. */ - test_eq_ptr(strmap_get(map, "K2"), NULL); - test_eq_ptr(strmap_get(map, "K5"), (void*)104); - /* Make sure we visited everyone once */ - smartlist_sort_strings(found_keys); - visited = smartlist_join_strings(found_keys, ":", 0, NULL); - test_streq(visited, "K1:K2:K3:K4:K5:K6"); - - strmap_assert_ok(map); - /* Clean up after ourselves. */ - strmap_free(map, NULL); - map = NULL; - - /* Now try some lc functions. */ - map = strmap_new(); - strmap_set_lc(map,"Ab.C", (void*)1); - test_eq_ptr(strmap_get(map,"ab.c"), (void*)1); - strmap_assert_ok(map); - test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1); - test_eq_ptr(strmap_get(map,"AB.C"), NULL); - test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1); - strmap_assert_ok(map); - test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL); - - done: - if (map) - strmap_free(map,NULL); - if (found_keys) { - SMARTLIST_FOREACH(found_keys, char *, cp, tor_free(cp)); - smartlist_free(found_keys); - } - tor_free(visited); -} - -/** Run unit tests for mmap() wrapper functionality. */ -static void -test_util_mmap(void) -{ - char *fname1 = tor_strdup(get_fname("mapped_1")); - char *fname2 = tor_strdup(get_fname("mapped_2")); - char *fname3 = tor_strdup(get_fname("mapped_3")); - const size_t buflen = 17000; - char *buf = tor_malloc(17000); - tor_mmap_t *mapping = NULL; - - crypto_rand(buf, buflen); - - mapping = tor_mmap_file(fname1); - test_assert(! mapping); - - write_str_to_file(fname1, "Short file.", 1); - write_bytes_to_file(fname2, buf, buflen, 1); - write_bytes_to_file(fname3, buf, 16384, 1); - - mapping = tor_mmap_file(fname1); - test_assert(mapping); - test_eq(mapping->size, strlen("Short file.")); - test_streq(mapping->data, "Short file."); -#ifdef MS_WINDOWS - tor_munmap_file(mapping); - mapping = NULL; - test_assert(unlink(fname1) == 0); -#else - /* make sure we can unlink. */ - test_assert(unlink(fname1) == 0); - test_streq(mapping->data, "Short file."); - tor_munmap_file(mapping); - mapping = NULL; -#endif - - /* Now a zero-length file. */ - write_str_to_file(fname1, "", 1); - mapping = tor_mmap_file(fname1); - test_eq(mapping, NULL); - test_eq(ERANGE, errno); - unlink(fname1); - - /* Make sure that we fail to map a no-longer-existent file. */ - mapping = tor_mmap_file(fname1); - test_assert(mapping == NULL); - - /* Now try a big file that stretches across a few pages and isn't aligned */ - mapping = tor_mmap_file(fname2); - test_assert(mapping); - test_eq(mapping->size, buflen); - test_memeq(mapping->data, buf, buflen); - tor_munmap_file(mapping); - mapping = NULL; - - /* Now try a big aligned file. */ - mapping = tor_mmap_file(fname3); - test_assert(mapping); - test_eq(mapping->size, 16384); - test_memeq(mapping->data, buf, 16384); - tor_munmap_file(mapping); - mapping = NULL; - - done: - unlink(fname1); - unlink(fname2); - unlink(fname3); - - tor_free(fname1); - tor_free(fname2); - tor_free(fname3); - tor_free(buf); - - if (mapping) - tor_munmap_file(mapping); -} - -/** Run unit tests for escaping/unescaping data for use by controllers. */ -static void -test_util_control_formats(void) -{ - char *out = NULL; - const char *inp = - "..This is a test\r\nof the emergency \nbroadcast\r\n..system.\r\nZ.\r\n"; - size_t sz; - - sz = read_escaped_data(inp, strlen(inp), &out); - test_streq(out, - ".This is a test\nof the emergency \nbroadcast\n.system.\nZ.\n"); - test_eq(sz, strlen(out)); - - done: - tor_free(out); -} - -static void -test_util_sscanf(void) -{ - unsigned u1, u2, u3; - char s1[10], s2[10], s3[10], ch; - int r; - - r = tor_sscanf("hello world", "hello world"); /* String match: success */ - test_eq(r, 0); - r = tor_sscanf("hello world 3", "hello worlb %u", &u1); /* String fail */ - test_eq(r, 0); - r = tor_sscanf("12345", "%u", &u1); /* Simple number */ - test_eq(r, 1); - test_eq(u1, 12345u); - r = tor_sscanf("", "%u", &u1); /* absent number */ - test_eq(r, 0); - r = tor_sscanf("A", "%u", &u1); /* bogus number */ - test_eq(r, 0); - r = tor_sscanf("4294967295", "%u", &u1); /* UINT32_MAX should work. */ - test_eq(r, 1); - test_eq(u1, 4294967295u); - r = tor_sscanf("4294967296", "%u", &u1); /* Always say -1 at 32 bits. */ - test_eq(r, 0); - r = tor_sscanf("123456", "%2u%u", &u1, &u2); /* Width */ - test_eq(r, 2); - test_eq(u1, 12u); - test_eq(u2, 3456u); - r = tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3); /* separators */ - test_eq(r, 3); - test_eq(u1, 12u); - test_eq(u2, 3u); - test_eq(u3, 456u); - r = tor_sscanf("12:3:045", "%2u:%2u:%3u", &u1, &u2, &u3); /* 0s */ - test_eq(r, 3); - test_eq(u1, 12u); - test_eq(u2, 3u); - test_eq(u3, 45u); - /* %u does not match space.*/ - r = tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3); - test_eq(r, 2); - /* %u does not match negative numbers. */ - r = tor_sscanf("12:3:-4", "%2u:%2u:%3u", &u1, &u2, &u3); - test_eq(r, 2); - /* Arbitrary amounts of 0-padding are okay */ - r = tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u", &u1, &u2, &u3); - test_eq(r, 3); - test_eq(u1, 12u); - test_eq(u2, 3u); - test_eq(u3, 99u); - - r = tor_sscanf("99% fresh", "%3u%% fresh", &u1); /* percents are scannable.*/ - test_eq(r, 1); - test_eq(u1, 99); - - r = tor_sscanf("hello", "%s", s1); /* %s needs a number. */ - test_eq(r, -1); - - r = tor_sscanf("hello", "%3s%7s", s1, s2); /* %s matches characters. */ - test_eq(r, 2); - test_streq(s1, "hel"); - test_streq(s2, "lo"); - r = tor_sscanf("WD40", "%2s%u", s3, &u1); /* %s%u */ - test_eq(r, 2); - test_streq(s3, "WD"); - test_eq(u1, 40); - r = tor_sscanf("76trombones", "%6u%9s", &u1, s1); /* %u%s */ - test_eq(r, 2); - test_eq(u1, 76); - test_streq(s1, "trombones"); - r = tor_sscanf("hello world", "%9s %9s", s1, s2); /* %s doesn't eat space. */ - test_eq(r, 2); - test_streq(s1, "hello"); - test_streq(s2, "world"); - r = tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3); /* %s can be empty. */ - test_eq(r, 3); - test_streq(s1, "hi"); - test_streq(s2, ""); - test_streq(s3, ""); - - r = tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch); - test_eq(r, 3); - r = tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch); - test_eq(r, 4); - - done: - ; -} - -/** Run unit tests for the onion handshake code. */ -static void -test_onion_handshake(void) -{ - /* client-side */ - crypto_dh_env_t *c_dh = NULL; - char c_buf[ONIONSKIN_CHALLENGE_LEN]; - char c_keys[40]; - - /* server-side */ - char s_buf[ONIONSKIN_REPLY_LEN]; - char s_keys[40]; - - /* shared */ - crypto_pk_env_t *pk = NULL; - - pk = pk_generate(0); - - /* client handshake 1. */ - memset(c_buf, 0, ONIONSKIN_CHALLENGE_LEN); - test_assert(! onion_skin_create(pk, &c_dh, c_buf)); - - /* server handshake */ - memset(s_buf, 0, ONIONSKIN_REPLY_LEN); - memset(s_keys, 0, 40); - test_assert(! onion_skin_server_handshake(c_buf, pk, NULL, - s_buf, s_keys, 40)); - - /* client handshake 2 */ - memset(c_keys, 0, 40); - test_assert(! onion_skin_client_handshake(c_dh, s_buf, c_keys, 40)); - - if (memcmp(c_keys, s_keys, 40)) { - puts("Aiiiie"); - exit(1); - } - test_memeq(c_keys, s_keys, 40); - memset(s_buf, 0, 40); - test_memneq(c_keys, s_buf, 40); - - done: - if (c_dh) - crypto_dh_free(c_dh); - if (pk) - crypto_free_pk_env(pk); -} - -/** Run unit tests for router descriptor generation logic. */ -static void -test_dir_format(void) -{ - char buf[8192], buf2[8192]; - char platform[256]; - char fingerprint[FINGERPRINT_LEN+1]; - char *pk1_str = NULL, *pk2_str = NULL, *pk3_str = NULL, *cp; - size_t pk1_str_len, pk2_str_len, pk3_str_len; - routerinfo_t *r1=NULL, *r2=NULL; - crypto_pk_env_t *pk1 = NULL, *pk2 = NULL, *pk3 = NULL; - routerinfo_t *rp1 = NULL; - addr_policy_t *ex1, *ex2; - routerlist_t *dir1 = NULL, *dir2 = NULL; - tor_version_t ver1; - - pk1 = pk_generate(0); - pk2 = pk_generate(1); - pk3 = pk_generate(2); - - test_assert( is_legal_nickname("a")); - test_assert(!is_legal_nickname("")); - test_assert(!is_legal_nickname("abcdefghijklmnopqrst")); /* 20 chars */ - test_assert(!is_legal_nickname("hyphen-")); /* bad char */ - test_assert( is_legal_nickname("abcdefghijklmnopqrs")); /* 19 chars */ - test_assert(!is_legal_nickname("$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA")); - /* valid */ - test_assert( is_legal_nickname_or_hexdigest( - "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA")); - test_assert( is_legal_nickname_or_hexdigest( - "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA=fred")); - test_assert( is_legal_nickname_or_hexdigest( - "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA~fred")); - /* too short */ - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); - /* illegal char */ - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); - /* hex part too long */ - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=fred")); - /* Bad nickname */ - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")); - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~")); - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~hyphen-")); - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~" - "abcdefghijklmnoppqrst")); - /* Bad extra char. */ - test_assert(!is_legal_nickname_or_hexdigest( - "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!")); - test_assert(is_legal_nickname_or_hexdigest("xyzzy")); - test_assert(is_legal_nickname_or_hexdigest("abcdefghijklmnopqrs")); - test_assert(!is_legal_nickname_or_hexdigest("abcdefghijklmnopqrst")); - - get_platform_str(platform, sizeof(platform)); - r1 = tor_malloc_zero(sizeof(routerinfo_t)); - r1->address = tor_strdup("18.244.0.1"); - r1->addr = 0xc0a80001u; /* 192.168.0.1 */ - r1->cache_info.published_on = 0; - r1->or_port = 9000; - r1->dir_port = 9003; - r1->onion_pkey = crypto_pk_dup_key(pk1); - r1->identity_pkey = crypto_pk_dup_key(pk2); - r1->bandwidthrate = 1000; - r1->bandwidthburst = 5000; - r1->bandwidthcapacity = 10000; - r1->exit_policy = NULL; - r1->nickname = tor_strdup("Magri"); - r1->platform = tor_strdup(platform); - - ex1 = tor_malloc_zero(sizeof(addr_policy_t)); - ex2 = tor_malloc_zero(sizeof(addr_policy_t)); - ex1->policy_type = ADDR_POLICY_ACCEPT; - tor_addr_from_ipv4h(&ex1->addr, 0); - ex1->maskbits = 0; - ex1->prt_min = ex1->prt_max = 80; - ex2->policy_type = ADDR_POLICY_REJECT; - tor_addr_from_ipv4h(&ex2->addr, 18<<24); - ex2->maskbits = 8; - ex2->prt_min = ex2->prt_max = 24; - r2 = tor_malloc_zero(sizeof(routerinfo_t)); - r2->address = tor_strdup("1.1.1.1"); - r2->addr = 0x0a030201u; /* 10.3.2.1 */ - r2->platform = tor_strdup(platform); - r2->cache_info.published_on = 5; - r2->or_port = 9005; - r2->dir_port = 0; - r2->onion_pkey = crypto_pk_dup_key(pk2); - r2->identity_pkey = crypto_pk_dup_key(pk1); - r2->bandwidthrate = r2->bandwidthburst = r2->bandwidthcapacity = 3000; - r2->exit_policy = smartlist_create(); - smartlist_add(r2->exit_policy, ex2); - smartlist_add(r2->exit_policy, ex1); - r2->nickname = tor_strdup("Fred"); - - test_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str, - &pk1_str_len)); - test_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str, - &pk2_str_len)); - test_assert(!crypto_pk_write_public_key_to_string(pk3 , &pk3_str, - &pk3_str_len)); - - memset(buf, 0, 2048); - test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0); - - strlcpy(buf2, "router Magri 18.244.0.1 9000 0 9003\n" - "platform Tor "VERSION" on ", sizeof(buf2)); - strlcat(buf2, get_uname(), sizeof(buf2)); - strlcat(buf2, "\n" - "opt protocols Link 1 2 Circuit 1\n" - "published 1970-01-01 00:00:00\n" - "opt fingerprint ", sizeof(buf2)); - test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1)); - strlcat(buf2, fingerprint, sizeof(buf2)); - strlcat(buf2, "\nuptime 0\n" - /* XXX the "0" above is hard-coded, but even if we made it reflect - * uptime, that still wouldn't make it right, because the two - * descriptors might be made on different seconds... hm. */ - "bandwidth 1000 5000 10000\n" - "opt extra-info-digest 0000000000000000000000000000000000000000\n" - "onion-key\n", sizeof(buf2)); - strlcat(buf2, pk1_str, sizeof(buf2)); - strlcat(buf2, "signing-key\n", sizeof(buf2)); - strlcat(buf2, pk2_str, sizeof(buf2)); - strlcat(buf2, "opt hidden-service-dir\n", sizeof(buf2)); - strlcat(buf2, "reject *:*\nrouter-signature\n", sizeof(buf2)); - buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same - * twice */ - - test_streq(buf, buf2); - - test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0); - cp = buf; - rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); - test_assert(rp1); - test_streq(rp1->address, r1->address); - test_eq(rp1->or_port, r1->or_port); - //test_eq(rp1->dir_port, r1->dir_port); - test_eq(rp1->bandwidthrate, r1->bandwidthrate); - test_eq(rp1->bandwidthburst, r1->bandwidthburst); - test_eq(rp1->bandwidthcapacity, r1->bandwidthcapacity); - test_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0); - test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0); - //test_assert(rp1->exit_policy == NULL); - -#if 0 - /* XXX Once we have exit policies, test this again. XXX */ - strlcpy(buf2, "router tor.tor.tor 9005 0 0 3000\n", sizeof(buf2)); - strlcat(buf2, pk2_str, sizeof(buf2)); - strlcat(buf2, "signing-key\n", sizeof(buf2)); - strlcat(buf2, pk1_str, sizeof(buf2)); - strlcat(buf2, "accept *:80\nreject 18.*:24\n\n", sizeof(buf2)); - test_assert(router_dump_router_to_string(buf, 2048, &r2, pk2)>0); - test_streq(buf, buf2); - - cp = buf; - rp2 = router_parse_entry_from_string(&cp,1); - test_assert(rp2); - test_streq(rp2->address, r2.address); - test_eq(rp2->or_port, r2.or_port); - test_eq(rp2->dir_port, r2.dir_port); - test_eq(rp2->bandwidth, r2.bandwidth); - test_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0); - test_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0); - test_eq(rp2->exit_policy->policy_type, EXIT_POLICY_ACCEPT); - test_streq(rp2->exit_policy->string, "accept *:80"); - test_streq(rp2->exit_policy->address, "*"); - test_streq(rp2->exit_policy->port, "80"); - test_eq(rp2->exit_policy->next->policy_type, EXIT_POLICY_REJECT); - test_streq(rp2->exit_policy->next->string, "reject 18.*:24"); - test_streq(rp2->exit_policy->next->address, "18.*"); - test_streq(rp2->exit_policy->next->port, "24"); - test_assert(rp2->exit_policy->next->next == NULL); - - /* Okay, now for the directories. */ - { - fingerprint_list = smartlist_create(); - crypto_pk_get_fingerprint(pk2, buf, 1); - add_fingerprint_to_dir("Magri", buf, fingerprint_list); - crypto_pk_get_fingerprint(pk1, buf, 1); - add_fingerprint_to_dir("Fred", buf, fingerprint_list); - } - - { - char d[DIGEST_LEN]; - const char *m; - /* XXXX NM re-enable. */ - /* Make sure routers aren't too far in the past any more. */ - r1->cache_info.published_on = time(NULL); - r2->cache_info.published_on = time(NULL)-3*60*60; - test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0); - test_eq(dirserv_add_descriptor(buf,&m,""), ROUTER_ADDED_NOTIFY_GENERATOR); - test_assert(router_dump_router_to_string(buf, 2048, r2, pk1)>0); - test_eq(dirserv_add_descriptor(buf,&m,""), ROUTER_ADDED_NOTIFY_GENERATOR); - get_options()->Nickname = tor_strdup("DirServer"); - test_assert(!dirserv_dump_directory_to_string(&cp,pk3, 0)); - crypto_pk_get_digest(pk3, d); - test_assert(!router_parse_directory(cp)); - test_eq(2, smartlist_len(dir1->routers)); - tor_free(cp); - } -#endif - dirserv_free_fingerprint_list(); - - /* Try out version parsing functionality */ - test_eq(0, tor_version_parse("0.3.4pre2-cvs", &ver1)); - test_eq(0, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_PRE, ver1.status); - test_eq(2, ver1.patchlevel); - test_eq(0, tor_version_parse("0.3.4rc1", &ver1)); - test_eq(0, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_RC, ver1.status); - test_eq(1, ver1.patchlevel); - test_eq(0, tor_version_parse("1.3.4", &ver1)); - test_eq(1, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_RELEASE, ver1.status); - test_eq(0, ver1.patchlevel); - test_eq(0, tor_version_parse("1.3.4.999", &ver1)); - test_eq(1, ver1.major); - test_eq(3, ver1.minor); - test_eq(4, ver1.micro); - test_eq(VER_RELEASE, ver1.status); - test_eq(999, ver1.patchlevel); - test_eq(0, tor_version_parse("0.1.2.4-alpha", &ver1)); - test_eq(0, ver1.major); - test_eq(1, ver1.minor); - test_eq(2, ver1.micro); - test_eq(4, ver1.patchlevel); - test_eq(VER_RELEASE, ver1.status); - test_streq("alpha", ver1.status_tag); - test_eq(0, tor_version_parse("0.1.2.4", &ver1)); - test_eq(0, ver1.major); - test_eq(1, ver1.minor); - test_eq(2, ver1.micro); - test_eq(4, ver1.patchlevel); - test_eq(VER_RELEASE, ver1.status); - test_streq("", ver1.status_tag); - -#define test_eq_vs(vs1, vs2) test_eq_type(version_status_t, "%d", (vs1), (vs2)) -#define test_v_i_o(val, ver, lst) \ - test_eq_vs(val, tor_version_is_obsolete(ver, lst)) - - /* make sure tor_version_is_obsolete() works */ - test_v_i_o(VS_OLD, "0.0.1", "Tor 0.0.2"); - test_v_i_o(VS_OLD, "0.0.1", "0.0.2, Tor 0.0.3"); - test_v_i_o(VS_OLD, "0.0.1", "0.0.2,Tor 0.0.3"); - test_v_i_o(VS_OLD, "0.0.1","0.0.3,BetterTor 0.0.1"); - test_v_i_o(VS_RECOMMENDED, "0.0.2", "Tor 0.0.2,Tor 0.0.3"); - test_v_i_o(VS_NEW_IN_SERIES, "0.0.2", "Tor 0.0.2pre1,Tor 0.0.3"); - test_v_i_o(VS_OLD, "0.0.2", "Tor 0.0.2.1,Tor 0.0.3"); - test_v_i_o(VS_NEW, "0.1.0", "Tor 0.0.2,Tor 0.0.3"); - test_v_i_o(VS_RECOMMENDED, "0.0.7rc2", "0.0.7,Tor 0.0.7rc2,Tor 0.0.8"); - test_v_i_o(VS_OLD, "0.0.5.0", "0.0.5.1-cvs"); - test_v_i_o(VS_NEW_IN_SERIES, "0.0.5.1-cvs", "0.0.5, 0.0.6"); - /* Not on list, but newer than any in same series. */ - test_v_i_o(VS_NEW_IN_SERIES, "0.1.0.3", - "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); - /* Series newer than any on list. */ - test_v_i_o(VS_NEW, "0.1.2.3", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); - /* Series older than any on list. */ - test_v_i_o(VS_OLD, "0.0.1.3", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); - /* Not on list, not newer than any on same series. */ - test_v_i_o(VS_UNRECOMMENDED, "0.1.0.1", - "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); - /* On list, not newer than any on same series. */ - test_v_i_o(VS_UNRECOMMENDED, - "0.1.0.1", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); - test_eq(0, tor_version_as_new_as("Tor 0.0.5", "0.0.9pre1-cvs")); - test_eq(1, tor_version_as_new_as( - "Tor 0.0.8 on Darwin 64-121-192-100.c3-0." - "sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh", - "0.0.8rc2")); - test_eq(0, tor_version_as_new_as( - "Tor 0.0.8 on Darwin 64-121-192-100.c3-0." - "sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh", "0.0.8.2")); - - /* Now try svn revisions. */ - test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", - "Tor 0.2.1.0-dev (r99)")); - test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100) on Banana Jr", - "Tor 0.2.1.0-dev (r99) on Hal 9000")); - test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", - "Tor 0.2.1.0-dev on Colossus")); - test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99)", - "Tor 0.2.1.0-dev (r100)")); - test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99) on MCP", - "Tor 0.2.1.0-dev (r100) on AM")); - test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev", - "Tor 0.2.1.0-dev (r99)")); - test_eq(1, tor_version_as_new_as("Tor 0.2.1.1", - "Tor 0.2.1.0-dev (r99)")); - done: - if (r1) - routerinfo_free(r1); - if (r2) - routerinfo_free(r2); - - tor_free(pk1_str); - tor_free(pk2_str); - tor_free(pk3_str); - if (pk1) crypto_free_pk_env(pk1); - if (pk2) crypto_free_pk_env(pk2); - if (pk3) crypto_free_pk_env(pk3); - if (rp1) routerinfo_free(rp1); - tor_free(dir1); /* XXXX And more !*/ - tor_free(dir2); /* And more !*/ -} - -/** Run unit tests for misc directory functions. */ -static void -test_dirutil(void) -{ - smartlist_t *sl = smartlist_create(); - fp_pair_t *pair; - - dir_split_resource_into_fingerprint_pairs( - /* Two pairs, out of order, with one duplicate. */ - "73656372657420646174612E0000000000FFFFFF-" - "557365204145532d32353620696e73746561642e+" - "73656372657420646174612E0000000000FFFFFF-" - "557365204145532d32353620696e73746561642e+" - "48657861646563696d616c2069736e277420736f-" - "676f6f6420666f7220686964696e6720796f7572.z", sl); - - test_eq(smartlist_len(sl), 2); - pair = smartlist_get(sl, 0); - test_memeq(pair->first, "Hexadecimal isn't so", DIGEST_LEN); - test_memeq(pair->second, "good for hiding your", DIGEST_LEN); - pair = smartlist_get(sl, 1); - test_memeq(pair->first, "secret data.\0\0\0\0\0\xff\xff\xff", DIGEST_LEN); - test_memeq(pair->second, "Use AES-256 instead.", DIGEST_LEN); - - done: - SMARTLIST_FOREACH(sl, fp_pair_t *, pair, tor_free(pair)); - smartlist_free(sl); -} - -extern const char AUTHORITY_CERT_1[]; -extern const char AUTHORITY_SIGNKEY_1[]; -extern const char AUTHORITY_CERT_2[]; -extern const char AUTHORITY_SIGNKEY_2[]; -extern const char AUTHORITY_CERT_3[]; -extern const char AUTHORITY_SIGNKEY_3[]; - -/** Helper: Test that two networkstatus_voter_info_t do in fact represent the - * same voting authority, and that they do in fact have all the same - * information. */ -static void -test_same_voter(networkstatus_voter_info_t *v1, - networkstatus_voter_info_t *v2) -{ - test_streq(v1->nickname, v2->nickname); - test_memeq(v1->identity_digest, v2->identity_digest, DIGEST_LEN); - test_streq(v1->address, v2->address); - test_eq(v1->addr, v2->addr); - test_eq(v1->dir_port, v2->dir_port); - test_eq(v1->or_port, v2->or_port); - test_streq(v1->contact, v2->contact); - test_memeq(v1->vote_digest, v2->vote_digest, DIGEST_LEN); - done: - ; -} - -/** Run unit tests for getting the median of a list. */ -static void -test_util_order_functions(void) -{ - int lst[25], n = 0; - // int a=12,b=24,c=25,d=60,e=77; - -#define median() median_int(lst, n) - - lst[n++] = 12; - test_eq(12, median()); /* 12 */ - lst[n++] = 77; - //smartlist_shuffle(sl); - test_eq(12, median()); /* 12, 77 */ - lst[n++] = 77; - //smartlist_shuffle(sl); - test_eq(77, median()); /* 12, 77, 77 */ - lst[n++] = 24; - test_eq(24, median()); /* 12,24,77,77 */ - lst[n++] = 60; - lst[n++] = 12; - lst[n++] = 25; - //smartlist_shuffle(sl); - test_eq(25, median()); /* 12,12,24,25,60,77,77 */ -#undef median - - done: - ; -} - -/** Helper: Make a new routerinfo containing the right information for a - * given vote_routerstatus_t. */ -static routerinfo_t * -generate_ri_from_rs(const vote_routerstatus_t *vrs) -{ - routerinfo_t *r; - const routerstatus_t *rs = &vrs->status; - static time_t published = 0; - - r = tor_malloc_zero(sizeof(routerinfo_t)); - memcpy(r->cache_info.identity_digest, rs->identity_digest, DIGEST_LEN); - memcpy(r->cache_info.signed_descriptor_digest, rs->descriptor_digest, - DIGEST_LEN); - r->cache_info.do_not_cache = 1; - r->cache_info.routerlist_index = -1; - r->cache_info.signed_descriptor_body = - tor_strdup("123456789012345678901234567890123"); - r->cache_info.signed_descriptor_len = - strlen(r->cache_info.signed_descriptor_body); - r->exit_policy = smartlist_create(); - r->cache_info.published_on = ++published + time(NULL); - return r; -} - -/** Run unit tests for generating and parsing V3 consensus networkstatus - * documents. */ -static void -test_v3_networkstatus(void) -{ - authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL; - crypto_pk_env_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL; - crypto_pk_env_t *sign_skey_leg1=NULL; - const char *msg=NULL; - - time_t now = time(NULL); - networkstatus_voter_info_t *voter; - networkstatus_t *vote=NULL, *v1=NULL, *v2=NULL, *v3=NULL, *con=NULL; - vote_routerstatus_t *vrs; - routerstatus_t *rs; - char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL, *cp; - smartlist_t *votes = smartlist_create(); - - /* For generating the two other consensuses. */ - char *detached_text1=NULL, *detached_text2=NULL; - char *consensus_text2=NULL, *consensus_text3=NULL; - networkstatus_t *con2=NULL, *con3=NULL; - ns_detached_signatures_t *dsig1=NULL, *dsig2=NULL; - - /* Parse certificates and keys. */ - cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL); - test_assert(cert1); - test_assert(cert1->is_cross_certified); - cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL); - test_assert(cert2); - cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL); - test_assert(cert3); - sign_skey_1 = crypto_new_pk_env(); - sign_skey_2 = crypto_new_pk_env(); - sign_skey_3 = crypto_new_pk_env(); - sign_skey_leg1 = pk_generate(4); - - test_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, - AUTHORITY_SIGNKEY_1)); - test_assert(!crypto_pk_read_private_key_from_string(sign_skey_2, - AUTHORITY_SIGNKEY_2)); - test_assert(!crypto_pk_read_private_key_from_string(sign_skey_3, - AUTHORITY_SIGNKEY_3)); - - test_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key)); - test_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key)); - - /* - * Set up a vote; generate it; try to parse it. - */ - vote = tor_malloc_zero(sizeof(networkstatus_t)); - vote->type = NS_TYPE_VOTE; - vote->published = now; - vote->valid_after = now+1000; - vote->fresh_until = now+2000; - vote->valid_until = now+3000; - vote->vote_seconds = 100; - vote->dist_seconds = 200; - vote->supported_methods = smartlist_create(); - smartlist_split_string(vote->supported_methods, "1 2 3", NULL, 0, -1); - vote->client_versions = tor_strdup("0.1.2.14,0.1.2.15"); - vote->server_versions = tor_strdup("0.1.2.14,0.1.2.15,0.1.2.16"); - vote->known_flags = smartlist_create(); - smartlist_split_string(vote->known_flags, - "Authority Exit Fast Guard Running Stable V2Dir Valid", - 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - vote->voters = smartlist_create(); - voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t)); - voter->nickname = tor_strdup("Voter1"); - voter->address = tor_strdup("1.2.3.4"); - voter->addr = 0x01020304; - voter->dir_port = 80; - voter->or_port = 9000; - voter->contact = tor_strdup("voter@example.com"); - crypto_pk_get_digest(cert1->identity_key, voter->identity_digest); - smartlist_add(vote->voters, voter); - vote->cert = authority_cert_dup(cert1); - vote->routerstatus_list = smartlist_create(); - /* add the first routerstatus. */ - vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); - rs = &vrs->status; - vrs->version = tor_strdup("0.1.2.14"); - rs->published_on = now-1500; - strlcpy(rs->nickname, "router2", sizeof(rs->nickname)); - memset(rs->identity_digest, 3, DIGEST_LEN); - memset(rs->descriptor_digest, 78, DIGEST_LEN); - rs->addr = 0x99008801; - rs->or_port = 443; - rs->dir_port = 8000; - /* all flags but running cleared */ - rs->is_running = 1; - smartlist_add(vote->routerstatus_list, vrs); - test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); - - /* add the second routerstatus. */ - vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); - rs = &vrs->status; - vrs->version = tor_strdup("0.2.0.5"); - rs->published_on = now-1000; - strlcpy(rs->nickname, "router1", sizeof(rs->nickname)); - memset(rs->identity_digest, 5, DIGEST_LEN); - memset(rs->descriptor_digest, 77, DIGEST_LEN); - 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_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); - - /* add the third routerstatus. */ - vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); - rs = &vrs->status; - vrs->version = tor_strdup("0.1.0.3"); - rs->published_on = now-1000; - strlcpy(rs->nickname, "router3", sizeof(rs->nickname)); - memset(rs->identity_digest, 33, DIGEST_LEN); - memset(rs->descriptor_digest, 79, DIGEST_LEN); - rs->addr = 0xAA009901; - 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; - smartlist_add(vote->routerstatus_list, vrs); - test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); - - /* add a fourth routerstatus that is not running. */ - vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); - rs = &vrs->status; - vrs->version = tor_strdup("0.1.6.3"); - rs->published_on = now-1000; - strlcpy(rs->nickname, "router4", sizeof(rs->nickname)); - memset(rs->identity_digest, 34, DIGEST_LEN); - memset(rs->descriptor_digest, 48, DIGEST_LEN); - rs->addr = 0xC0000203; - rs->or_port = 500; - rs->dir_port = 1999; - /* Running flag (and others) cleared */ - smartlist_add(vote->routerstatus_list, vrs); - test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); - - /* dump the vote and try to parse it. */ - v1_text = format_networkstatus_vote(sign_skey_1, vote); - test_assert(v1_text); - v1 = networkstatus_parse_vote_from_string(v1_text, NULL, NS_TYPE_VOTE); - test_assert(v1); - - /* Make sure the parsed thing was right. */ - test_eq(v1->type, NS_TYPE_VOTE); - test_eq(v1->published, vote->published); - test_eq(v1->valid_after, vote->valid_after); - test_eq(v1->fresh_until, vote->fresh_until); - test_eq(v1->valid_until, vote->valid_until); - test_eq(v1->vote_seconds, vote->vote_seconds); - test_eq(v1->dist_seconds, vote->dist_seconds); - test_streq(v1->client_versions, vote->client_versions); - test_streq(v1->server_versions, vote->server_versions); - test_assert(v1->voters && smartlist_len(v1->voters)); - voter = smartlist_get(v1->voters, 0); - test_streq(voter->nickname, "Voter1"); - test_streq(voter->address, "1.2.3.4"); - test_eq(voter->addr, 0x01020304); - test_eq(voter->dir_port, 80); - test_eq(voter->or_port, 9000); - test_streq(voter->contact, "voter@example.com"); - test_assert(v1->cert); - test_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key)); - cp = smartlist_join_strings(v1->known_flags, ":", 0, NULL); - test_streq(cp, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid"); - tor_free(cp); - test_eq(smartlist_len(v1->routerstatus_list), 4); - /* Check the first routerstatus. */ - vrs = smartlist_get(v1->routerstatus_list, 0); - rs = &vrs->status; - test_streq(vrs->version, "0.1.2.14"); - test_eq(rs->published_on, now-1500); - test_streq(rs->nickname, "router2"); - test_memeq(rs->identity_digest, - "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", - DIGEST_LEN); - test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); - test_eq(rs->addr, 0x99008801); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 8000); - test_eq(vrs->flags, U64_LITERAL(16)); // no flags except "running" - /* Check the second routerstatus. */ - vrs = smartlist_get(v1->routerstatus_list, 1); - rs = &vrs->status; - test_streq(vrs->version, "0.2.0.5"); - test_eq(rs->published_on, now-1000); - test_streq(rs->nickname, "router1"); - test_memeq(rs->identity_digest, - "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", - DIGEST_LEN); - test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); - test_eq(rs->addr, 0x99009901); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 0); - test_eq(vrs->flags, U64_LITERAL(254)); // all flags except "authority." - - /* Generate second vote. It disagrees on some of the times, - * and doesn't list versions, and knows some crazy flags */ - vote->published = now+1; - vote->fresh_until = now+3005; - vote->dist_seconds = 300; - authority_cert_free(vote->cert); - vote->cert = authority_cert_dup(cert2); - tor_free(vote->client_versions); - tor_free(vote->server_versions); - voter = smartlist_get(vote->voters, 0); - tor_free(voter->nickname); - tor_free(voter->address); - voter->nickname = tor_strdup("Voter2"); - voter->address = tor_strdup("2.3.4.5"); - voter->addr = 0x02030405; - crypto_pk_get_digest(cert2->identity_key, voter->identity_digest); - smartlist_add(vote->known_flags, tor_strdup("MadeOfCheese")); - smartlist_add(vote->known_flags, tor_strdup("MadeOfTin")); - smartlist_sort_strings(vote->known_flags); - vrs = smartlist_get(vote->routerstatus_list, 2); - smartlist_del_keeporder(vote->routerstatus_list, 2); - tor_free(vrs->version); - tor_free(vrs); - vrs = smartlist_get(vote->routerstatus_list, 0); - vrs->status.is_fast = 1; - /* generate and parse. */ - v2_text = format_networkstatus_vote(sign_skey_2, vote); - test_assert(v2_text); - v2 = networkstatus_parse_vote_from_string(v2_text, NULL, NS_TYPE_VOTE); - test_assert(v2); - /* Check that flags come out right.*/ - cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL); - test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" - "Running:Stable:V2Dir:Valid"); - tor_free(cp); - vrs = smartlist_get(v2->routerstatus_list, 1); - /* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) */ - test_eq(vrs->flags, U64_LITERAL(974)); - - /* Generate the third vote. */ - vote->published = now; - vote->fresh_until = now+2003; - vote->dist_seconds = 250; - authority_cert_free(vote->cert); - vote->cert = authority_cert_dup(cert3); - smartlist_add(vote->supported_methods, tor_strdup("4")); - vote->client_versions = tor_strdup("0.1.2.14,0.1.2.17"); - vote->server_versions = tor_strdup("0.1.2.10,0.1.2.15,0.1.2.16"); - voter = smartlist_get(vote->voters, 0); - tor_free(voter->nickname); - tor_free(voter->address); - voter->nickname = tor_strdup("Voter3"); - voter->address = tor_strdup("3.4.5.6"); - voter->addr = 0x03040506; - crypto_pk_get_digest(cert3->identity_key, voter->identity_digest); - /* This one has a legacy id. */ - memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN); - vrs = smartlist_get(vote->routerstatus_list, 0); - smartlist_del_keeporder(vote->routerstatus_list, 0); - tor_free(vrs->version); - tor_free(vrs); - vrs = smartlist_get(vote->routerstatus_list, 0); - memset(vrs->status.descriptor_digest, (int)'Z', DIGEST_LEN); - test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); - - v3_text = format_networkstatus_vote(sign_skey_3, vote); - test_assert(v3_text); - - v3 = networkstatus_parse_vote_from_string(v3_text, NULL, NS_TYPE_VOTE); - test_assert(v3); - - /* Compute a consensus as voter 3. */ - smartlist_add(votes, v3); - smartlist_add(votes, v1); - smartlist_add(votes, v2); - consensus_text = networkstatus_compute_consensus(votes, 3, - cert3->identity_key, - sign_skey_3, - "AAAAAAAAAAAAAAAAAAAA", - sign_skey_leg1); - test_assert(consensus_text); - con = networkstatus_parse_vote_from_string(consensus_text, NULL, - NS_TYPE_CONSENSUS); - test_assert(con); - //log_notice(LD_GENERAL, "<<%s>>\n<<%s>>\n<<%s>>\n", - // v1_text, v2_text, v3_text); - - /* Check consensus contents. */ - test_assert(con->type == NS_TYPE_CONSENSUS); - test_eq(con->published, 0); /* this field only appears in votes. */ - test_eq(con->valid_after, now+1000); - test_eq(con->fresh_until, now+2003); /* median */ - test_eq(con->valid_until, now+3000); - test_eq(con->vote_seconds, 100); - test_eq(con->dist_seconds, 250); /* median */ - test_streq(con->client_versions, "0.1.2.14"); - test_streq(con->server_versions, "0.1.2.15,0.1.2.16"); - cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL); - test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" - "Running:Stable:V2Dir:Valid"); - tor_free(cp); - test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/ - /* The voter id digests should be in this order. */ - test_assert(memcmp(cert2->cache_info.identity_digest, - cert1->cache_info.identity_digest,DIGEST_LEN)<0); - test_assert(memcmp(cert1->cache_info.identity_digest, - cert3->cache_info.identity_digest,DIGEST_LEN)<0); - test_same_voter(smartlist_get(con->voters, 1), - smartlist_get(v2->voters, 0)); - test_same_voter(smartlist_get(con->voters, 2), - smartlist_get(v1->voters, 0)); - test_same_voter(smartlist_get(con->voters, 3), - smartlist_get(v3->voters, 0)); - - test_assert(!con->cert); - test_eq(2, smartlist_len(con->routerstatus_list)); - /* There should be two listed routers: one with identity 3, one with - * identity 5. */ - /* This one showed up in 2 digests. */ - rs = smartlist_get(con->routerstatus_list, 0); - test_memeq(rs->identity_digest, - "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", - DIGEST_LEN); - test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); - test_assert(!rs->is_authority); - test_assert(!rs->is_exit); - 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 */ - test_assert(!rs->is_v2_dir); - test_assert(!rs->is_valid); - test_assert(!rs->is_named); - /* XXXX check version */ - - rs = smartlist_get(con->routerstatus_list, 1); - /* This one showed up in 3 digests. Twice with ID 'M', once with 'Z'. */ - test_memeq(rs->identity_digest, - "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", - DIGEST_LEN); - test_streq(rs->nickname, "router1"); - test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); - test_eq(rs->published_on, now-1000); - test_eq(rs->addr, 0x99009901); - test_eq(rs->or_port, 443); - test_eq(rs->dir_port, 0); - test_assert(!rs->is_authority); - test_assert(rs->is_exit); - 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_v2_dir); - test_assert(rs->is_valid); - test_assert(!rs->is_named); - /* XXXX check version */ - // x231 - // x213 - - /* Check signatures. the first voter is a pseudo-entry with a legacy key. - * The second one hasn't signed. The fourth one has signed: validate it. */ - voter = smartlist_get(con->voters, 1); - test_assert(!voter->signature); - test_assert(!voter->good_signature); - test_assert(!voter->bad_signature); - - voter = smartlist_get(con->voters, 3); - test_assert(voter->signature); - test_assert(!voter->good_signature); - test_assert(!voter->bad_signature); - test_assert(!networkstatus_check_voter_signature(con, - smartlist_get(con->voters, 3), - cert3)); - test_assert(voter->signature); - test_assert(voter->good_signature); - test_assert(!voter->bad_signature); - - { - const char *msg=NULL; - /* Compute the other two signed consensuses. */ - smartlist_shuffle(votes); - consensus_text2 = networkstatus_compute_consensus(votes, 3, - cert2->identity_key, - sign_skey_2, NULL,NULL); - smartlist_shuffle(votes); - consensus_text3 = networkstatus_compute_consensus(votes, 3, - cert1->identity_key, - sign_skey_1, NULL,NULL); - test_assert(consensus_text2); - test_assert(consensus_text3); - con2 = networkstatus_parse_vote_from_string(consensus_text2, NULL, - NS_TYPE_CONSENSUS); - con3 = networkstatus_parse_vote_from_string(consensus_text3, NULL, - NS_TYPE_CONSENSUS); - test_assert(con2); - test_assert(con3); - - /* All three should have the same digest. */ - test_memeq(con->networkstatus_digest, con2->networkstatus_digest, - DIGEST_LEN); - test_memeq(con->networkstatus_digest, con3->networkstatus_digest, - DIGEST_LEN); - - /* Extract a detached signature from con3. */ - detached_text1 = networkstatus_get_detached_signatures(con3); - tor_assert(detached_text1); - /* Try to parse it. */ - dsig1 = networkstatus_parse_detached_signatures(detached_text1, NULL); - tor_assert(dsig1); - - /* Are parsed values as expected? */ - test_eq(dsig1->valid_after, con3->valid_after); - test_eq(dsig1->fresh_until, con3->fresh_until); - test_eq(dsig1->valid_until, con3->valid_until); - test_memeq(dsig1->networkstatus_digest, con3->networkstatus_digest, - DIGEST_LEN); - test_eq(1, smartlist_len(dsig1->signatures)); - voter = smartlist_get(dsig1->signatures, 0); - test_memeq(voter->identity_digest, cert1->cache_info.identity_digest, - DIGEST_LEN); - - /* Try adding it to con2. */ - detached_text2 = networkstatus_get_detached_signatures(con2); - test_eq(1, networkstatus_add_detached_signatures(con2, dsig1, &msg)); - tor_free(detached_text2); - detached_text2 = networkstatus_get_detached_signatures(con2); - //printf("\n<%s>\n", detached_text2); - dsig2 = networkstatus_parse_detached_signatures(detached_text2, NULL); - test_assert(dsig2); - /* - printf("\n"); - SMARTLIST_FOREACH(dsig2->signatures, networkstatus_voter_info_t *, vi, { - char hd[64]; - base16_encode(hd, sizeof(hd), vi->identity_digest, DIGEST_LEN); - printf("%s\n", hd); - }); - */ - test_eq(2, smartlist_len(dsig2->signatures)); - - /* Try adding to con2 twice; verify that nothing changes. */ - test_eq(0, networkstatus_add_detached_signatures(con2, dsig1, &msg)); - - /* Add to con. */ - test_eq(2, networkstatus_add_detached_signatures(con, dsig2, &msg)); - /* Check signatures */ - test_assert(!networkstatus_check_voter_signature(con, - smartlist_get(con->voters, 1), - cert2)); - test_assert(!networkstatus_check_voter_signature(con, - smartlist_get(con->voters, 2), - cert1)); - - } - - done: - smartlist_free(votes); - tor_free(v1_text); - tor_free(v2_text); - tor_free(v3_text); - tor_free(consensus_text); - - if (vote) - networkstatus_vote_free(vote); - if (v1) - networkstatus_vote_free(v1); - if (v2) - networkstatus_vote_free(v2); - if (v3) - networkstatus_vote_free(v3); - if (con) - networkstatus_vote_free(con); - if (sign_skey_1) - crypto_free_pk_env(sign_skey_1); - if (sign_skey_2) - crypto_free_pk_env(sign_skey_2); - if (sign_skey_3) - crypto_free_pk_env(sign_skey_3); - if (sign_skey_leg1) - crypto_free_pk_env(sign_skey_leg1); - if (cert1) - authority_cert_free(cert1); - if (cert2) - authority_cert_free(cert2); - if (cert3) - authority_cert_free(cert3); - - tor_free(consensus_text2); - tor_free(consensus_text3); - tor_free(detached_text1); - tor_free(detached_text2); - if (con2) - networkstatus_vote_free(con2); - if (con3) - networkstatus_vote_free(con3); - if (dsig1) - ns_detached_signatures_free(dsig1); - if (dsig2) - ns_detached_signatures_free(dsig2); -} - -/** Helper: Parse the exit policy string in <b>policy_str</b>, and make sure - * that policies_summarize() produces the string <b>expected_summary</b> from - * it. */ -static void -test_policy_summary_helper(const char *policy_str, - const char *expected_summary) -{ - config_line_t line; - smartlist_t *policy = smartlist_create(); - char *summary = NULL; - int r; - - line.key = (char*)"foo"; - line.value = (char *)policy_str; - line.next = NULL; - - r = policies_parse_exit_policy(&line, &policy, 0, NULL); - test_eq(r, 0); - summary = policy_summarize(policy); - - test_assert(summary != NULL); - test_streq(summary, expected_summary); - - done: - tor_free(summary); - if (policy) - addr_policy_list_free(policy); -} - -/** Run unit tests for generating summary lines of exit policies */ -static void -test_policies(void) -{ - int i; - smartlist_t *policy = NULL, *policy2 = NULL; - addr_policy_t *p; - tor_addr_t tar; - config_line_t line; - smartlist_t *sm = NULL; - char *policy_str = NULL; - - policy = smartlist_create(); - - p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); - test_assert(p != NULL); - test_eq(ADDR_POLICY_REJECT, p->policy_type); - tor_addr_from_ipv4h(&tar, 0xc0a80000u); - test_eq(0, tor_addr_compare(&p->addr, &tar, CMP_EXACT)); - test_eq(16, p->maskbits); - test_eq(1, p->prt_min); - test_eq(65535, p->prt_max); - - smartlist_add(policy, p); - - test_assert(ADDR_POLICY_ACCEPTED == - compare_addr_to_addr_policy(0x01020304u, 2, policy)); - test_assert(ADDR_POLICY_PROBABLY_ACCEPTED == - compare_addr_to_addr_policy(0, 2, policy)); - test_assert(ADDR_POLICY_REJECTED == - compare_addr_to_addr_policy(0xc0a80102, 2, policy)); - - policy2 = NULL; - test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, NULL)); - test_assert(policy2); - - test_assert(!exit_policy_is_general_exit(policy)); - test_assert(exit_policy_is_general_exit(policy2)); - test_assert(!exit_policy_is_general_exit(NULL)); - - test_assert(cmp_addr_policies(policy, policy2)); - test_assert(cmp_addr_policies(policy, NULL)); - test_assert(!cmp_addr_policies(policy2, policy2)); - test_assert(!cmp_addr_policies(NULL, NULL)); - - test_assert(!policy_is_reject_star(policy2)); - test_assert(policy_is_reject_star(policy)); - test_assert(policy_is_reject_star(NULL)); - - addr_policy_list_free(policy); - policy = NULL; - - /* make sure compacting logic works. */ - policy = NULL; - line.key = (char*)"foo"; - line.value = (char*)"accept *:80,reject private:*,reject *:*"; - line.next = NULL; - test_assert(0 == policies_parse_exit_policy(&line, &policy, 0, NULL)); - test_assert(policy); - //test_streq(policy->string, "accept *:80"); - //test_streq(policy->next->string, "reject *:*"); - test_eq(smartlist_len(policy), 2); - - /* test policy summaries */ - /* check if we properly ignore private IP addresses */ - test_policy_summary_helper("reject 192.168.0.0/16:*," - "reject 0.0.0.0/8:*," - "reject 10.0.0.0/8:*," - "accept *:10-30," - "accept *:90," - "reject *:*", - "accept 10-30,90"); - /* check all accept policies, and proper counting of rejects */ - test_policy_summary_helper("reject 11.0.0.0/9:80," - "reject 12.0.0.0/9:80," - "reject 13.0.0.0/9:80," - "reject 14.0.0.0/9:80," - "accept *:*", "accept 1-65535"); - test_policy_summary_helper("reject 11.0.0.0/9:80," - "reject 12.0.0.0/9:80," - "reject 13.0.0.0/9:80," - "reject 14.0.0.0/9:80," - "reject 15.0.0.0:81," - "accept *:*", "accept 1-65535"); - test_policy_summary_helper("reject 11.0.0.0/9:80," - "reject 12.0.0.0/9:80," - "reject 13.0.0.0/9:80," - "reject 14.0.0.0/9:80," - "reject 15.0.0.0:80," - "accept *:*", - "reject 80"); - /* no exits */ - test_policy_summary_helper("accept 11.0.0.0/9:80," - "reject *:*", - "reject 1-65535"); - /* port merging */ - test_policy_summary_helper("accept *:80," - "accept *:81," - "accept *:100-110," - "accept *:111," - "reject *:*", - "accept 80-81,100-111"); - /* border ports */ - test_policy_summary_helper("accept *:1," - "accept *:3," - "accept *:65535," - "reject *:*", - "accept 1,3,65535"); - /* holes */ - test_policy_summary_helper("accept *:1," - "accept *:3," - "accept *:5," - "accept *:7," - "reject *:*", - "accept 1,3,5,7"); - test_policy_summary_helper("reject *:1," - "reject *:3," - "reject *:5," - "reject *:7," - "accept *:*", - "reject 1,3,5,7"); - - /* truncation ports */ - sm = smartlist_create(); - for (i=1; i<2000; i+=2) { - char buf[POLICY_BUF_LEN]; - tor_snprintf(buf, sizeof(buf), "reject *:%d", i); - smartlist_add(sm, tor_strdup(buf)); - } - smartlist_add(sm, tor_strdup("accept *:*")); - policy_str = smartlist_join_strings(sm, ",", 0, NULL); - test_policy_summary_helper( policy_str, - "accept 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44," - "46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90," - "92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128," - "130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164," - "166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200," - "202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236," - "238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272," - "274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308," - "310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344," - "346,348,350,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380," - "382,384,386,388,390,392,394,396,398,400,402,404,406,408,410,412,414,416," - "418,420,422,424,426,428,430,432,434,436,438,440,442,444,446,448,450,452," - "454,456,458,460,462,464,466,468,470,472,474,476,478,480,482,484,486,488," - "490,492,494,496,498,500,502,504,506,508,510,512,514,516,518,520,522"); - - done: - if (policy) - addr_policy_list_free(policy); - if (policy2) - addr_policy_list_free(policy2); - tor_free(policy_str); - if (sm) { - SMARTLIST_FOREACH(sm, char *, s, tor_free(s)); - smartlist_free(sm); - } -} - -/** Run unit tests for basic rendezvous functions. */ -static void -test_rend_fns(void) -{ - char address1[] = "fooaddress.onion"; - char address2[] = "aaaaaaaaaaaaaaaa.onion"; - char address3[] = "fooaddress.exit"; - char address4[] = "www.torproject.org"; - rend_service_descriptor_t *d1 = - tor_malloc_zero(sizeof(rend_service_descriptor_t)); - rend_service_descriptor_t *d2 = NULL; - char *encoded = NULL; - size_t len; - time_t now; - int i; - crypto_pk_env_t *pk1 = pk_generate(0), *pk2 = pk_generate(1); - - /* Test unversioned (v0) descriptor */ - d1->pk = crypto_pk_dup_key(pk1); - now = time(NULL); - d1->timestamp = now; - d1->version = 0; - d1->intro_nodes = smartlist_create(); - for (i = 0; i < 3; i++) { - rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t)); - intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); - crypto_rand(intro->extend_info->identity_digest, DIGEST_LEN); - intro->extend_info->nickname[0] = '$'; - base16_encode(intro->extend_info->nickname+1, HEX_DIGEST_LEN+1, - intro->extend_info->identity_digest, DIGEST_LEN); - smartlist_add(d1->intro_nodes, intro); - } - test_assert(! rend_encode_service_descriptor(d1, pk1, &encoded, &len)); - d2 = rend_parse_service_descriptor(encoded, len); - test_assert(d2); - - test_assert(!crypto_pk_cmp_keys(d1->pk, d2->pk)); - test_eq(d2->timestamp, now); - test_eq(d2->version, 0); - test_eq(d2->protocols, 1<<2); - test_eq(smartlist_len(d2->intro_nodes), 3); - for (i = 0; i < 3; i++) { - rend_intro_point_t *intro1 = smartlist_get(d1->intro_nodes, i); - rend_intro_point_t *intro2 = smartlist_get(d2->intro_nodes, i); - test_streq(intro1->extend_info->nickname, - intro2->extend_info->nickname); - } - - test_assert(BAD_HOSTNAME == parse_extended_hostname(address1)); - test_assert(ONION_HOSTNAME == parse_extended_hostname(address2)); - test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3)); - test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4)); - - crypto_free_pk_env(pk1); - crypto_free_pk_env(pk2); - pk1 = pk2 = NULL; - rend_service_descriptor_free(d1); - rend_service_descriptor_free(d2); - d1 = d2 = NULL; - - done: - if (pk1) - crypto_free_pk_env(pk1); - if (pk2) - crypto_free_pk_env(pk2); - if (d1) - rend_service_descriptor_free(d1); - if (d2) - rend_service_descriptor_free(d2); - tor_free(encoded); -} - -/** 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); -} - -/** Run unittests for memory pool allocator */ -static void -test_util_mempool(void) -{ - mp_pool_t *pool = NULL; - smartlist_t *allocated = NULL; - int i; - - pool = mp_pool_new(1, 100); - test_assert(pool); - test_assert(pool->new_chunk_capacity >= 100); - test_assert(pool->item_alloc_size >= sizeof(void*)+1); - mp_pool_destroy(pool); - pool = NULL; - - pool = mp_pool_new(241, 2500); - test_assert(pool); - test_assert(pool->new_chunk_capacity >= 10); - test_assert(pool->item_alloc_size >= sizeof(void*)+241); - test_eq(pool->item_alloc_size & 0x03, 0); - test_assert(pool->new_chunk_capacity < 60); - - allocated = smartlist_create(); - for (i = 0; i < 20000; ++i) { - if (smartlist_len(allocated) < 20 || crypto_rand_int(2)) { - void *m = mp_pool_get(pool); - memset(m, 0x09, 241); - smartlist_add(allocated, m); - //printf("%d: %p\n", i, m); - //mp_pool_assert_ok(pool); - } else { - int idx = crypto_rand_int(smartlist_len(allocated)); - void *m = smartlist_get(allocated, idx); - //printf("%d: free %p\n", i, m); - smartlist_del(allocated, idx); - mp_pool_release(m); - //mp_pool_assert_ok(pool); - } - if (crypto_rand_int(777)==0) - mp_pool_clean(pool, 1, 1); - - if (i % 777) - mp_pool_assert_ok(pool); - } - - done: - if (allocated) { - SMARTLIST_FOREACH(allocated, void *, m, mp_pool_release(m)); - mp_pool_assert_ok(pool); - mp_pool_clean(pool, 0, 0); - mp_pool_assert_ok(pool); - smartlist_free(allocated); - } - - if (pool) - mp_pool_destroy(pool); -} - -/** Run unittests for memory area allocator */ -static void -test_util_memarea(void) -{ - memarea_t *area = memarea_new(); - char *p1, *p2, *p3, *p1_orig; - void *malloced_ptr = NULL; - int i; - - test_assert(area); - - p1_orig = p1 = memarea_alloc(area,64); - p2 = memarea_alloc_zero(area,52); - p3 = memarea_alloc(area,11); - - test_assert(memarea_owns_ptr(area, p1)); - test_assert(memarea_owns_ptr(area, p2)); - test_assert(memarea_owns_ptr(area, p3)); - /* Make sure we left enough space. */ - test_assert(p1+64 <= p2); - test_assert(p2+52 <= p3); - /* Make sure we aligned. */ - test_eq(((uintptr_t)p1) % sizeof(void*), 0); - test_eq(((uintptr_t)p2) % sizeof(void*), 0); - test_eq(((uintptr_t)p3) % sizeof(void*), 0); - test_assert(!memarea_owns_ptr(area, p3+8192)); - test_assert(!memarea_owns_ptr(area, p3+30)); - test_assert(tor_mem_is_zero(p2, 52)); - /* Make sure we don't overalign. */ - p1 = memarea_alloc(area, 1); - p2 = memarea_alloc(area, 1); - test_eq(p1+sizeof(void*), p2); - { - malloced_ptr = tor_malloc(64); - test_assert(!memarea_owns_ptr(area, malloced_ptr)); - tor_free(malloced_ptr); - } - - /* memarea_memdup */ - { - malloced_ptr = tor_malloc(64); - crypto_rand((char*)malloced_ptr, 64); - p1 = memarea_memdup(area, malloced_ptr, 64); - test_assert(p1 != malloced_ptr); - test_memeq(p1, malloced_ptr, 64); - tor_free(malloced_ptr); - } - - /* memarea_strdup. */ - p1 = memarea_strdup(area,""); - p2 = memarea_strdup(area, "abcd"); - test_assert(p1); - test_assert(p2); - test_streq(p1, ""); - test_streq(p2, "abcd"); - - /* memarea_strndup. */ - { - const char *s = "Ad ogni porta batte la morte e grida: il nome!"; - /* (From Turandot, act 3.) */ - size_t len = strlen(s); - p1 = memarea_strndup(area, s, 1000); - p2 = memarea_strndup(area, s, 10); - test_streq(p1, s); - test_assert(p2 >= p1 + len + 1); - test_memeq(s, p2, 10); - test_eq(p2[10], '\0'); - p3 = memarea_strndup(area, s, len); - test_streq(p3, s); - p3 = memarea_strndup(area, s, len-1); - test_memeq(s, p3, len-1); - test_eq(p3[len-1], '\0'); - } - - memarea_clear(area); - p1 = memarea_alloc(area, 1); - test_eq(p1, p1_orig); - memarea_clear(area); - - /* Check for running over an area's size. */ - for (i = 0; i < 512; ++i) { - p1 = memarea_alloc(area, crypto_rand_int(5)+1); - test_assert(memarea_owns_ptr(area, p1)); - } - memarea_assert_ok(area); - /* Make sure we can allocate a too-big object. */ - p1 = memarea_alloc_zero(area, 9000); - p2 = memarea_alloc_zero(area, 16); - test_assert(memarea_owns_ptr(area, p1)); - test_assert(memarea_owns_ptr(area, p2)); - - done: - memarea_drop_all(area); - tor_free(malloced_ptr); -} - -/** Run unit tests for utility functions to get file names relative to - * the data directory. */ -static void -test_util_datadir(void) -{ - char buf[1024]; - char *f = NULL; - - f = get_datadir_fname(NULL); - test_streq(f, temp_dir); - tor_free(f); - f = get_datadir_fname("state"); - tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir); - test_streq(f, buf); - tor_free(f); - f = get_datadir_fname2("cache", "thingy"); - tor_snprintf(buf, sizeof(buf), - "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir); - test_streq(f, buf); - tor_free(f); - f = get_datadir_fname2_suffix("cache", "thingy", ".foo"); - tor_snprintf(buf, sizeof(buf), - "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir); - test_streq(f, buf); - tor_free(f); - f = get_datadir_fname_suffix("cache", ".foo"); - tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo", - temp_dir); - test_streq(f, buf); - - done: - tor_free(f); -} - -/** Test AES-CTR encryption and decryption with IV. */ -static void -test_crypto_aes_iv(void) -{ - crypto_cipher_env_t *cipher; - char *plain, *encrypted1, *encrypted2, *decrypted1, *decrypted2; - char plain_1[1], plain_15[15], plain_16[16], plain_17[17]; - char key1[16], key2[16]; - ssize_t encrypted_size, decrypted_size; - - plain = tor_malloc(4095); - encrypted1 = tor_malloc(4095 + 1 + 16); - encrypted2 = tor_malloc(4095 + 1 + 16); - decrypted1 = tor_malloc(4095 + 1); - decrypted2 = tor_malloc(4095 + 1); - - crypto_rand(plain, 4095); - crypto_rand(key1, 16); - crypto_rand(key2, 16); - crypto_rand(plain_1, 1); - crypto_rand(plain_15, 15); - crypto_rand(plain_16, 16); - crypto_rand(plain_17, 17); - key1[0] = key2[0] + 128; /* Make sure that contents are different. */ - /* Encrypt and decrypt with the same key. */ - cipher = crypto_create_init_cipher(key1, 1); - encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 4095, - plain, 4095); - 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 - * greater than 0, but its truth is not - * obvious to all analysis tools. */ - cipher = crypto_create_init_cipher(key1, 0); - decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 4095, - encrypted1, encrypted_size); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_eq(decrypted_size, 4095); - tor_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); - encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted2, 16 + 4095, - plain, 4095); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_eq(encrypted_size, 16 + 4095); - tor_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); - test_memeq(plain, decrypted2, 4095); - test_memneq(encrypted1, encrypted2, encrypted_size); - /* Decrypt with the wrong key. */ - cipher = crypto_create_init_cipher(key2, 0); - decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095, - encrypted1, encrypted_size); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_memneq(plain, decrypted2, encrypted_size); - /* Alter the initialization vector. */ - encrypted1[0] += 42; - cipher = crypto_create_init_cipher(key1, 0); - decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 4095, - encrypted1, encrypted_size); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_memneq(plain, decrypted2, 4095); - /* Special length case: 1. */ - cipher = crypto_create_init_cipher(key1, 1); - encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 1, - plain_1, 1); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_eq(encrypted_size, 16 + 1); - tor_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); - test_memeq(plain_1, decrypted1, 1); - /* Special length case: 15. */ - cipher = crypto_create_init_cipher(key1, 1); - encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 15, - plain_15, 15); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_eq(encrypted_size, 16 + 15); - tor_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); - test_memeq(plain_15, decrypted1, 15); - /* Special length case: 16. */ - cipher = crypto_create_init_cipher(key1, 1); - encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 16, - plain_16, 16); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_eq(encrypted_size, 16 + 16); - tor_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); - test_memeq(plain_16, decrypted1, 16); - /* Special length case: 17. */ - cipher = crypto_create_init_cipher(key1, 1); - encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 17, - plain_17, 17); - crypto_free_cipher_env(cipher); - cipher = NULL; - test_eq(encrypted_size, 16 + 17); - tor_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); - test_memeq(plain_17, decrypted1, 17); - - done: - /* Free memory. */ - tor_free(plain); - tor_free(encrypted1); - tor_free(encrypted2); - tor_free(decrypted1); - tor_free(decrypted2); - if (cipher) - crypto_free_cipher_env(cipher); -} - -/** Test base32 decoding. */ -static void -test_crypto_base32_decode(void) -{ - char plain[60], encoded[96 + 1], decoded[60]; - int res; - crypto_rand(plain, 60); - /* Encode and decode a random string. */ - base32_encode(encoded, 96 + 1, plain, 60); - res = base32_decode(decoded, 60, encoded, 96); - test_eq(res, 0); - test_memeq(plain, decoded, 60); - /* Encode, uppercase, and decode a random string. */ - base32_encode(encoded, 96 + 1, plain, 60); - tor_strupper(encoded); - res = base32_decode(decoded, 60, encoded, 96); - test_eq(res, 0); - test_memeq(plain, decoded, 60); - /* Change encoded string and decode. */ - if (encoded[0] == 'A' || encoded[0] == 'a') - encoded[0] = 'B'; - else - encoded[0] = 'A'; - res = base32_decode(decoded, 60, encoded, 96); - test_eq(res, 0); - test_memneq(plain, decoded, 60); - /* Bad encodings. */ - encoded[0] = '!'; - res = base32_decode(decoded, 60, encoded, 96); - test_assert(res < 0); - - done: - ; -} - -/** Test encoding and parsing of v2 rendezvous service descriptors. */ -static void -test_rend_fns_v2(void) -{ - rend_service_descriptor_t *generated = NULL, *parsed = NULL; - char service_id[DIGEST_LEN]; - char service_id_base32[REND_SERVICE_ID_LEN_BASE32+1]; - const char *next_desc; - smartlist_t *descs = smartlist_create(); - char computed_desc_id[DIGEST_LEN]; - char parsed_desc_id[DIGEST_LEN]; - crypto_pk_env_t *pk1 = NULL, *pk2 = NULL; - time_t now; - char *intro_points_encrypted = NULL; - size_t intro_points_size; - size_t encoded_size; - int i; - pk1 = pk_generate(0); - pk2 = pk_generate(1); - generated = tor_malloc_zero(sizeof(rend_service_descriptor_t)); - generated->pk = crypto_pk_dup_key(pk1); - crypto_pk_get_digest(generated->pk, service_id); - base32_encode(service_id_base32, REND_SERVICE_ID_LEN_BASE32+1, - service_id, REND_SERVICE_ID_LEN); - now = time(NULL); - generated->timestamp = now; - generated->version = 2; - generated->protocols = 42; - generated->intro_nodes = smartlist_create(); - - for (i = 0; i < 3; i++) { - rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t)); - crypto_pk_env_t *okey = pk_generate(2 + i); - intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); - intro->extend_info->onion_key = okey; - crypto_pk_get_digest(intro->extend_info->onion_key, - intro->extend_info->identity_digest); - //crypto_rand(info->identity_digest, DIGEST_LEN); /* Would this work? */ - intro->extend_info->nickname[0] = '$'; - base16_encode(intro->extend_info->nickname + 1, - sizeof(intro->extend_info->nickname) - 1, - intro->extend_info->identity_digest, DIGEST_LEN); - /* Does not cover all IP addresses. */ - tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536)); - intro->extend_info->port = crypto_rand_int(65536); - intro->intro_key = crypto_pk_dup_key(pk2); - smartlist_add(generated->intro_nodes, intro); - } - test_assert(rend_encode_v2_descriptors(descs, generated, now, 0, - REND_NO_AUTH, NULL, NULL) > 0); - test_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32, - NULL, now, 0) == 0); - test_memeq(((rend_encoded_v2_service_descriptor_t *) - smartlist_get(descs, 0))->desc_id, computed_desc_id, DIGEST_LEN); - test_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id, - &intro_points_encrypted, - &intro_points_size, - &encoded_size, - &next_desc, - ((rend_encoded_v2_service_descriptor_t *) - smartlist_get(descs, 0))->desc_str) == 0); - test_assert(parsed); - test_memeq(((rend_encoded_v2_service_descriptor_t *) - smartlist_get(descs, 0))->desc_id, parsed_desc_id, DIGEST_LEN); - test_eq(rend_parse_introduction_points(parsed, intro_points_encrypted, - intro_points_size), 3); - test_assert(!crypto_pk_cmp_keys(generated->pk, parsed->pk)); - test_eq(parsed->timestamp, now); - test_eq(parsed->version, 2); - test_eq(parsed->protocols, 42); - test_eq(smartlist_len(parsed->intro_nodes), 3); - for (i = 0; i < smartlist_len(parsed->intro_nodes); i++) { - rend_intro_point_t *par_intro = smartlist_get(parsed->intro_nodes, i), - *gen_intro = smartlist_get(generated->intro_nodes, i); - extend_info_t *par_info = par_intro->extend_info; - extend_info_t *gen_info = gen_intro->extend_info; - test_assert(!crypto_pk_cmp_keys(gen_info->onion_key, par_info->onion_key)); - test_memeq(gen_info->identity_digest, par_info->identity_digest, - DIGEST_LEN); - test_streq(gen_info->nickname, par_info->nickname); - test_assert(tor_addr_eq(&gen_info->addr, &par_info->addr)); - test_eq(gen_info->port, par_info->port); - } - - rend_service_descriptor_free(parsed); - rend_service_descriptor_free(generated); - parsed = generated = NULL; - - done: - if (descs) { - for (i = 0; i < smartlist_len(descs); i++) - rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i)); - smartlist_free(descs); - } - if (parsed) - rend_service_descriptor_free(parsed); - if (generated) - rend_service_descriptor_free(generated); - if (pk1) - crypto_free_pk_env(pk1); - if (pk2) - crypto_free_pk_env(pk2); - tor_free(intro_points_encrypted); -} - -/** Run unit tests for GeoIP code. */ -static void -test_geoip(void) -{ - int i, j; - time_t now = time(NULL); - char *s = NULL; - - /* 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 - * fine uint32_t values. */ - test_eq(0, geoip_parse_entry("10,50,AB")); - test_eq(0, geoip_parse_entry("52,90,XY")); - test_eq(0, geoip_parse_entry("95,100,AB")); - test_eq(0, geoip_parse_entry("\"105\",\"140\",\"ZZ\"")); - test_eq(0, geoip_parse_entry("\"150\",\"190\",\"XY\"")); - test_eq(0, geoip_parse_entry("\"200\",\"250\",\"AB\"")); - - /* We should have 3 countries: ab, xy, zz. */ - test_eq(3, geoip_get_n_countries()); - /* Make sure that country ID actually works. */ -#define NAMEFOR(x) geoip_get_country_name(geoip_get_country_by_ip(x)) - test_streq("ab", NAMEFOR(32)); - test_streq("??", NAMEFOR(5)); - test_streq("??", NAMEFOR(51)); - test_streq("xy", NAMEFOR(150)); - test_streq("xy", NAMEFOR(190)); - test_streq("??", NAMEFOR(2000)); -#undef NAMEFOR - - get_options()->BridgeRelay = 1; - get_options()->BridgeRecordUsageByCountry = 1; - /* Put 9 observations in AB... */ - for (i=32; i < 40; ++i) - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-7200); - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 225, now-7200); - /* and 3 observations in XY, several times. */ - for (j=0; j < 10; ++j) - for (i=52; i < 55; ++i) - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-3600); - /* and 17 observations in ZZ... */ - for (i=110; i < 127; ++i) - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now); - s = geoip_get_client_history(now+5*24*60*60, GEOIP_CLIENT_CONNECT); - test_assert(s); - test_streq("zz=24,ab=16,xy=8", s); - tor_free(s); - - /* Now clear out all the AB observations. */ - geoip_remove_old_clients(now-6000); - s = geoip_get_client_history(now+5*24*60*60, GEOIP_CLIENT_CONNECT); - test_assert(s); - test_streq("zz=24,xy=8", s); - - done: - tor_free(s); -} - -/** For test_array. Declare an CLI-invocable off-by-default function in the - * unit tests, with function name and user-visible name <b>x</b>*/ -#define DISABLED(x) { #x, x, 0, 0, 0 } -/** For test_array. Declare an CLI-invocable unit test function, with function - * name test_<b>x</b>(), and user-visible name <b>x</b> */ -#define ENT(x) { #x, test_ ## x, 0, 0, 1 } -/** For test_array. Declare an CLI-invocable unit test function, with function - * name test_<b>x</b>_<b>y</b>(), and user-visible name - * <b>x</b>/<b>y</b>. This function will be treated as a subentry of <b>x</b>, - * so that invoking <b>x</b> from the CLI invokes this test too. */ -#define SUBENT(x,y) { #x "/" #y, test_ ## x ## _ ## y, 1, 0, 1 } - -/** An array of functions and information for all the unit tests we can run. */ -static struct { - const char *test_name; /**< How does the user refer to this test from the - * command line? */ - void (*test_fn)(void); /**< What function is called to run this test? */ - int is_subent; /**< Is this a subentry of a bigger set of related tests? */ - int selected; /**< Are we planning to run this one? */ - int is_default; /**< If the user doesn't say what tests they want, do they - * get this function by default? */ -} test_array[] = { - ENT(buffers), - ENT(crypto), - SUBENT(crypto, rng), - SUBENT(crypto, aes), - SUBENT(crypto, sha), - SUBENT(crypto, pk), - SUBENT(crypto, dh), - SUBENT(crypto, s2k), - SUBENT(crypto, aes_iv), - SUBENT(crypto, base32_decode), - ENT(util), - SUBENT(util, ip6_helpers), - SUBENT(util, gzip), - SUBENT(util, datadir), - SUBENT(util, smartlist_basic), - SUBENT(util, smartlist_strings), - SUBENT(util, smartlist_overlap), - SUBENT(util, smartlist_digests), - SUBENT(util, smartlist_join), - SUBENT(util, bitarray), - SUBENT(util, digestset), - SUBENT(util, mempool), - SUBENT(util, memarea), - SUBENT(util, strmap), - SUBENT(util, control_formats), - SUBENT(util, pqueue), - SUBENT(util, mmap), - SUBENT(util, threads), - SUBENT(util, order_functions), - SUBENT(util, sscanf), - ENT(onion_handshake), - ENT(dir_format), - ENT(dirutil), - ENT(v3_networkstatus), - ENT(policies), - ENT(rend_fns), - SUBENT(rend_fns, v2), - ENT(geoip), - - DISABLED(bench_aes), - DISABLED(bench_dmap), - { NULL, NULL, 0, 0, 0 }, -}; - -static void syntax(void) ATTR_NORETURN; - -/** Print a syntax usage message, and exit.*/ -static void -syntax(void) -{ - int i; - printf("Syntax:\n" - " test [-v|--verbose] [--warn|--notice|--info|--debug]\n" - " [testname...]\n" - "Recognized tests are:\n"); - for (i = 0; test_array[i].test_name; ++i) { - printf(" %s\n", test_array[i].test_name); - } - - exit(0); -} - -/** Main entry point for unit test code: parse the command line, and run - * some unit tests. */ -int -main(int c, char**v) -{ - or_options_t *options; - char *errmsg = NULL; - int i; - int verbose = 0, any_selected = 0; - int loglevel = LOG_ERR; - -#ifdef USE_DMALLOC - { - int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc, _tor_free); - tor_assert(r); - } -#endif - - update_approx_time(time(NULL)); - options = options_new(); - tor_threads_init(); - init_logging(); - - for (i = 1; i < c; ++i) { - if (!strcmp(v[i], "-v") || !strcmp(v[i], "--verbose")) - verbose++; - else if (!strcmp(v[i], "--warn")) - loglevel = LOG_WARN; - else if (!strcmp(v[i], "--notice")) - loglevel = LOG_NOTICE; - else if (!strcmp(v[i], "--info")) - loglevel = LOG_INFO; - else if (!strcmp(v[i], "--debug")) - loglevel = LOG_DEBUG; - else if (!strcmp(v[i], "--help") || !strcmp(v[i], "-h") || v[i][0] == '-') - syntax(); - else { - int j, found=0; - for (j = 0; test_array[j].test_name; ++j) { - if (!strcmp(v[i], test_array[j].test_name) || - (test_array[j].is_subent && - !strcmpstart(test_array[j].test_name, v[i]) && - test_array[j].test_name[strlen(v[i])] == '/') || - (v[i][0] == '=' && !strcmp(v[i]+1, test_array[j].test_name))) { - test_array[j].selected = 1; - any_selected = 1; - found = 1; - } - } - if (!found) { - printf("Unknown test: %s\n", v[i]); - syntax(); - } - } - } - - if (!any_selected) { - for (i = 0; test_array[i].test_name; ++i) { - test_array[i].selected = test_array[i].is_default; - } - } - - { - log_severity_list_t s; - memset(&s, 0, sizeof(s)); - set_log_severity_config(loglevel, LOG_ERR, &s); - add_stream_log(&s, "", fileno(stdout)); - } - - options->command = CMD_RUN_UNITTESTS; - crypto_global_init(0); - rep_hist_init(); - network_init(); - setup_directory(); - options_init(options); - options->DataDirectory = tor_strdup(temp_dir); - if (set_options(options, &errmsg) < 0) { - printf("Failed to set initial options: %s\n", errmsg); - tor_free(errmsg); - return 1; - } - - crypto_seed_rng(1); - - atexit(remove_directory); - - printf("Running Tor unit tests on %s\n", get_uname()); - - for (i = 0; test_array[i].test_name; ++i) { - if (!test_array[i].selected) - continue; - if (!test_array[i].is_subent) { - printf("\n============================== %s\n",test_array[i].test_name); - } else if (test_array[i].is_subent && verbose) { - printf("\n%s", test_array[i].test_name); - } - test_array[i].test_fn(); - } - puts(""); - - free_pregenerated_keys(); -#ifdef USE_DMALLOC - tor_free_all(0); - dmalloc_log_unfreed(); -#endif - - if (have_failed) - return 1; - else - return 0; -} - diff --git a/src/or/tor_main.c b/src/or/tor_main.c index bb1bf37b4d..117369c565 100644 --- a/src/or/tor_main.c +++ b/src/or/tor_main.c @@ -7,7 +7,7 @@ * built from. This string is generated by a bit of shell kludging int * src/or/Makefile.am, and is usually right. */ -const char tor_svn_revision[] = +const char tor_git_revision[] = #ifndef _MSC_VER #include "micro-revision.i" #endif diff --git a/src/test/Makefile.am b/src/test/Makefile.am new file mode 100644 index 0000000000..546fa2f4b7 --- /dev/null +++ b/src/test/Makefile.am @@ -0,0 +1,30 @@ +TESTS = test + +noinst_PROGRAMS = test + +AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ + -DLOCALSTATEDIR="\"$(localstatedir)\"" \ + -DBINDIR="\"$(bindir)\"" \ + -I"$(top_srcdir)/src/or" + +# -L flags need to go in LDFLAGS. -l flags need to go in LDADD. +# This seems to matter nowhere but on windows, but I assure you that it +# 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_crypto.c \ + test_dir.c \ + test_containers.c \ + test_util.c \ + tinytest.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@ + +noinst_HEADERS = tinytest.h tinytest_macros.h test.h diff --git a/src/test/test.c b/src/test/test.c new file mode 100644 index 0000000000..8782ef5077 --- /dev/null +++ b/src/test/test.c @@ -0,0 +1,1286 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, 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 test.c + * \brief Unit tests for many pieces of the lower level Tor modules. + **/ + +#include "orconfig.h" + +#include <stdio.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef MS_WINDOWS +/* For mkdir() */ +#include <direct.h> +#else +#include <dirent.h> +#endif + +/* These macros pull in declarations for some functions and structures that + * are typically file-private. */ +#define BUFFERS_PRIVATE +#define CONFIG_PRIVATE +#define GEOIP_PRIVATE +#define ROUTER_PRIVATE +#define CIRCUIT_PRIVATE + +/* + * Linux doesn't provide lround in math.h by default, but mac os does... + * It's best just to leave math.h out of the picture entirely. + */ +//#include <math.h> +long int lround(double x); +double fabs(double x); + +#include "or.h" +#include "buffers.h" +#include "circuitbuild.h" +#include "config.h" +#include "connection_edge.h" +#include "geoip.h" +#include "rendcommon.h" +#include "test.h" +#include "torgzip.h" +#include "mempool.h" +#include "memarea.h" +#include "onion.h" +#include "policies.h" +#include "rephist.h" +#include "routerparse.h" + +#ifdef USE_DMALLOC +#include <dmalloc.h> +#include <openssl/crypto.h> +#include "main.h" +#endif + +/** Set to true if any unit test has failed. Mostly, this is set by the macros + * in test.h */ +int have_failed = 0; + +/** Temporary directory (set up by setup_directory) under which we store all + * our files during testing. */ +static char temp_dir[256]; +static pid_t temp_dir_setup_in_pid = 0; + +/** Select and create the temporary directory we'll use to run our unit tests. + * Store it in <b>temp_dir</b>. Exit immediately if we can't create it. + * idempotent. */ +static void +setup_directory(void) +{ + static int is_setup = 0; + int r; + if (is_setup) return; + +#ifdef MS_WINDOWS + // XXXX + tor_snprintf(temp_dir, sizeof(temp_dir), + "c:\\windows\\temp\\tor_test_%d", (int)getpid()); + r = mkdir(temp_dir); +#else + tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d", (int) getpid()); + r = mkdir(temp_dir, 0700); +#endif + if (r) { + fprintf(stderr, "Can't create directory %s:", temp_dir); + perror(""); + exit(1); + } + is_setup = 1; + temp_dir_setup_in_pid = getpid(); +} + +/** Return a filename relative to our testing temporary directory */ +const char * +get_fname(const char *name) +{ + static char buf[1024]; + setup_directory(); + if (!name) + return temp_dir; + tor_snprintf(buf,sizeof(buf),"%s/%s",temp_dir,name); + return buf; +} + +/** Remove all files stored under the temporary directory, and the directory + * itself. Called by atexit(). */ +static void +remove_directory(void) +{ + 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); + 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); + tor_free(tmp); + }); + SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); + smartlist_free(elements); + } + rmdir(temp_dir); +} + +/** Define this if unit tests spend too much time generating public keys*/ +#undef CACHE_GENERATED_KEYS + +static crypto_pk_env_t *pregen_keys[5] = {NULL, NULL, NULL, NULL, NULL}; +#define N_PREGEN_KEYS ((int)(sizeof(pregen_keys)/sizeof(pregen_keys[0]))) + +/** Generate and return a new keypair for use in unit tests. If we're using + * the key cache optimization, we might reuse keys: we only guarantee that + * keys made with distinct values for <b>idx</b> are different. The value of + * <b>idx</b> must be at least 0, and less than N_PREGEN_KEYS. */ +crypto_pk_env_t * +pk_generate(int idx) +{ +#ifdef CACHE_GENERATED_KEYS + tor_assert(idx < N_PREGEN_KEYS); + if (! pregen_keys[idx]) { + pregen_keys[idx] = crypto_new_pk_env(); + tor_assert(!crypto_pk_generate_key(pregen_keys[idx])); + } + return crypto_pk_dup_key(pregen_keys[idx]); +#else + crypto_pk_env_t *result; + (void) idx; + result = crypto_new_pk_env(); + tor_assert(!crypto_pk_generate_key(result)); + return result; +#endif +} + +/** Free all storage used for the cached key optimization. */ +static void +free_pregenerated_keys(void) +{ + unsigned idx; + for (idx = 0; idx < N_PREGEN_KEYS; ++idx) { + if (pregen_keys[idx]) { + crypto_free_pk_env(pregen_keys[idx]); + pregen_keys[idx] = NULL; + } + } +} + +/** Run unit tests for buffers.c */ +static void +test_buffers(void) +{ + char str[256]; + char str2[256]; + + buf_t *buf = NULL, *buf2 = NULL; + const char *cp; + + int j; + size_t r; + + /**** + * buf_new + ****/ + if (!(buf = buf_new())) + test_fail(); + + //test_eq(buf_capacity(buf), 4096); + test_eq(buf_datalen(buf), 0); + + /**** + * General pointer frobbing + */ + for (j=0;j<256;++j) { + str[j] = (char)j; + } + write_to_buf(str, 256, buf); + write_to_buf(str, 256, buf); + test_eq(buf_datalen(buf), 512); + fetch_from_buf(str2, 200, buf); + test_memeq(str, str2, 200); + test_eq(buf_datalen(buf), 312); + memset(str2, 0, sizeof(str2)); + + fetch_from_buf(str2, 256, buf); + test_memeq(str+200, str2, 56); + test_memeq(str, str2+56, 200); + test_eq(buf_datalen(buf), 56); + memset(str2, 0, sizeof(str2)); + /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add + * another 3584 bytes, we hit the end. */ + for (j=0;j<15;++j) { + write_to_buf(str, 256, buf); + } + assert_buf_ok(buf); + test_eq(buf_datalen(buf), 3896); + fetch_from_buf(str2, 56, buf); + test_eq(buf_datalen(buf), 3840); + test_memeq(str+200, str2, 56); + for (j=0;j<15;++j) { + memset(str2, 0, sizeof(str2)); + fetch_from_buf(str2, 256, buf); + test_memeq(str, str2, 256); + } + test_eq(buf_datalen(buf), 0); + buf_free(buf); + buf = NULL; + + /* Okay, now make sure growing can work. */ + buf = buf_new_with_capacity(16); + //test_eq(buf_capacity(buf), 16); + write_to_buf(str+1, 255, buf); + //test_eq(buf_capacity(buf), 256); + fetch_from_buf(str2, 254, buf); + test_memeq(str+1, str2, 254); + //test_eq(buf_capacity(buf), 256); + assert_buf_ok(buf); + write_to_buf(str, 32, buf); + //test_eq(buf_capacity(buf), 256); + assert_buf_ok(buf); + write_to_buf(str, 256, buf); + assert_buf_ok(buf); + //test_eq(buf_capacity(buf), 512); + test_eq(buf_datalen(buf), 33+256); + fetch_from_buf(str2, 33, buf); + test_eq(*str2, str[255]); + + test_memeq(str2+1, str, 32); + //test_eq(buf_capacity(buf), 512); + test_eq(buf_datalen(buf), 256); + fetch_from_buf(str2, 256, buf); + test_memeq(str, str2, 256); + + /* now try shrinking: case 1. */ + buf_free(buf); + buf = buf_new_with_capacity(33668); + for (j=0;j<67;++j) { + write_to_buf(str,255, buf); + } + //test_eq(buf_capacity(buf), 33668); + test_eq(buf_datalen(buf), 17085); + for (j=0; j < 40; ++j) { + fetch_from_buf(str2, 255,buf); + test_memeq(str2, str, 255); + } + + /* now try shrinking: case 2. */ + buf_free(buf); + buf = buf_new_with_capacity(33668); + for (j=0;j<67;++j) { + write_to_buf(str,255, buf); + } + for (j=0; j < 20; ++j) { + fetch_from_buf(str2, 255,buf); + test_memeq(str2, str, 255); + } + for (j=0;j<80;++j) { + write_to_buf(str,255, buf); + } + //test_eq(buf_capacity(buf),33668); + for (j=0; j < 120; ++j) { + fetch_from_buf(str2, 255,buf); + test_memeq(str2, str, 255); + } + + /* Move from buf to buf. */ + buf_free(buf); + buf = buf_new_with_capacity(4096); + buf2 = buf_new_with_capacity(4096); + for (j=0;j<100;++j) + write_to_buf(str, 255, buf); + test_eq(buf_datalen(buf), 25500); + for (j=0;j<100;++j) { + r = 10; + move_buf_to_buf(buf2, buf, &r); + test_eq(r, 0); + } + test_eq(buf_datalen(buf), 24500); + test_eq(buf_datalen(buf2), 1000); + for (j=0;j<3;++j) { + fetch_from_buf(str2, 255, buf2); + test_memeq(str2, str, 255); + } + r = 8192; /*big move*/ + move_buf_to_buf(buf2, buf, &r); + test_eq(r, 0); + r = 30000; /* incomplete move */ + move_buf_to_buf(buf2, buf, &r); + test_eq(r, 13692); + for (j=0;j<97;++j) { + fetch_from_buf(str2, 255, buf2); + test_memeq(str2, str, 255); + } + buf_free(buf); + buf_free(buf2); + buf = buf2 = NULL; + + buf = buf_new_with_capacity(5); + cp = "Testing. This is a moderately long Testing string."; + for (j = 0; cp[j]; j++) + write_to_buf(cp+j, 1, buf); + test_eq(0, buf_find_string_offset(buf, "Testing", 7)); + test_eq(1, buf_find_string_offset(buf, "esting", 6)); + test_eq(1, buf_find_string_offset(buf, "est", 3)); + test_eq(39, buf_find_string_offset(buf, "ing str", 7)); + test_eq(35, buf_find_string_offset(buf, "Testing str", 11)); + test_eq(32, buf_find_string_offset(buf, "ng ", 3)); + test_eq(43, buf_find_string_offset(buf, "string.", 7)); + test_eq(-1, buf_find_string_offset(buf, "shrdlu", 6)); + test_eq(-1, buf_find_string_offset(buf, "Testing thing", 13)); + test_eq(-1, buf_find_string_offset(buf, "ngx", 3)); + buf_free(buf); + buf = NULL; + + done: + if (buf) + buf_free(buf); + if (buf2) + buf_free(buf2); +} + +/** Run unit tests for the onion handshake code. */ +static void +test_onion_handshake(void) +{ + /* client-side */ + crypto_dh_env_t *c_dh = NULL; + char c_buf[ONIONSKIN_CHALLENGE_LEN]; + char c_keys[40]; + + /* server-side */ + char s_buf[ONIONSKIN_REPLY_LEN]; + char s_keys[40]; + + /* shared */ + crypto_pk_env_t *pk = NULL; + + pk = pk_generate(0); + + /* client handshake 1. */ + memset(c_buf, 0, ONIONSKIN_CHALLENGE_LEN); + test_assert(! onion_skin_create(pk, &c_dh, c_buf)); + + /* server handshake */ + memset(s_buf, 0, ONIONSKIN_REPLY_LEN); + memset(s_keys, 0, 40); + test_assert(! onion_skin_server_handshake(c_buf, pk, NULL, + s_buf, s_keys, 40)); + + /* client handshake 2 */ + memset(c_keys, 0, 40); + test_assert(! onion_skin_client_handshake(c_dh, s_buf, c_keys, 40)); + + if (memcmp(c_keys, s_keys, 40)) { + puts("Aiiiie"); + exit(1); + } + test_memeq(c_keys, s_keys, 40); + memset(s_buf, 0, 40); + test_memneq(c_keys, s_buf, 40); + + done: + if (c_dh) + crypto_dh_free(c_dh); + if (pk) + crypto_free_pk_env(pk); +} + +static void +test_circuit_timeout(void) +{ + /* Plan: + * 1. Generate 1000 samples + * 2. Estimate parameters + * 3. If difference, repeat + * 4. Save state + * 5. load state + * 6. Estimate parameters + * 7. compare differences + */ + circuit_build_times_t initial; + circuit_build_times_t estimate; + circuit_build_times_t final; + double timeout1, timeout2; + or_state_t state; + int i, runs; + double close_ms; + circuit_build_times_init(&initial); + circuit_build_times_init(&estimate); + circuit_build_times_init(&final); + + memset(&state, 0, sizeof(or_state_t)); + + circuitbuild_running_unit_tests(); +#define timeout0 (build_time_t)(30*1000.0) + initial.Xm = 3000; + circuit_build_times_initial_alpha(&initial, + CBT_DEFAULT_QUANTILE_CUTOFF/100.0, + timeout0); + close_ms = MAX(circuit_build_times_calculate_timeout(&initial, + CBT_DEFAULT_CLOSE_QUANTILE/100.0), + CBT_DEFAULT_TIMEOUT_INITIAL_VALUE); + do { + for (i=0; i < CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE; i++) { + build_time_t sample = circuit_build_times_generate_sample(&initial,0,1); + + if (sample > close_ms) { + circuit_build_times_add_time(&estimate, CBT_BUILD_ABANDONED); + } else { + circuit_build_times_add_time(&estimate, sample); + } + } + circuit_build_times_update_alpha(&estimate); + timeout1 = circuit_build_times_calculate_timeout(&estimate, + CBT_DEFAULT_QUANTILE_CUTOFF/100.0); + circuit_build_times_set_timeout(&estimate); + log_notice(LD_CIRC, "Timeout1 is %lf, Xm is %d", timeout1, estimate.Xm); + /* 2% error */ + } while (fabs(circuit_build_times_cdf(&initial, timeout0) - + circuit_build_times_cdf(&initial, timeout1)) > 0.02); + + test_assert(estimate.total_build_times <= CBT_NCIRCUITS_TO_OBSERVE); + + circuit_build_times_update_state(&estimate, &state); + test_assert(circuit_build_times_parse_state(&final, &state) == 0); + + circuit_build_times_update_alpha(&final); + timeout2 = circuit_build_times_calculate_timeout(&final, + CBT_DEFAULT_QUANTILE_CUTOFF/100.0); + + circuit_build_times_set_timeout(&final); + log_notice(LD_CIRC, "Timeout2 is %lf, Xm is %d", timeout2, final.Xm); + + /* 5% here because some accuracy is lost due to histogram conversion */ + test_assert(fabs(circuit_build_times_cdf(&initial, timeout0) - + circuit_build_times_cdf(&initial, timeout2)) < 0.05); + + for (runs = 0; runs < 50; runs++) { + int build_times_idx = 0; + int total_build_times = 0; + + final.close_ms = final.timeout_ms = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE; + estimate.close_ms = estimate.timeout_ms + = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE; + + for (i = 0; i < CBT_DEFAULT_RECENT_CIRCUITS*2; i++) { + circuit_build_times_network_circ_success(&estimate); + circuit_build_times_add_time(&estimate, + circuit_build_times_generate_sample(&estimate, 0, + CBT_DEFAULT_QUANTILE_CUTOFF/100.0)); + + circuit_build_times_network_circ_success(&estimate); + circuit_build_times_add_time(&final, + circuit_build_times_generate_sample(&final, 0, + CBT_DEFAULT_QUANTILE_CUTOFF/100.0)); + } + + test_assert(!circuit_build_times_network_check_changed(&estimate)); + test_assert(!circuit_build_times_network_check_changed(&final)); + + /* Reset liveness to be non-live */ + final.liveness.network_last_live = 0; + estimate.liveness.network_last_live = 0; + + build_times_idx = estimate.build_times_idx; + total_build_times = estimate.total_build_times; + + test_assert(circuit_build_times_network_check_live(&estimate)); + test_assert(circuit_build_times_network_check_live(&final)); + + circuit_build_times_count_close(&estimate, 0, + (time_t)(approx_time()-estimate.close_ms/1000.0-1)); + circuit_build_times_count_close(&final, 0, + (time_t)(approx_time()-final.close_ms/1000.0-1)); + + test_assert(!circuit_build_times_network_check_live(&estimate)); + test_assert(!circuit_build_times_network_check_live(&final)); + + log_info(LD_CIRC, "idx: %d %d, tot: %d %d", + build_times_idx, estimate.build_times_idx, + total_build_times, estimate.total_build_times); + + /* Check rollback index. Should match top of loop. */ + test_assert(build_times_idx == estimate.build_times_idx); + // This can fail if estimate.total_build_times == 1000, because + // in that case, rewind actually causes us to lose timeouts + if (total_build_times != CBT_NCIRCUITS_TO_OBSERVE) + test_assert(total_build_times == estimate.total_build_times); + + /* Now simulate that the network has become live and we need + * a change */ + circuit_build_times_network_is_live(&estimate); + circuit_build_times_network_is_live(&final); + + for (i = 0; i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT; i++) { + circuit_build_times_count_timeout(&estimate, 1); + + if (i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1) { + circuit_build_times_count_timeout(&final, 1); + } + } + + test_assert(estimate.liveness.after_firsthop_idx == 0); + test_assert(final.liveness.after_firsthop_idx == + CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1); + + test_assert(circuit_build_times_network_check_live(&estimate)); + test_assert(circuit_build_times_network_check_live(&final)); + + circuit_build_times_count_timeout(&final, 1); + } + + done: + return; +} + +/** Helper: Parse the exit policy string in <b>policy_str</b>, and make sure + * that policies_summarize() produces the string <b>expected_summary</b> from + * it. */ +static void +test_policy_summary_helper(const char *policy_str, + const char *expected_summary) +{ + config_line_t line; + smartlist_t *policy = smartlist_create(); + char *summary = NULL; + int r; + + line.key = (char*)"foo"; + line.value = (char *)policy_str; + line.next = NULL; + + r = policies_parse_exit_policy(&line, &policy, 0, NULL, 1); + test_eq(r, 0); + summary = policy_summarize(policy); + + test_assert(summary != NULL); + test_streq(summary, expected_summary); + + done: + tor_free(summary); + if (policy) + addr_policy_list_free(policy); +} + +/** Run unit tests for generating summary lines of exit policies */ +static void +test_policies(void) +{ + int i; + smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL, + *policy4 = NULL, *policy5 = NULL, *policy6 = NULL, + *policy7 = NULL; + addr_policy_t *p; + tor_addr_t tar; + config_line_t line; + smartlist_t *sm = NULL; + char *policy_str = NULL; + + policy = smartlist_create(); + + p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); + test_assert(p != NULL); + test_eq(ADDR_POLICY_REJECT, p->policy_type); + tor_addr_from_ipv4h(&tar, 0xc0a80000u); + test_eq(0, tor_addr_compare(&p->addr, &tar, CMP_EXACT)); + test_eq(16, p->maskbits); + test_eq(1, p->prt_min); + test_eq(65535, p->prt_max); + + smartlist_add(policy, p); + + test_assert(ADDR_POLICY_ACCEPTED == + compare_addr_to_addr_policy(0x01020304u, 2, policy)); + test_assert(ADDR_POLICY_PROBABLY_ACCEPTED == + compare_addr_to_addr_policy(0, 2, policy)); + test_assert(ADDR_POLICY_REJECTED == + compare_addr_to_addr_policy(0xc0a80102, 2, policy)); + + test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, NULL, 1)); + test_assert(policy2); + + policy3 = smartlist_create(); + p = router_parse_addr_policy_item_from_string("reject *:*",-1); + test_assert(p != NULL); + smartlist_add(policy3, p); + p = router_parse_addr_policy_item_from_string("accept *:*",-1); + test_assert(p != NULL); + smartlist_add(policy3, p); + + policy4 = smartlist_create(); + p = router_parse_addr_policy_item_from_string("accept *:443",-1); + test_assert(p != NULL); + smartlist_add(policy4, p); + p = router_parse_addr_policy_item_from_string("accept *:443",-1); + test_assert(p != NULL); + smartlist_add(policy4, p); + + policy5 = smartlist_create(); + p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject *:1-65534",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("reject *:65535",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + p = router_parse_addr_policy_item_from_string("accept *:1-65535",-1); + test_assert(p != NULL); + smartlist_add(policy5, p); + + policy6 = smartlist_create(); + p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*",-1); + test_assert(p != NULL); + smartlist_add(policy6, p); + + policy7 = smartlist_create(); + p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*",-1); + test_assert(p != NULL); + smartlist_add(policy7, p); + + test_assert(!exit_policy_is_general_exit(policy)); + test_assert(exit_policy_is_general_exit(policy2)); + test_assert(!exit_policy_is_general_exit(NULL)); + test_assert(!exit_policy_is_general_exit(policy3)); + test_assert(!exit_policy_is_general_exit(policy4)); + test_assert(!exit_policy_is_general_exit(policy5)); + test_assert(!exit_policy_is_general_exit(policy6)); + test_assert(!exit_policy_is_general_exit(policy7)); + + test_assert(cmp_addr_policies(policy, policy2)); + test_assert(cmp_addr_policies(policy, NULL)); + test_assert(!cmp_addr_policies(policy2, policy2)); + test_assert(!cmp_addr_policies(NULL, NULL)); + + test_assert(!policy_is_reject_star(policy2)); + test_assert(policy_is_reject_star(policy)); + test_assert(policy_is_reject_star(NULL)); + + addr_policy_list_free(policy); + policy = NULL; + + /* make sure compacting logic works. */ + policy = NULL; + line.key = (char*)"foo"; + line.value = (char*)"accept *:80,reject private:*,reject *:*"; + line.next = NULL; + test_assert(0 == policies_parse_exit_policy(&line, &policy, 0, NULL, 1)); + test_assert(policy); + //test_streq(policy->string, "accept *:80"); + //test_streq(policy->next->string, "reject *:*"); + test_eq(smartlist_len(policy), 2); + + /* test policy summaries */ + /* check if we properly ignore private IP addresses */ + test_policy_summary_helper("reject 192.168.0.0/16:*," + "reject 0.0.0.0/8:*," + "reject 10.0.0.0/8:*," + "accept *:10-30," + "accept *:90," + "reject *:*", + "accept 10-30,90"); + /* check all accept policies, and proper counting of rejects */ + test_policy_summary_helper("reject 11.0.0.0/9:80," + "reject 12.0.0.0/9:80," + "reject 13.0.0.0/9:80," + "reject 14.0.0.0/9:80," + "accept *:*", "accept 1-65535"); + test_policy_summary_helper("reject 11.0.0.0/9:80," + "reject 12.0.0.0/9:80," + "reject 13.0.0.0/9:80," + "reject 14.0.0.0/9:80," + "reject 15.0.0.0:81," + "accept *:*", "accept 1-65535"); + test_policy_summary_helper("reject 11.0.0.0/9:80," + "reject 12.0.0.0/9:80," + "reject 13.0.0.0/9:80," + "reject 14.0.0.0/9:80," + "reject 15.0.0.0:80," + "accept *:*", + "reject 80"); + /* no exits */ + test_policy_summary_helper("accept 11.0.0.0/9:80," + "reject *:*", + "reject 1-65535"); + /* port merging */ + test_policy_summary_helper("accept *:80," + "accept *:81," + "accept *:100-110," + "accept *:111," + "reject *:*", + "accept 80-81,100-111"); + /* border ports */ + test_policy_summary_helper("accept *:1," + "accept *:3," + "accept *:65535," + "reject *:*", + "accept 1,3,65535"); + /* holes */ + test_policy_summary_helper("accept *:1," + "accept *:3," + "accept *:5," + "accept *:7," + "reject *:*", + "accept 1,3,5,7"); + test_policy_summary_helper("reject *:1," + "reject *:3," + "reject *:5," + "reject *:7," + "accept *:*", + "reject 1,3,5,7"); + + /* truncation ports */ + sm = smartlist_create(); + for (i=1; i<2000; i+=2) { + char buf[POLICY_BUF_LEN]; + tor_snprintf(buf, sizeof(buf), "reject *:%d", i); + smartlist_add(sm, tor_strdup(buf)); + } + smartlist_add(sm, tor_strdup("accept *:*")); + policy_str = smartlist_join_strings(sm, ",", 0, NULL); + test_policy_summary_helper( policy_str, + "accept 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44," + "46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90," + "92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128," + "130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164," + "166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200," + "202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236," + "238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272," + "274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308," + "310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344," + "346,348,350,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380," + "382,384,386,388,390,392,394,396,398,400,402,404,406,408,410,412,414,416," + "418,420,422,424,426,428,430,432,434,436,438,440,442,444,446,448,450,452," + "454,456,458,460,462,464,466,468,470,472,474,476,478,480,482,484,486,488," + "490,492,494,496,498,500,502,504,506,508,510,512,514,516,518,520,522"); + + done: + addr_policy_list_free(policy); + addr_policy_list_free(policy2); + addr_policy_list_free(policy3); + addr_policy_list_free(policy4); + addr_policy_list_free(policy5); + addr_policy_list_free(policy6); + addr_policy_list_free(policy7); + tor_free(policy_str); + if (sm) { + SMARTLIST_FOREACH(sm, char *, s, tor_free(s)); + smartlist_free(sm); + } +} + +/** 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) +{ + rend_service_descriptor_t *generated = NULL, *parsed = NULL; + char service_id[DIGEST_LEN]; + char service_id_base32[REND_SERVICE_ID_LEN_BASE32+1]; + const char *next_desc; + smartlist_t *descs = smartlist_create(); + char computed_desc_id[DIGEST_LEN]; + char parsed_desc_id[DIGEST_LEN]; + crypto_pk_env_t *pk1 = NULL, *pk2 = NULL; + time_t now; + char *intro_points_encrypted = NULL; + size_t intro_points_size; + size_t encoded_size; + int i; + char address1[] = "fooaddress.onion"; + char address2[] = "aaaaaaaaaaaaaaaa.onion"; + char address3[] = "fooaddress.exit"; + char address4[] = "www.torproject.org"; + + test_assert(BAD_HOSTNAME == parse_extended_hostname(address1, 1)); + test_assert(ONION_HOSTNAME == parse_extended_hostname(address2, 1)); + test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3, 1)); + test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4, 1)); + + pk1 = pk_generate(0); + pk2 = pk_generate(1); + generated = tor_malloc_zero(sizeof(rend_service_descriptor_t)); + generated->pk = crypto_pk_dup_key(pk1); + crypto_pk_get_digest(generated->pk, service_id); + base32_encode(service_id_base32, REND_SERVICE_ID_LEN_BASE32+1, + service_id, REND_SERVICE_ID_LEN); + now = time(NULL); + generated->timestamp = now; + generated->version = 2; + generated->protocols = 42; + generated->intro_nodes = smartlist_create(); + + for (i = 0; i < 3; i++) { + rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t)); + crypto_pk_env_t *okey = pk_generate(2 + i); + intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); + intro->extend_info->onion_key = okey; + crypto_pk_get_digest(intro->extend_info->onion_key, + intro->extend_info->identity_digest); + //crypto_rand(info->identity_digest, DIGEST_LEN); /* Would this work? */ + intro->extend_info->nickname[0] = '$'; + base16_encode(intro->extend_info->nickname + 1, + sizeof(intro->extend_info->nickname) - 1, + intro->extend_info->identity_digest, DIGEST_LEN); + /* Does not cover all IP addresses. */ + tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536)); + intro->extend_info->port = 1 + crypto_rand_int(65535); + intro->intro_key = crypto_pk_dup_key(pk2); + smartlist_add(generated->intro_nodes, intro); + } + test_assert(rend_encode_v2_descriptors(descs, generated, now, 0, + REND_NO_AUTH, NULL, NULL) > 0); + test_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32, + NULL, now, 0) == 0); + test_memeq(((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0))->desc_id, computed_desc_id, DIGEST_LEN); + test_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id, + &intro_points_encrypted, + &intro_points_size, + &encoded_size, + &next_desc, + ((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0))->desc_str) == 0); + test_assert(parsed); + test_memeq(((rend_encoded_v2_service_descriptor_t *) + smartlist_get(descs, 0))->desc_id, parsed_desc_id, DIGEST_LEN); + test_eq(rend_parse_introduction_points(parsed, intro_points_encrypted, + intro_points_size), 3); + test_assert(!crypto_pk_cmp_keys(generated->pk, parsed->pk)); + test_eq(parsed->timestamp, now); + test_eq(parsed->version, 2); + test_eq(parsed->protocols, 42); + test_eq(smartlist_len(parsed->intro_nodes), 3); + for (i = 0; i < smartlist_len(parsed->intro_nodes); i++) { + rend_intro_point_t *par_intro = smartlist_get(parsed->intro_nodes, i), + *gen_intro = smartlist_get(generated->intro_nodes, i); + extend_info_t *par_info = par_intro->extend_info; + extend_info_t *gen_info = gen_intro->extend_info; + test_assert(!crypto_pk_cmp_keys(gen_info->onion_key, par_info->onion_key)); + test_memeq(gen_info->identity_digest, par_info->identity_digest, + DIGEST_LEN); + test_streq(gen_info->nickname, par_info->nickname); + test_assert(tor_addr_eq(&gen_info->addr, &par_info->addr)); + test_eq(gen_info->port, par_info->port); + } + + rend_service_descriptor_free(parsed); + rend_service_descriptor_free(generated); + parsed = generated = NULL; + + done: + if (descs) { + for (i = 0; i < smartlist_len(descs); i++) + rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i)); + smartlist_free(descs); + } + if (parsed) + rend_service_descriptor_free(parsed); + if (generated) + rend_service_descriptor_free(generated); + if (pk1) + crypto_free_pk_env(pk1); + if (pk2) + crypto_free_pk_env(pk2); + tor_free(intro_points_encrypted); +} + +/** Run unit tests for GeoIP code. */ +static void +test_geoip(void) +{ + int i, j; + time_t now = time(NULL); + char *s = NULL; + + /* 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 + * fine uint32_t values. */ + test_eq(0, geoip_parse_entry("10,50,AB")); + test_eq(0, geoip_parse_entry("52,90,XY")); + test_eq(0, geoip_parse_entry("95,100,AB")); + test_eq(0, geoip_parse_entry("\"105\",\"140\",\"ZZ\"")); + test_eq(0, geoip_parse_entry("\"150\",\"190\",\"XY\"")); + test_eq(0, geoip_parse_entry("\"200\",\"250\",\"AB\"")); + + /* We should have 4 countries: ??, ab, xy, zz. */ + test_eq(4, geoip_get_n_countries()); + /* Make sure that country ID actually works. */ +#define NAMEFOR(x) geoip_get_country_name(geoip_get_country_by_ip(x)) + test_streq("??", NAMEFOR(3)); + test_eq(0, geoip_get_country_by_ip(3)); + test_streq("ab", NAMEFOR(32)); + test_streq("??", NAMEFOR(5)); + test_streq("??", NAMEFOR(51)); + test_streq("xy", NAMEFOR(150)); + test_streq("xy", NAMEFOR(190)); + test_streq("??", NAMEFOR(2000)); +#undef NAMEFOR + + get_options()->BridgeRelay = 1; + get_options()->BridgeRecordUsageByCountry = 1; + /* Put 9 observations in AB... */ + for (i=32; i < 40; ++i) + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-7200); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 225, now-7200); + /* and 3 observations in XY, several times. */ + for (j=0; j < 10; ++j) + for (i=52; i < 55; ++i) + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-3600); + /* and 17 observations in ZZ... */ + for (i=110; i < 127; ++i) + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now); + s = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + test_assert(s); + test_streq("zz=24,ab=16,xy=8", s); + tor_free(s); + + /* Now clear out all the AB observations. */ + geoip_remove_old_clients(now-6000); + s = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + test_assert(s); + test_streq("zz=24,xy=8", s); + + done: + tor_free(s); +} + +/** Run unit tests for stats code. */ +static void +test_stats(void) +{ + time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ + char *s = NULL; + int i; + + /* 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); + test_assert(!s); + + /* Initialize stats, note some streams and bytes, and generate history + * string. */ + rep_hist_exit_stats_init(now); + rep_hist_note_exit_stream_opened(80); + rep_hist_note_exit_bytes(80, 100, 10000); + rep_hist_note_exit_stream_opened(443); + rep_hist_note_exit_bytes(443, 100, 10000); + rep_hist_note_exit_bytes(443, 100, 10000); + s = rep_hist_format_exit_stats(now + 86400); + test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "exit-kibibytes-written 80=1,443=1,other=0\n" + "exit-kibibytes-read 80=10,443=20,other=0\n" + "exit-streams-opened 80=4,443=4,other=0\n", s); + tor_free(s); + + /* Add a few bytes on 10 more ports and ensure that only the top 10 + * ports are contained in the history string. */ + for (i = 50; i < 60; i++) { + rep_hist_note_exit_bytes(i, i, i); + rep_hist_note_exit_stream_opened(i); + } + s = rep_hist_format_exit_stats(now + 86400); + test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1," + "59=1,80=1,443=1,other=1\n" + "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1," + "59=1,80=10,443=20,other=1\n" + "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4," + "59=4,80=4,443=4,other=4\n", s); + tor_free(s); + + /* Stop collecting stats, add some bytes, and ensure we don't generate + * a history string. */ + rep_hist_exit_stats_term(); + rep_hist_note_exit_bytes(80, 100, 10000); + s = rep_hist_format_exit_stats(now + 86400); + 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. */ + rep_hist_exit_stats_init(now); + rep_hist_note_exit_stream_opened(80); + rep_hist_note_exit_bytes(80, 100, 10000); + rep_hist_reset_exit_stats(now); + s = rep_hist_format_exit_stats(now + 86400); + test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "exit-kibibytes-written other=0\n" + "exit-kibibytes-read other=0\n" + "exit-streams-opened other=0\n", s); + + done: + tor_free(s); +} + +static void * +legacy_test_setup(const struct testcase_t *testcase) +{ + return testcase->setup_data; +} + +void +legacy_test_helper(void *data) +{ + void (*fn)(void) = data; + fn(); +} + +static int +legacy_test_cleanup(const struct testcase_t *testcase, void *ptr) +{ + (void)ptr; + (void)testcase; + return 1; +} + +const struct testcase_setup_t legacy_setup = { + legacy_test_setup, legacy_test_cleanup +}; + +#define ENT(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_ ## name } +#define SUBENT(group, name) \ + { #group "_" #name, legacy_test_helper, 0, &legacy_setup, \ + test_ ## group ## _ ## name } +#define DISABLED(name) \ + { #name, legacy_test_helper, TT_SKIP, &legacy_setup, name } +#define FORK(name) \ + { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_ ## name } + +static struct testcase_t test_array[] = { + ENT(buffers), + ENT(onion_handshake), + ENT(circuit_timeout), + ENT(policies), + ENT(rend_fns), + ENT(geoip), + FORK(stats), + + DISABLED(bench_aes), + DISABLED(bench_dmap), + END_OF_TESTCASES +}; + +extern struct testcase_t addr_tests[]; +extern struct testcase_t crypto_tests[]; +extern struct testcase_t container_tests[]; +extern struct testcase_t util_tests[]; +extern struct testcase_t dir_tests[]; + +static struct testgroup_t testgroups[] = { + { "", test_array }, + { "addr/", addr_tests }, + { "crypto/", crypto_tests }, + { "container/", container_tests }, + { "util/", util_tests }, + { "dir/", dir_tests }, + END_OF_GROUPS +}; + +/** Main entry point for unit test code: parse the command line, and run + * some unit tests. */ +int +main(int c, const char **v) +{ + or_options_t *options; + char *errmsg = NULL; + int i, i_out; + int loglevel = LOG_ERR; + +#ifdef USE_DMALLOC + { + int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc, _tor_free); + tor_assert(r); + } +#endif + + update_approx_time(time(NULL)); + options = options_new(); + tor_threads_init(); + init_logging(); + + for (i_out = i = 1; i < c; ++i) { + if (!strcmp(v[i], "--warn")) { + loglevel = LOG_WARN; + } else if (!strcmp(v[i], "--notice")) { + loglevel = LOG_NOTICE; + } else if (!strcmp(v[i], "--info")) { + loglevel = LOG_INFO; + } else if (!strcmp(v[i], "--debug")) { + loglevel = LOG_DEBUG; + } else { + v[i_out++] = v[i]; + } + } + c = i_out; + + { + log_severity_list_t s; + memset(&s, 0, sizeof(s)); + set_log_severity_config(loglevel, LOG_ERR, &s); + add_stream_log(&s, "", fileno(stdout)); + } + + options->command = CMD_RUN_UNITTESTS; + crypto_global_init(0, NULL, NULL); + rep_hist_init(); + network_init(); + setup_directory(); + options_init(options); + options->DataDirectory = tor_strdup(temp_dir); + options->EntryStatistics = 1; + if (set_options(options, &errmsg) < 0) { + printf("Failed to set initial options: %s\n", errmsg); + tor_free(errmsg); + return 1; + } + + crypto_seed_rng(1); + + atexit(remove_directory); + + have_failed = (tinytest_main(c, v, testgroups) != 0); + + free_pregenerated_keys(); +#ifdef USE_DMALLOC + tor_free_all(0); + dmalloc_log_unfreed(); +#endif + + if (have_failed) + return 1; + else + return 0; +} + diff --git a/src/test/test.h b/src/test/test.h new file mode 100644 index 0000000000..550c57a812 --- /dev/null +++ b/src/test/test.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2001-2003, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef _TOR_TEST_H +#define _TOR_TEST_H + +/** + * \file test.h + * \brief Macros and functions used by unit tests. + */ + +#include "compat.h" +#include "tinytest.h" +#define TT_EXIT_TEST_FUNCTION STMT_BEGIN goto done; STMT_END +#include "tinytest_macros.h" + +#ifdef __GNUC__ +#define PRETTY_FUNCTION __PRETTY_FUNCTION__ +#else +#define PRETTY_FUNCTION "" +#endif + +#define test_fail_msg(msg) TT_DIE((msg)) + +#define test_fail() test_fail_msg("Assertion failed.") + +#define test_assert(expr) tt_assert(expr) + +#define test_eq(expr1, expr2) tt_int_op((expr1), ==, (expr2)) +#define test_eq_ptr(expr1, expr2) tt_ptr_op((expr1), ==, (expr2)) +#define test_neq(expr1, expr2) tt_int_op((expr1), !=, (expr2)) +#define test_neq_ptr(expr1, expr2) tt_ptr_op((expr1), !=, (expr2)) +#define test_streq(expr1, expr2) tt_str_op((expr1), ==, (expr2)) +#define test_strneq(expr1, expr2) tt_str_op((expr1), !=, (expr2)) +#define test_streq(expr1, expr2) tt_str_op((expr1), ==, (expr2)) + +#define test_mem_op(expr1, op, expr2, len) \ + tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2, \ + const char *, \ + (memcmp(_val1, _val2, len) op 0), \ + char *, "%s", \ + { size_t printlen = (len)*2+1; \ + _print = tor_malloc(printlen); \ + base16_encode(_print, printlen, _value, \ + (len)); }, \ + { tor_free(_print); } \ + ); + +#define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len) +#define test_memneq(expr1, expr2, len) test_mem_op((expr1), !=, (expr2), len) + +/* As test_mem_op, but decodes 'hex' before comparing. There must be a + * local char* variable called mem_op_hex_tmp for this to work. */ +#define test_mem_op_hex(expr1, op, hex) \ + STMT_BEGIN \ + size_t length = strlen(hex); \ + tor_free(mem_op_hex_tmp); \ + mem_op_hex_tmp = tor_malloc(length/2); \ + tor_assert((length&1)==0); \ + base16_decode(mem_op_hex_tmp, length/2, hex, length); \ + test_mem_op(expr1, op, mem_op_hex_tmp, length/2); \ + STMT_END + +#define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, ==, hex) + +const char *get_fname(const char *name); +crypto_pk_env_t *pk_generate(int idx); + +void legacy_test_helper(void *data); +extern const struct testcase_setup_t legacy_setup; + +#endif + diff --git a/src/test/test_addr.c b/src/test/test_addr.c new file mode 100644 index 0000000000..bafc0a968e --- /dev/null +++ b/src/test/test_addr.c @@ -0,0 +1,497 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "or.h" +#include "test.h" + +static void +test_addr_basic(void) +{ + uint32_t u32; + uint16_t u16; + char *cp; + + /* Test parse_addr_port */ + cp = NULL; u32 = 3; u16 = 3; + test_assert(!parse_addr_port(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_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", + &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_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_eq(cp, NULL); + test_eq(u32, 0x7f000001u); + test_eq(u16, 0); + tor_free(cp); + test_eq(0, addr_mask_get_bits(0x0u)); + test_eq(32, addr_mask_get_bits(0xFFFFFFFFu)); + test_eq(16, addr_mask_get_bits(0xFFFF0000u)); + test_eq(31, addr_mask_get_bits(0xFFFFFFFEu)); + test_eq(1, addr_mask_get_bits(0x80000000u)); + + /* Test inet_ntop */ + { + 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)); + test_streq(tmpbuf, ip); + } + + done: + ; +} + +#define _test_op_ip6(a,op,b,e1,e2) \ + STMT_BEGIN \ + tt_assert_test_fmt_type(a,b,e1" "#op" "e2,struct in6_addr*, \ + (memcmp(_val1->s6_addr, _val2->s6_addr, 16) op 0), \ + char *, "%s", \ + { int i; char *cp; \ + cp = _print = tor_malloc(64); \ + for (i=0;i<16;++i) { \ + tor_snprintf(cp, 3,"%02x", (unsigned)_value->s6_addr[i]);\ + cp += 2; \ + if (i != 15) *cp++ = ':'; \ + } \ + }, { tor_free(_print); } \ + ); \ + STMT_END + +/** Helper: Assert that two strings both decode as IPv6 addresses with + * tor_inet_pton(), and both decode to the same address. */ +#define test_pton6_same(a,b) STMT_BEGIN \ + test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \ + test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \ + _test_op_ip6(&a1,==,&a2,#a,#b); \ + STMT_END + +/** Helper: Assert that <b>a</b> is recognized as a bad IPv6 address by + * tor_inet_pton(). */ +#define test_pton6_bad(a) \ + test_eq(0, tor_inet_pton(AF_INET6, a, &a1)) + +/** Helper: assert that <b>a</b>, when parsed by tor_inet_pton() and displayed + * with tor_inet_ntop(), yields <b>b</b>. Also assert that <b>b</b> parses to + * the same value as <b>a</b>. */ +#define test_ntop6_reduces(a,b) STMT_BEGIN \ + test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \ + test_streq(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), b); \ + test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \ + _test_op_ip6(&a1, ==, &a2, a, b); \ + STMT_END + +/** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that + * passes tor_addr_is_internal() with <b>for_listening</b>. */ +#define test_internal_ip(a,for_listening) STMT_BEGIN \ + test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ + t1.family = AF_INET6; \ + if (!tor_addr_is_internal(&t1, for_listening)) \ + test_fail_msg( a "was not internal."); \ + STMT_END + +/** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that + * does not pass tor_addr_is_internal() with <b>for_listening</b>. */ +#define test_external_ip(a,for_listening) STMT_BEGIN \ + test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ + t1.family = AF_INET6; \ + if (tor_addr_is_internal(&t1, for_listening)) \ + test_fail_msg(a "was not external."); \ + STMT_END + +/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by + * tor_inet_pton(), give addresses that compare in the order defined by + * <b>op</b> with tor_addr_compare(). */ +#define test_addr_compare(a, op, b) STMT_BEGIN \ + test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ + test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \ + t1.family = t2.family = AF_INET6; \ + r = tor_addr_compare(&t1,&t2,CMP_SEMANTIC); \ + if (!(r op 0)) \ + test_fail_msg("failed: tor_addr_compare("a","b") "#op" 0"); \ + STMT_END + +/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by + * tor_inet_pton(), give addresses that compare in the order defined by + * <b>op</b> with tor_addr_compare_masked() with <b>m</b> masked. */ +#define test_addr_compare_masked(a, op, b, m) STMT_BEGIN \ + test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \ + test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \ + t1.family = t2.family = AF_INET6; \ + r = tor_addr_compare_masked(&t1,&t2,m,CMP_SEMANTIC); \ + if (!(r op 0)) \ + test_fail_msg("failed: tor_addr_compare_masked("a","b","#m") "#op" 0"); \ + STMT_END + +/** Helper: assert that <b>xx</b> is parseable as a masked IPv6 address with + * ports by tor_parse_mask_addr_ports(), with family <b>f</b>, IP address + * as 4 32-bit words <b>ip1...ip4</b>, mask bits as <b>mm</b>, and port range + * as <b>pt1..pt2</b>. */ +#define test_addr_mask_ports_parse(xx, f, ip1, ip2, ip3, ip4, mm, pt1, pt2) \ + STMT_BEGIN \ + test_eq(tor_addr_parse_mask_ports(xx, &t1, &mask, &port1, &port2), f); \ + p1=tor_inet_ntop(AF_INET6, &t1.addr.in6_addr, bug, sizeof(bug)); \ + test_eq(htonl(ip1), tor_addr_to_in6_addr32(&t1)[0]); \ + test_eq(htonl(ip2), tor_addr_to_in6_addr32(&t1)[1]); \ + test_eq(htonl(ip3), tor_addr_to_in6_addr32(&t1)[2]); \ + test_eq(htonl(ip4), tor_addr_to_in6_addr32(&t1)[3]); \ + test_eq(mask, mm); \ + test_eq(port1, pt1); \ + test_eq(port2, pt2); \ + STMT_END + +/** Run unit tests for IPv6 encoding/decoding/manipulation functions. */ +static void +test_addr_ip6_helpers(void) +{ + char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN]; + struct in6_addr a1, a2; + tor_addr_t t1, t2; + int r, i; + uint16_t port1, port2; + maskbits_t mask; + const char *p1; + struct sockaddr_storage sa_storage; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + // struct in_addr b1, b2; + /* Test tor_inet_ntop and tor_inet_pton: IPv6 */ + + /* ==== Converting to and from sockaddr_t. */ + sin = (struct sockaddr_in *)&sa_storage; + sin->sin_family = AF_INET; + sin->sin_port = 9090; + sin->sin_addr.s_addr = htonl(0x7f7f0102); /*127.127.1.2*/ + tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL); + test_eq(tor_addr_family(&t1), AF_INET); + test_eq(tor_addr_to_ipv4h(&t1), 0x7f7f0102); + + memset(&sa_storage, 0, sizeof(sa_storage)); + test_eq(sizeof(struct sockaddr_in), + tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage, + sizeof(sa_storage))); + test_eq(1234, ntohs(sin->sin_port)); + test_eq(0x7f7f0102, ntohl(sin->sin_addr.s_addr)); + + memset(&sa_storage, 0, sizeof(sa_storage)); + sin6 = (struct sockaddr_in6 *)&sa_storage; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = htons(7070); + sin6->sin6_addr.s6_addr[0] = 128; + tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL); + test_eq(tor_addr_family(&t1), AF_INET6); + p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0); + test_streq(p1, "8000::"); + + memset(&sa_storage, 0, sizeof(sa_storage)); + test_eq(sizeof(struct sockaddr_in6), + tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage, + sizeof(sa_storage))); + test_eq(AF_INET6, sin6->sin6_family); + test_eq(9999, ntohs(sin6->sin6_port)); + test_eq(0x80000000, ntohl(S6_ADDR32(sin6->sin6_addr)[0])); + + /* ==== tor_addr_lookup: static cases. (Can't test dns without knowing we + * have a good resolver. */ + test_eq(0, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1)); + test_eq(AF_INET, tor_addr_family(&t1)); + test_eq(tor_addr_to_ipv4h(&t1), 0x7f808182); + + test_eq(0, tor_addr_lookup("9000::5", AF_UNSPEC, &t1)); + test_eq(AF_INET6, tor_addr_family(&t1)); + test_eq(0x90, tor_addr_to_in6_addr8(&t1)[0]); + test_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14)); + test_eq(0x05, tor_addr_to_in6_addr8(&t1)[15]); + + /* === Test pton: valid af_inet6 */ + /* Simple, valid parsing. */ + r = tor_inet_pton(AF_INET6, + "0102:0304:0506:0708:090A:0B0C:0D0E:0F10", &a1); + test_assert(r==1); + for (i=0;i<16;++i) { test_eq(i+1, (int)a1.s6_addr[i]); } + /* ipv4 ending. */ + test_pton6_same("0102:0304:0506:0708:090A:0B0C:0D0E:0F10", + "0102:0304:0506:0708:090A:0B0C:13.14.15.16"); + /* shortened words. */ + test_pton6_same("0001:0099:BEEF:0000:0123:FFFF:0001:0001", + "1:99:BEEF:0:0123:FFFF:1:1"); + /* zeros at the beginning */ + test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001", + "::9:c0a8:1:1"); + test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001", + "::9:c0a8:0.1.0.1"); + /* zeros in the middle. */ + test_pton6_same("fe80:0000:0000:0000:0202:1111:0001:0001", + "fe80::202:1111:1:1"); + /* zeros at the end. */ + test_pton6_same("1000:0001:0000:0007:0000:0000:0000:0000", + "1000:1:0:7::"); + + /* === Test ntop: af_inet6 */ + test_ntop6_reduces("0:0:0:0:0:0:0:0", "::"); + + test_ntop6_reduces("0001:0099:BEEF:0006:0123:FFFF:0001:0001", + "1:99:beef:6:123:ffff:1:1"); + + //test_ntop6_reduces("0:0:0:0:0:0:c0a8:0101", "::192.168.1.1"); + test_ntop6_reduces("0:0:0:0:0:ffff:c0a8:0101", "::ffff:192.168.1.1"); + test_ntop6_reduces("002:0:0000:0:3::4", "2::3:0:0:4"); + test_ntop6_reduces("0:0::1:0:3", "::1:0:3"); + test_ntop6_reduces("008:0::0", "8::"); + test_ntop6_reduces("0:0:0:0:0:ffff::1", "::ffff:0.0.0.1"); + test_ntop6_reduces("abcd:0:0:0:0:0:7f00::", "abcd::7f00:0"); + test_ntop6_reduces("0000:0000:0000:0000:0009:C0A8:0001:0001", + "::9:c0a8:1:1"); + test_ntop6_reduces("fe80:0000:0000:0000:0202:1111:0001:0001", + "fe80::202:1111:1:1"); + test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000", + "1000:1:0:7::"); + + /* === Test pton: invalid in6. */ + test_pton6_bad("foobar."); + test_pton6_bad("55555::"); + test_pton6_bad("9:-60::"); + 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"); + test_pton6_bad("1:2:3:4:5:6:1.2.3.4.5"); + 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("99"); + test_pton6_bad(""); + test_pton6_bad("1::2::3:4"); + test_pton6_bad("a:::b:c"); + test_pton6_bad(":::a:b:c"); + test_pton6_bad("a:b:c:::"); + + /* test internal checking */ + test_external_ip("fbff:ffff::2:7", 0); + test_internal_ip("fc01::2:7", 0); + test_internal_ip("fdff:ffff::f:f", 0); + test_external_ip("fe00::3:f", 0); + + test_external_ip("fe7f:ffff::2:7", 0); + test_internal_ip("fe80::2:7", 0); + test_internal_ip("febf:ffff::f:f", 0); + + test_internal_ip("fec0::2:7:7", 0); + test_internal_ip("feff:ffff::e:7:7", 0); + test_external_ip("ff00::e:7:7", 0); + + test_internal_ip("::", 0); + test_internal_ip("::1", 0); + test_internal_ip("::1", 1); + test_internal_ip("::", 0); + test_external_ip("::", 1); + test_external_ip("::2", 0); + test_external_ip("2001::", 0); + test_external_ip("ffff::", 0); + + test_external_ip("::ffff:0.0.0.0", 1); + test_internal_ip("::ffff:0.0.0.0", 0); + test_internal_ip("::ffff:0.255.255.255", 0); + test_external_ip("::ffff:1.0.0.0", 0); + + test_external_ip("::ffff:9.255.255.255", 0); + test_internal_ip("::ffff:10.0.0.0", 0); + test_internal_ip("::ffff:10.255.255.255", 0); + test_external_ip("::ffff:11.0.0.0", 0); + + test_external_ip("::ffff:126.255.255.255", 0); + test_internal_ip("::ffff:127.0.0.0", 0); + test_internal_ip("::ffff:127.255.255.255", 0); + test_external_ip("::ffff:128.0.0.0", 0); + + test_external_ip("::ffff:172.15.255.255", 0); + test_internal_ip("::ffff:172.16.0.0", 0); + test_internal_ip("::ffff:172.31.255.255", 0); + test_external_ip("::ffff:172.32.0.0", 0); + + test_external_ip("::ffff:192.167.255.255", 0); + test_internal_ip("::ffff:192.168.0.0", 0); + test_internal_ip("::ffff:192.168.255.255", 0); + test_external_ip("::ffff:192.169.0.0", 0); + + test_external_ip("::ffff:169.253.255.255", 0); + test_internal_ip("::ffff:169.254.0.0", 0); + test_internal_ip("::ffff:169.254.255.255", 0); + test_external_ip("::ffff:169.255.0.0", 0); + test_assert(is_internal_IP(0x7f000001, 0)); + + /* tor_addr_compare(tor_addr_t x2) */ + test_addr_compare("ffff::", ==, "ffff::0"); + test_addr_compare("0::3:2:1", <, "0::ffff:0.3.2.1"); + test_addr_compare("0::2:2:1", <, "0::ffff:0.3.2.1"); + test_addr_compare("0::ffff:0.3.2.1", >, "0::0:0:0"); + test_addr_compare("0::ffff:5.2.2.1", <, "::ffff:6.0.0.0"); /* XXXX wrong. */ + tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", &t1, NULL, NULL, NULL); + tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL); + test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0); + tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", &t1, NULL, NULL, NULL); + tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL); + test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0); + + /* test compare_masked */ + test_addr_compare_masked("ffff::", ==, "ffff::0", 128); + test_addr_compare_masked("ffff::", ==, "ffff::0", 64); + 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]")); + 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")); + 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_eq(0, i); + i = tor_addr_parse_reverse_lookup_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", + 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); + test_eq(0, i); + i = tor_addr_parse_reverse_lookup_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, + "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", + AF_UNSPEC, 0); + test_eq(1, i); + 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, + "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, + "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, + "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", + AF_UNSPEC, 0); + test_eq(i, -1); + i = tor_addr_parse_reverse_lookup_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", + AF_UNSPEC, 0); + test_eq(i, -1); + i = tor_addr_parse_reverse_lookup_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, + "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_parse_mask_ports */ + test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6, + 0, 0, 0, 0x0000000f, 17, 47, 95); + //test_addr_parse("[::fefe:4.1.1.7/120]:999-1000"); + //test_addr_parse_check("::fefe:401:107", 120, 999, 1000); + test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6, + 0, 0, 0x0000ffff, 0x04010107, 120, 443, 443); + test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6, + 0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000); + + r=tor_addr_parse_mask_ports("[fefef::]/112", &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("efef::/112", &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]", &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL); + test_assert(r == -1); + /* Test for V4-mapped address with mask < 96. (arguably not valid) */ + r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]", &t1, &mask, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("1.1.2.2/33", &t1, &mask, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("1.1.2.2/31", &t1, &mask, NULL, NULL); + test_assert(r == AF_INET); + r=tor_addr_parse_mask_ports("[efef::]/112", &t1, &mask, &port1, &port2); + test_assert(r == AF_INET6); + test_assert(port1 == 1); + test_assert(port2 == 65535); + + /* make sure inet address lengths >= max */ + test_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255")); + test_assert(TOR_ADDR_BUF_LEN >= + sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")); + + test_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr)); + + /* get interface addresses */ + r = get_interface_address6(LOG_DEBUG, AF_INET, &t1); + i = get_interface_address6(LOG_DEBUG, AF_INET6, &t2); +#if 0 + tor_inet_ntop(AF_INET, &t1.sa.sin_addr, buf, sizeof(buf)); + printf("\nv4 address: %s (family=%i)", buf, IN_FAMILY(&t1)); + tor_inet_ntop(AF_INET6, &t2.sa6.sin6_addr, buf, sizeof(buf)); + printf("\nv6 address: %s (family=%i)", buf, IN_FAMILY(&t2)); +#endif + + done: + ; +} + +#define ADDR_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_addr_ ## name } + +struct testcase_t addr_tests[] = { + ADDR_LEGACY(basic), + ADDR_LEGACY(ip6_helpers), + END_OF_TESTCASES +}; + diff --git a/src/test/test_containers.c b/src/test/test_containers.c new file mode 100644 index 0000000000..1fc248cb46 --- /dev/null +++ b/src/test/test_containers.c @@ -0,0 +1,765 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "or.h" +#include "test.h" + +/** Helper: return a tristate based on comparing the strings in *<b>a</b> and + * *<b>b</b>. */ +static int +_compare_strs(const void **a, const void **b) +{ + const char *s1 = *a, *s2 = *b; + return strcmp(s1, s2); +} + +/** Helper: return a tristate based on comparing the strings in *<b>a</b> and + * *<b>b</b>, excluding a's first character, and ignoring case. */ +static int +_compare_without_first_ch(const void *a, const void **b) +{ + const char *s1 = a, *s2 = *b; + return strcasecmp(s1+1, s2); +} + +/** Run unit tests for basic dynamic-sized array functionality. */ +static void +test_container_smartlist_basic(void) +{ + smartlist_t *sl; + + /* XXXX test sort_digests, uniq_strings, uniq_digests */ + + /* Test smartlist add, del_keeporder, insert, get. */ + sl = smartlist_create(); + smartlist_add(sl, (void*)1); + smartlist_add(sl, (void*)2); + smartlist_add(sl, (void*)3); + smartlist_add(sl, (void*)4); + smartlist_del_keeporder(sl, 1); + smartlist_insert(sl, 1, (void*)22); + smartlist_insert(sl, 0, (void*)0); + smartlist_insert(sl, 5, (void*)555); + test_eq_ptr((void*)0, smartlist_get(sl,0)); + test_eq_ptr((void*)1, smartlist_get(sl,1)); + test_eq_ptr((void*)22, smartlist_get(sl,2)); + test_eq_ptr((void*)3, smartlist_get(sl,3)); + test_eq_ptr((void*)4, smartlist_get(sl,4)); + test_eq_ptr((void*)555, smartlist_get(sl,5)); + /* Try deleting in the middle. */ + smartlist_del(sl, 1); + test_eq_ptr((void*)555, smartlist_get(sl, 1)); + /* Try deleting at the end. */ + smartlist_del(sl, 4); + test_eq(4, smartlist_len(sl)); + + /* test isin. */ + test_assert(smartlist_isin(sl, (void*)3)); + test_assert(!smartlist_isin(sl, (void*)99)); + + done: + smartlist_free(sl); +} + +/** Run unit tests for smartlist-of-strings functionality. */ +static void +test_container_smartlist_strings(void) +{ + smartlist_t *sl = smartlist_create(); + char *cp=NULL, *cp_alloc=NULL; + size_t sz; + + /* Test split and join */ + test_eq(0, smartlist_len(sl)); + smartlist_split_string(sl, "abc", ":", 0, 0); + test_eq(1, smartlist_len(sl)); + test_streq("abc", smartlist_get(sl, 0)); + smartlist_split_string(sl, "a::bc::", "::", 0, 0); + test_eq(4, smartlist_len(sl)); + test_streq("a", smartlist_get(sl, 1)); + test_streq("bc", smartlist_get(sl, 2)); + test_streq("", smartlist_get(sl, 3)); + cp_alloc = smartlist_join_strings(sl, "", 0, NULL); + test_streq(cp_alloc, "abcabc"); + tor_free(cp_alloc); + cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); + test_streq(cp_alloc, "abc!a!bc!"); + tor_free(cp_alloc); + cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); + test_streq(cp_alloc, "abcXYaXYbcXY"); + tor_free(cp_alloc); + cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); + test_streq(cp_alloc, "abcXYaXYbcXYXY"); + tor_free(cp_alloc); + cp_alloc = smartlist_join_strings(sl, "", 1, NULL); + test_streq(cp_alloc, "abcabc"); + tor_free(cp_alloc); + + smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); + test_eq(8, smartlist_len(sl)); + test_streq("", smartlist_get(sl, 4)); + test_streq("def", smartlist_get(sl, 5)); + test_streq(" ", smartlist_get(sl, 6)); + test_streq("ghijk", smartlist_get(sl, 7)); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); + test_eq(3, smartlist_len(sl)); + test_streq("a", smartlist_get(sl,0)); + test_streq("bbd", smartlist_get(sl,1)); + test_streq("cdef", smartlist_get(sl,2)); + smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", + SPLIT_SKIP_SPACE, 0); + test_eq(8, smartlist_len(sl)); + test_streq("z", smartlist_get(sl,3)); + test_streq("zhasd", smartlist_get(sl,4)); + test_streq("", smartlist_get(sl,5)); + test_streq("bnud", smartlist_get(sl,6)); + test_streq("", smartlist_get(sl,7)); + + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + smartlist_split_string(sl, " ab\tc \td ef ", NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + test_eq(4, smartlist_len(sl)); + test_streq("ab", smartlist_get(sl,0)); + test_streq("c", smartlist_get(sl,1)); + test_streq("d", smartlist_get(sl,2)); + test_streq("ef", smartlist_get(sl,3)); + smartlist_split_string(sl, "ghi\tj", NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + test_eq(6, smartlist_len(sl)); + test_streq("ghi", smartlist_get(sl,4)); + test_streq("j", smartlist_get(sl,5)); + + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); + test_streq(cp_alloc, ""); + tor_free(cp_alloc); + cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); + test_streq(cp_alloc, "XY"); + tor_free(cp_alloc); + + smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + test_eq(3, smartlist_len(sl)); + test_streq("z", smartlist_get(sl, 0)); + test_streq("zhasd", smartlist_get(sl, 1)); + test_streq("bnud", smartlist_get(sl, 2)); + smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); + test_eq(5, smartlist_len(sl)); + test_streq("z", smartlist_get(sl, 3)); + test_streq("zhasd <> <> bnud<>", smartlist_get(sl, 4)); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + smartlist_split_string(sl, "abcd\n", "\n", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + test_eq(1, smartlist_len(sl)); + test_streq("abcd", smartlist_get(sl, 0)); + smartlist_split_string(sl, "efgh", "\n", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + test_eq(2, smartlist_len(sl)); + test_streq("efgh", smartlist_get(sl, 1)); + + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Test swapping, shuffling, and sorting. */ + smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); + test_eq(7, smartlist_len(sl)); + smartlist_sort(sl, _compare_strs); + cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); + test_streq(cp_alloc,"and,arma,by,nickm,onion,router,the"); + tor_free(cp_alloc); + smartlist_swap(sl, 1, 5); + cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); + test_streq(cp_alloc,"and,router,by,nickm,onion,arma,the"); + tor_free(cp_alloc); + smartlist_shuffle(sl); + test_eq(7, smartlist_len(sl)); + test_assert(smartlist_string_isin(sl, "and")); + test_assert(smartlist_string_isin(sl, "router")); + test_assert(smartlist_string_isin(sl, "by")); + test_assert(smartlist_string_isin(sl, "nickm")); + test_assert(smartlist_string_isin(sl, "onion")); + test_assert(smartlist_string_isin(sl, "arma")); + test_assert(smartlist_string_isin(sl, "the")); + + /* Test bsearch. */ + smartlist_sort(sl, _compare_strs); + test_streq("nickm", smartlist_bsearch(sl, "zNicKM", + _compare_without_first_ch)); + test_streq("and", smartlist_bsearch(sl, " AND", _compare_without_first_ch)); + test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", _compare_without_first_ch)); + + /* Test bsearch_idx */ + { + int f; + test_eq(0, smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f)); + test_eq(f, 0); + test_eq(0, smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f)); + test_eq(f, 1); + test_eq(1, smartlist_bsearch_idx(sl," arm",_compare_without_first_ch,&f)); + test_eq(f, 0); + test_eq(1, smartlist_bsearch_idx(sl," arma",_compare_without_first_ch,&f)); + test_eq(f, 1); + test_eq(2, smartlist_bsearch_idx(sl," armb",_compare_without_first_ch,&f)); + test_eq(f, 0); + test_eq(7, smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f)); + test_eq(f, 0); + } + + /* Test reverse() and pop_last() */ + smartlist_reverse(sl); + cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); + test_streq(cp_alloc,"the,router,onion,nickm,by,arma,and"); + tor_free(cp_alloc); + cp_alloc = smartlist_pop_last(sl); + test_streq(cp_alloc, "and"); + tor_free(cp_alloc); + test_eq(smartlist_len(sl), 6); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + cp_alloc = smartlist_pop_last(sl); + test_eq(cp_alloc, NULL); + + /* Test uniq() */ + smartlist_split_string(sl, + "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50", + ",", 0, 0); + smartlist_sort(sl, _compare_strs); + smartlist_uniq(sl, _compare_strs, _tor_free); + cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); + test_streq(cp_alloc, "50,a,canal,man,noon,panama,plan,radar"); + tor_free(cp_alloc); + + /* Test string_isin and isin_case and num_isin */ + test_assert(smartlist_string_isin(sl, "noon")); + test_assert(!smartlist_string_isin(sl, "noonoon")); + test_assert(smartlist_string_isin_case(sl, "nOOn")); + test_assert(!smartlist_string_isin_case(sl, "nooNooN")); + test_assert(smartlist_string_num_isin(sl, 50)); + test_assert(!smartlist_string_num_isin(sl, 60)); + + /* Test smartlist_choose */ + { + int i; + int allsame = 1; + int allin = 1; + void *first = smartlist_choose(sl); + test_assert(smartlist_isin(sl, first)); + for (i = 0; i < 100; ++i) { + void *second = smartlist_choose(sl); + if (second != first) + allsame = 0; + if (!smartlist_isin(sl, second)) + allin = 0; + } + test_assert(!allsame); + test_assert(allin); + } + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Test string_remove and remove and join_strings2 */ + smartlist_split_string(sl, + "Some say the Earth will end in ice and some in fire", + " ", 0, 0); + cp = smartlist_get(sl, 4); + test_streq(cp, "will"); + smartlist_add(sl, cp); + smartlist_remove(sl, cp); + tor_free(cp); + cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); + test_streq(cp_alloc, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); + tor_free(cp_alloc); + smartlist_string_remove(sl, "in"); + cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); + test_streq(cp_alloc, "Some+say+the+Earth+fire+end+some+ice+and"); + test_eq((int)sz, 40); + + done: + + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_free(sl); + tor_free(cp_alloc); +} + +/** Run unit tests for smartlist set manipulation functions. */ +static void +test_container_smartlist_overlap(void) +{ + smartlist_t *sl = smartlist_create(); + smartlist_t *ints = smartlist_create(); + smartlist_t *odds = smartlist_create(); + smartlist_t *evens = smartlist_create(); + smartlist_t *primes = smartlist_create(); + int i; + for (i=1; i < 10; i += 2) + smartlist_add(odds, (void*)(uintptr_t)i); + for (i=0; i < 10; i += 2) + smartlist_add(evens, (void*)(uintptr_t)i); + + /* add_all */ + smartlist_add_all(ints, odds); + smartlist_add_all(ints, evens); + test_eq(smartlist_len(ints), 10); + + smartlist_add(primes, (void*)2); + smartlist_add(primes, (void*)3); + smartlist_add(primes, (void*)5); + smartlist_add(primes, (void*)7); + + /* overlap */ + test_assert(smartlist_overlap(ints, odds)); + test_assert(smartlist_overlap(odds, primes)); + test_assert(smartlist_overlap(evens, primes)); + test_assert(!smartlist_overlap(odds, evens)); + + /* intersect */ + smartlist_add_all(sl, odds); + smartlist_intersect(sl, primes); + test_eq(smartlist_len(sl), 3); + test_assert(smartlist_isin(sl, (void*)3)); + test_assert(smartlist_isin(sl, (void*)5)); + test_assert(smartlist_isin(sl, (void*)7)); + + /* subtract */ + smartlist_add_all(sl, primes); + smartlist_subtract(sl, odds); + test_eq(smartlist_len(sl), 1); + test_assert(smartlist_isin(sl, (void*)2)); + + done: + smartlist_free(odds); + smartlist_free(evens); + smartlist_free(ints); + smartlist_free(primes); + smartlist_free(sl); +} + +/** Run unit tests for smartlist-of-digests functions. */ +static void +test_container_smartlist_digests(void) +{ + smartlist_t *sl = smartlist_create(); + + /* digest_isin. */ + smartlist_add(sl, tor_memdup("AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN)); + smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); + smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); + test_eq(0, smartlist_digest_isin(NULL, "AAAAAAAAAAAAAAAAAAAA")); + test_assert(smartlist_digest_isin(sl, "AAAAAAAAAAAAAAAAAAAA")); + test_assert(smartlist_digest_isin(sl, "\00090AAB2AAAAaasdAAAAA")); + test_eq(0, smartlist_digest_isin(sl, "\00090AAB2AAABaasdAAAAA")); + + /* sort digests */ + smartlist_sort_digests(sl); + test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); + test_memeq(smartlist_get(sl, 1), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); + test_memeq(smartlist_get(sl, 2), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); + test_eq(3, smartlist_len(sl)); + + /* uniq_digests */ + smartlist_uniq_digests(sl); + test_eq(2, smartlist_len(sl)); + test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); + test_memeq(smartlist_get(sl, 1), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); + + done: + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_free(sl); +} + +/** Run unit tests for concatenate-a-smartlist-of-strings functions. */ +static void +test_container_smartlist_join(void) +{ + smartlist_t *sl = smartlist_create(); + smartlist_t *sl2 = smartlist_create(), *sl3 = smartlist_create(), + *sl4 = smartlist_create(); + char *joined=NULL; + /* unique, sorted. */ + smartlist_split_string(sl, + "Abashments Ambush Anchorman Bacon Banks Borscht " + "Bunks Inhumane Insurance Knish Know Manners " + "Maraschinos Stamina Sunbonnets Unicorns Wombats", + " ", 0, 0); + /* non-unique, sorted. */ + smartlist_split_string(sl2, + "Ambush Anchorman Anchorman Anemias Anemias Bacon " + "Crossbowmen Inhumane Insurance Knish Know Manners " + "Manners Maraschinos Wombats Wombats Work", + " ", 0, 0); + SMARTLIST_FOREACH_JOIN(sl, char *, cp1, + sl2, char *, cp2, + strcmp(cp1,cp2), + smartlist_add(sl3, cp2)) { + test_streq(cp1, cp2); + smartlist_add(sl4, cp1); + } SMARTLIST_FOREACH_JOIN_END(cp1, cp2); + + SMARTLIST_FOREACH(sl3, const char *, cp, + test_assert(smartlist_isin(sl2, cp) && + !smartlist_string_isin(sl, cp))); + SMARTLIST_FOREACH(sl4, const char *, cp, + test_assert(smartlist_isin(sl, cp) && + smartlist_string_isin(sl2, cp))); + joined = smartlist_join_strings(sl3, ",", 0, NULL); + test_streq(joined, "Anemias,Anemias,Crossbowmen,Work"); + tor_free(joined); + joined = smartlist_join_strings(sl4, ",", 0, NULL); + test_streq(joined, "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance," + "Knish,Know,Manners,Manners,Maraschinos,Wombats,Wombats"); + tor_free(joined); + + done: + smartlist_free(sl4); + smartlist_free(sl3); + SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); + smartlist_free(sl2); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_free(sl); + tor_free(joined); +} + +/** Run unit tests for bitarray code */ +static void +test_container_bitarray(void) +{ + bitarray_t *ba = NULL; + int i, j, ok=1; + + ba = bitarray_init_zero(1); + test_assert(ba); + test_assert(! bitarray_is_set(ba, 0)); + bitarray_set(ba, 0); + test_assert(bitarray_is_set(ba, 0)); + bitarray_clear(ba, 0); + test_assert(! bitarray_is_set(ba, 0)); + bitarray_free(ba); + + ba = bitarray_init_zero(1023); + for (i = 1; i < 64; ) { + for (j = 0; j < 1023; ++j) { + if (j % i) + bitarray_set(ba, j); + else + bitarray_clear(ba, j); + } + for (j = 0; j < 1023; ++j) { + if (!bool_eq(bitarray_is_set(ba, j), j%i)) + ok = 0; + } + test_assert(ok); + if (i < 7) + ++i; + else if (i == 28) + i = 32; + else + i += 7; + } + + done: + if (ba) + bitarray_free(ba); +} + +/** Run unit tests for digest set code (implemented as a hashtable or as a + * bloom filter) */ +static void +test_container_digestset(void) +{ + smartlist_t *included = smartlist_create(); + char d[DIGEST_LEN]; + int i; + int ok = 1; + int false_positives = 0; + digestset_t *set = NULL; + + for (i = 0; i < 1000; ++i) { + crypto_rand(d, DIGEST_LEN); + smartlist_add(included, tor_memdup(d, DIGEST_LEN)); + } + set = digestset_new(1000); + SMARTLIST_FOREACH(included, const char *, cp, + if (digestset_isin(set, cp)) + ok = 0); + test_assert(ok); + SMARTLIST_FOREACH(included, const char *, cp, + digestset_add(set, cp)); + SMARTLIST_FOREACH(included, const char *, cp, + if (!digestset_isin(set, cp)) + ok = 0); + test_assert(ok); + for (i = 0; i < 1000; ++i) { + crypto_rand(d, DIGEST_LEN); + if (digestset_isin(set, d)) + ++false_positives; + } + test_assert(false_positives < 50); /* Should be far lower. */ + + done: + if (set) + digestset_free(set); + SMARTLIST_FOREACH(included, char *, cp, tor_free(cp)); + smartlist_free(included); +} + +typedef struct pq_entry_t { + const char *val; + int idx; +} pq_entry_t; + +/** Helper: return a tristate based on comparing two pq_entry_t values. */ +static int +_compare_strings_for_pqueue(const void *p1, const void *p2) +{ + const pq_entry_t *e1=p1, *e2=p2; + return strcmp(e1->val, e2->val); +} + +/** Run unit tests for heap-based priority queue functions. */ +static void +test_container_pqueue(void) +{ + smartlist_t *sl = smartlist_create(); + int (*cmp)(const void *, const void*); + const int offset = STRUCT_OFFSET(pq_entry_t, idx); +#define ENTRY(s) pq_entry_t s = { #s, -1 } + ENTRY(cows); + ENTRY(zebras); + ENTRY(fish); + ENTRY(frogs); + ENTRY(apples); + ENTRY(squid); + ENTRY(daschunds); + ENTRY(eggplants); + ENTRY(weissbier); + ENTRY(lobsters); + ENTRY(roquefort); + ENTRY(chinchillas); + ENTRY(fireflies); + +#define OK() smartlist_pqueue_assert_ok(sl, cmp, offset) + + cmp = _compare_strings_for_pqueue; + smartlist_pqueue_add(sl, cmp, offset, &cows); + smartlist_pqueue_add(sl, cmp, offset, &zebras); + smartlist_pqueue_add(sl, cmp, offset, &fish); + smartlist_pqueue_add(sl, cmp, offset, &frogs); + smartlist_pqueue_add(sl, cmp, offset, &apples); + smartlist_pqueue_add(sl, cmp, offset, &squid); + smartlist_pqueue_add(sl, cmp, offset, &daschunds); + smartlist_pqueue_add(sl, cmp, offset, &eggplants); + smartlist_pqueue_add(sl, cmp, offset, &weissbier); + smartlist_pqueue_add(sl, cmp, offset, &lobsters); + smartlist_pqueue_add(sl, cmp, offset, &roquefort); + + OK(); + + test_eq(smartlist_len(sl), 11); + test_eq_ptr(smartlist_get(sl, 0), &apples); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &apples); + test_eq(smartlist_len(sl), 10); + OK(); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &cows); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &daschunds); + smartlist_pqueue_add(sl, cmp, offset, &chinchillas); + OK(); + smartlist_pqueue_add(sl, cmp, offset, &fireflies); + OK(); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &chinchillas); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &eggplants); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fireflies); + OK(); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fish); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &frogs); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &lobsters); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &roquefort); + OK(); + test_eq(smartlist_len(sl), 3); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &squid); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &weissbier); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &zebras); + test_eq(smartlist_len(sl), 0); + OK(); + + /* Now test remove. */ + smartlist_pqueue_add(sl, cmp, offset, &cows); + smartlist_pqueue_add(sl, cmp, offset, &fish); + smartlist_pqueue_add(sl, cmp, offset, &frogs); + smartlist_pqueue_add(sl, cmp, offset, &apples); + smartlist_pqueue_add(sl, cmp, offset, &squid); + smartlist_pqueue_add(sl, cmp, offset, &zebras); + test_eq(smartlist_len(sl), 6); + OK(); + smartlist_pqueue_remove(sl, cmp, offset, &zebras); + test_eq(smartlist_len(sl), 5); + OK(); + smartlist_pqueue_remove(sl, cmp, offset, &cows); + test_eq(smartlist_len(sl), 4); + OK(); + smartlist_pqueue_remove(sl, cmp, offset, &apples); + test_eq(smartlist_len(sl), 3); + OK(); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fish); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &frogs); + test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &squid); + test_eq(smartlist_len(sl), 0); + OK(); + +#undef OK + + done: + + smartlist_free(sl); +} + +/** Run unit tests for string-to-void* map functions */ +static void +test_container_strmap(void) +{ + strmap_t *map; + strmap_iter_t *iter; + const char *k; + void *v; + char *visited = NULL; + smartlist_t *found_keys = NULL; + + map = strmap_new(); + test_assert(map); + test_eq(strmap_size(map), 0); + test_assert(strmap_isempty(map)); + v = strmap_set(map, "K1", (void*)99); + test_eq(v, NULL); + test_assert(!strmap_isempty(map)); + v = strmap_set(map, "K2", (void*)101); + test_eq(v, NULL); + v = strmap_set(map, "K1", (void*)100); + test_eq(v, (void*)99); + test_eq_ptr(strmap_get(map,"K1"), (void*)100); + test_eq_ptr(strmap_get(map,"K2"), (void*)101); + test_eq_ptr(strmap_get(map,"K-not-there"), NULL); + strmap_assert_ok(map); + + v = strmap_remove(map,"K2"); + strmap_assert_ok(map); + test_eq_ptr(v, (void*)101); + test_eq_ptr(strmap_get(map,"K2"), NULL); + test_eq_ptr(strmap_remove(map,"K2"), NULL); + + strmap_set(map, "K2", (void*)101); + strmap_set(map, "K3", (void*)102); + strmap_set(map, "K4", (void*)103); + test_eq(strmap_size(map), 4); + strmap_assert_ok(map); + strmap_set(map, "K5", (void*)104); + strmap_set(map, "K6", (void*)105); + strmap_assert_ok(map); + + /* Test iterator. */ + iter = strmap_iter_init(map); + found_keys = smartlist_create(); + while (!strmap_iter_done(iter)) { + strmap_iter_get(iter,&k,&v); + smartlist_add(found_keys, tor_strdup(k)); + test_eq_ptr(v, strmap_get(map, k)); + + if (!strcmp(k, "K2")) { + iter = strmap_iter_next_rmv(map,iter); + } else { + iter = strmap_iter_next(map,iter); + } + } + + /* Make sure we removed K2, but not the others. */ + test_eq_ptr(strmap_get(map, "K2"), NULL); + test_eq_ptr(strmap_get(map, "K5"), (void*)104); + /* Make sure we visited everyone once */ + smartlist_sort_strings(found_keys); + visited = smartlist_join_strings(found_keys, ":", 0, NULL); + test_streq(visited, "K1:K2:K3:K4:K5:K6"); + + strmap_assert_ok(map); + /* Clean up after ourselves. */ + strmap_free(map, NULL); + map = NULL; + + /* Now try some lc functions. */ + map = strmap_new(); + strmap_set_lc(map,"Ab.C", (void*)1); + test_eq_ptr(strmap_get(map,"ab.c"), (void*)1); + strmap_assert_ok(map); + test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1); + test_eq_ptr(strmap_get(map,"AB.C"), NULL); + test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1); + strmap_assert_ok(map); + test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL); + + done: + if (map) + strmap_free(map,NULL); + if (found_keys) { + SMARTLIST_FOREACH(found_keys, char *, cp, tor_free(cp)); + smartlist_free(found_keys); + } + tor_free(visited); +} + +/** Run unit tests for getting the median of a list. */ +static void +test_container_order_functions(void) +{ + int lst[25], n = 0; + // int a=12,b=24,c=25,d=60,e=77; + +#define median() median_int(lst, n) + + lst[n++] = 12; + test_eq(12, median()); /* 12 */ + lst[n++] = 77; + //smartlist_shuffle(sl); + test_eq(12, median()); /* 12, 77 */ + lst[n++] = 77; + //smartlist_shuffle(sl); + test_eq(77, median()); /* 12, 77, 77 */ + lst[n++] = 24; + test_eq(24, median()); /* 12,24,77,77 */ + lst[n++] = 60; + lst[n++] = 12; + lst[n++] = 25; + //smartlist_shuffle(sl); + test_eq(25, median()); /* 12,12,24,25,60,77,77 */ +#undef median + + done: + ; +} + +#define CONTAINER_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_container_ ## name } + +struct testcase_t container_tests[] = { + CONTAINER_LEGACY(smartlist_basic), + CONTAINER_LEGACY(smartlist_strings), + CONTAINER_LEGACY(smartlist_overlap), + CONTAINER_LEGACY(smartlist_digests), + CONTAINER_LEGACY(smartlist_join), + CONTAINER_LEGACY(bitarray), + CONTAINER_LEGACY(digestset), + CONTAINER_LEGACY(strmap), + CONTAINER_LEGACY(pqueue), + CONTAINER_LEGACY(order_functions), + END_OF_TESTCASES +}; + diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c new file mode 100644 index 0000000000..b475914b1b --- /dev/null +++ b/src/test/test_crypto.c @@ -0,0 +1,788 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#define CRYPTO_PRIVATE +#include "or.h" +#include "test.h" + +/** Run unit tests for Diffie-Hellman functionality. */ +static void +test_crypto_dh(void) +{ + crypto_dh_env_t *dh1 = crypto_dh_new(); + crypto_dh_env_t *dh2 = crypto_dh_new(); + char p1[DH_BYTES]; + char p2[DH_BYTES]; + char s1[DH_BYTES]; + char s2[DH_BYTES]; + ssize_t s1len, s2len; + + test_eq(crypto_dh_get_bytes(dh1), DH_BYTES); + test_eq(crypto_dh_get_bytes(dh2), DH_BYTES); + + memset(p1, 0, DH_BYTES); + memset(p2, 0, DH_BYTES); + test_memeq(p1, p2, DH_BYTES); + test_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES)); + test_memneq(p1, p2, DH_BYTES); + test_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES)); + test_memneq(p1, p2, DH_BYTES); + + memset(s1, 0, DH_BYTES); + memset(s2, 0xFF, DH_BYTES); + s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH_BYTES, s1, 50); + s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH_BYTES, s2, 50); + test_assert(s1len > 0); + test_eq(s1len, s2len); + test_memeq(s1, s2, s1len); + + { + /* XXXX Now fabricate some bad values and make sure they get caught, + * Check 0, 1, N-1, >= N, etc. + */ + } + + done: + crypto_dh_free(dh1); + crypto_dh_free(dh2); +} + +/** Run unit tests for our random number generation function and its wrappers. + */ +static void +test_crypto_rng(void) +{ + int i, j, allok; + char data1[100], data2[100]; + double d; + + /* Try out RNG. */ + test_assert(! crypto_seed_rng(0)); + crypto_rand(data1, 100); + crypto_rand(data2, 100); + test_memneq(data1,data2,100); + allok = 1; + for (i = 0; i < 100; ++i) { + uint64_t big; + char *host; + j = crypto_rand_int(100); + if (i < 0 || i >= 100) + allok = 0; + big = crypto_rand_uint64(U64_LITERAL(1)<<40); + if (big >= (U64_LITERAL(1)<<40)) + allok = 0; + big = crypto_rand_uint64(U64_LITERAL(5)); + if (big >= 5) + allok = 0; + d = crypto_rand_double(); + test_assert(d >= 0); + test_assert(d < 1.0); + host = crypto_random_hostname(3,8,"www.",".onion"); + if (strcmpstart(host,"www.") || + strcmpend(host,".onion") || + strlen(host) < 13 || + strlen(host) > 18) + allok = 0; + tor_free(host); + } + test_assert(allok); + done: + ; +} + +/** Run unit tests for our AES functionality */ +static void +test_crypto_aes(void) +{ + char *data1 = NULL, *data2 = NULL, *data3 = NULL; + crypto_cipher_env_t *env1 = NULL, *env2 = NULL; + int i, j; + char *mem_op_hex_tmp=NULL; + + data1 = tor_malloc(1024); + data2 = tor_malloc(1024); + data3 = tor_malloc(1024); + + /* Now, test encryption and decryption with stream cipher. */ + data1[0]='\0'; + for (i = 1023; i>0; i -= 35) + strncat(data1, "Now is the time for all good onions", i); + + memset(data2, 0, 1024); + memset(data3, 0, 1024); + env1 = crypto_new_cipher_env(); + test_neq(env1, 0); + env2 = crypto_new_cipher_env(); + test_neq(env2, 0); + j = crypto_cipher_generate_key(env1); + crypto_cipher_set_key(env2, crypto_cipher_get_key(env1)); + crypto_cipher_encrypt_init_cipher(env1); + crypto_cipher_decrypt_init_cipher(env2); + + /* Try encrypting 512 chars. */ + crypto_cipher_encrypt(env1, data2, data1, 512); + crypto_cipher_decrypt(env2, data3, data2, 512); + test_memeq(data1, data3, 512); + test_memneq(data1, data2, 512); + + /* Now encrypt 1 at a time, and get 1 at a time. */ + for (j = 512; j < 560; ++j) { + crypto_cipher_encrypt(env1, data2+j, data1+j, 1); + } + for (j = 512; j < 560; ++j) { + crypto_cipher_decrypt(env2, data3+j, data2+j, 1); + } + test_memeq(data1, data3, 560); + /* Now encrypt 3 at a time, and get 5 at a time. */ + for (j = 560; j < 1024-5; j += 3) { + crypto_cipher_encrypt(env1, data2+j, data1+j, 3); + } + for (j = 560; j < 1024-5; j += 5) { + crypto_cipher_decrypt(env2, data3+j, data2+j, 5); + } + test_memeq(data1, data3, 1024-5); + /* Now make sure that when we encrypt with different chunk sizes, we get + the same results. */ + crypto_free_cipher_env(env2); + env2 = NULL; + + memset(data3, 0, 1024); + env2 = crypto_new_cipher_env(); + test_neq(env2, 0); + crypto_cipher_set_key(env2, crypto_cipher_get_key(env1)); + crypto_cipher_encrypt_init_cipher(env2); + for (j = 0; j < 1024-16; j += 17) { + crypto_cipher_encrypt(env2, data3+j, data1+j, 17); + } + for (j= 0; j < 1024-16; ++j) { + if (data2[j] != data3[j]) { + printf("%d: %d\t%d\n", j, (int) data2[j], (int) data3[j]); + } + } + test_memeq(data2, data3, 1024-16); + crypto_free_cipher_env(env1); + env1 = NULL; + crypto_free_cipher_env(env2); + env2 = NULL; + + /* NIST test vector for aes. */ + env1 = crypto_new_cipher_env(); /* IV starts at 0 */ + crypto_cipher_set_key(env1, "\x80\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00"); + crypto_cipher_encrypt_init_cipher(env1); + crypto_cipher_encrypt(env1, data1, + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", 16); + test_memeq_hex(data1, "0EDD33D3C621E546455BD8BA1418BEC8"); + + /* Now test rollover. All these values are originally from a python + * script. */ + crypto_cipher_set_iv(env1, "\x00\x00\x00\x00\x00\x00\x00\x00" + "\xff\xff\xff\xff\xff\xff\xff\xff"); + memset(data2, 0, 1024); + crypto_cipher_encrypt(env1, data1, data2, 32); + test_memeq_hex(data1, "335fe6da56f843199066c14a00a40231" + "cdd0b917dbc7186908a6bfb5ffd574d3"); + + crypto_cipher_set_iv(env1, "\x00\x00\x00\x00\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff"); + memset(data2, 0, 1024); + crypto_cipher_encrypt(env1, data1, data2, 32); + test_memeq_hex(data1, "e627c6423fa2d77832a02b2794094b73" + "3e63c721df790d2c6469cc1953a3ffac"); + + crypto_cipher_set_iv(env1, "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff"); + memset(data2, 0, 1024); + crypto_cipher_encrypt(env1, data1, data2, 32); + test_memeq_hex(data1, "2aed2bff0de54f9328efd070bf48f70a" + "0EDD33D3C621E546455BD8BA1418BEC8"); + + /* Now check rollover on inplace cipher. */ + crypto_cipher_set_iv(env1, "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff"); + crypto_cipher_crypt_inplace(env1, data2, 64); + test_memeq_hex(data2, "2aed2bff0de54f9328efd070bf48f70a" + "0EDD33D3C621E546455BD8BA1418BEC8" + "93e2c5243d6839eac58503919192f7ae" + "1908e67cafa08d508816659c2e693191"); + crypto_cipher_set_iv(env1, "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff"); + crypto_cipher_crypt_inplace(env1, data2, 64); + test_assert(tor_mem_is_zero(data2, 64)); + + done: + tor_free(mem_op_hex_tmp); + if (env1) + crypto_free_cipher_env(env1); + if (env2) + crypto_free_cipher_env(env2); + tor_free(data1); + tor_free(data2); + tor_free(data3); +} + +/** Run unit tests for our SHA-1 functionality */ +static void +test_crypto_sha(void) +{ + crypto_digest_env_t *d1 = NULL, *d2 = NULL; + int i; + char key[80]; + char digest[32]; + char data[50]; + char d_out1[DIGEST_LEN], d_out2[DIGEST256_LEN]; + char *mem_op_hex_tmp=NULL; + + /* Test SHA-1 with a test vector from the specification. */ + i = crypto_digest(data, "abc", 3); + test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D"); + + /* Test SHA-256 with a test vector from the specification. */ + i = crypto_digest256(data, "abc", 3, DIGEST_SHA256); + test_memeq_hex(data, "BA7816BF8F01CFEA414140DE5DAE2223B00361A3" + "96177A9CB410FF61F20015AD"); + + /* Test HMAC-SHA-1 with test cases from RFC2202. */ + + /* Case 1. */ + memset(key, 0x0b, 20); + crypto_hmac_sha1(digest, key, 20, "Hi There", 8); + test_streq(hex_str(digest, 20), + "B617318655057264E28BC0B6FB378C8EF146BE00"); + /* Case 2. */ + crypto_hmac_sha1(digest, "Jefe", 4, "what do ya want for nothing?", 28); + test_streq(hex_str(digest, 20), + "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79"); + + /* Case 4. */ + base16_decode(key, 25, + "0102030405060708090a0b0c0d0e0f10111213141516171819", 50); + memset(data, 0xcd, 50); + crypto_hmac_sha1(digest, key, 25, data, 50); + test_streq(hex_str(digest, 20), + "4C9007F4026250C6BC8414F9BF50C86C2D7235DA"); + + /* Case 5. */ + memset(key, 0xaa, 80); + crypto_hmac_sha1(digest, key, 80, + "Test Using Larger Than Block-Size Key - Hash Key First", + 54); + test_streq(hex_str(digest, 20), + "AA4AE5E15272D00E95705637CE8A3B55ED402112"); + + /* Incremental digest code. */ + d1 = crypto_new_digest_env(); + test_assert(d1); + crypto_digest_add_bytes(d1, "abcdef", 6); + d2 = crypto_digest_dup(d1); + test_assert(d2); + crypto_digest_add_bytes(d2, "ghijkl", 6); + crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); + crypto_digest(d_out2, "abcdefghijkl", 12); + test_memeq(d_out1, d_out2, DIGEST_LEN); + crypto_digest_assign(d2, d1); + crypto_digest_add_bytes(d2, "mno", 3); + crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); + crypto_digest(d_out2, "abcdefmno", 9); + test_memeq(d_out1, d_out2, DIGEST_LEN); + crypto_digest_get_digest(d1, d_out1, sizeof(d_out1)); + crypto_digest(d_out2, "abcdef", 6); + test_memeq(d_out1, d_out2, DIGEST_LEN); + crypto_free_digest_env(d1); + crypto_free_digest_env(d2); + + /* Incremental digest code with sha256 */ + d1 = crypto_new_digest256_env(DIGEST_SHA256); + test_assert(d1); + crypto_digest_add_bytes(d1, "abcdef", 6); + d2 = crypto_digest_dup(d1); + test_assert(d2); + crypto_digest_add_bytes(d2, "ghijkl", 6); + crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); + crypto_digest256(d_out2, "abcdefghijkl", 12, DIGEST_SHA256); + test_memeq(d_out1, d_out2, DIGEST_LEN); + crypto_digest_assign(d2, d1); + crypto_digest_add_bytes(d2, "mno", 3); + crypto_digest_get_digest(d2, d_out1, sizeof(d_out1)); + crypto_digest256(d_out2, "abcdefmno", 9, DIGEST_SHA256); + test_memeq(d_out1, d_out2, DIGEST_LEN); + crypto_digest_get_digest(d1, d_out1, sizeof(d_out1)); + crypto_digest256(d_out2, "abcdef", 6, DIGEST_SHA256); + test_memeq(d_out1, d_out2, DIGEST_LEN); + + done: + if (d1) + crypto_free_digest_env(d1); + if (d2) + crypto_free_digest_env(d2); + tor_free(mem_op_hex_tmp); +} + +/** Run unit tests for our public key crypto functions */ +static void +test_crypto_pk(void) +{ + crypto_pk_env_t *pk1 = NULL, *pk2 = NULL; + char *encoded = NULL; + char data1[1024], data2[1024], data3[1024]; + size_t size; + int i, j, p, len; + + /* Public-key ciphers */ + pk1 = pk_generate(0); + pk2 = crypto_new_pk_env(); + test_assert(pk1 && pk2); + test_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size)); + test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size)); + test_eq(0, crypto_pk_cmp_keys(pk1, pk2)); + + test_eq(128, crypto_pk_keysize(pk1)); + test_eq(128, crypto_pk_keysize(pk2)); + + test_eq(128, crypto_pk_public_encrypt(pk2, data1, "Hello whirled.", 15, + PK_PKCS1_OAEP_PADDING)); + test_eq(128, crypto_pk_public_encrypt(pk1, data2, "Hello whirled.", 15, + PK_PKCS1_OAEP_PADDING)); + /* oaep padding should make encryption not match */ + test_memneq(data1, data2, 128); + test_eq(15, crypto_pk_private_decrypt(pk1, data3, data1, 128, + PK_PKCS1_OAEP_PADDING,1)); + test_streq(data3, "Hello whirled."); + memset(data3, 0, 1024); + test_eq(15, crypto_pk_private_decrypt(pk1, data3, data2, 128, + PK_PKCS1_OAEP_PADDING,1)); + test_streq(data3, "Hello whirled."); + /* Can't decrypt with public key. */ + test_eq(-1, crypto_pk_private_decrypt(pk2, data3, data2, 128, + PK_PKCS1_OAEP_PADDING,1)); + /* Try again with bad padding */ + memcpy(data2+1, "XYZZY", 5); /* This has fails ~ once-in-2^40 */ + test_eq(-1, crypto_pk_private_decrypt(pk1, data3, data2, 128, + PK_PKCS1_OAEP_PADDING,1)); + + /* File operations: save and load private key */ + test_assert(! crypto_pk_write_private_key_to_filename(pk1, + get_fname("pkey1"))); + /* failing case for read: can't read. */ + test_assert(crypto_pk_read_private_key_from_filename(pk2, + get_fname("xyzzy")) < 0); + write_str_to_file(get_fname("xyzzy"), "foobar", 6); + /* Failing case for read: no key. */ + test_assert(crypto_pk_read_private_key_from_filename(pk2, + get_fname("xyzzy")) < 0); + test_assert(! crypto_pk_read_private_key_from_filename(pk2, + get_fname("pkey1"))); + test_eq(15, crypto_pk_private_decrypt(pk2, data3, data1, 128, + PK_PKCS1_OAEP_PADDING,1)); + + /* Now try signing. */ + strlcpy(data1, "Ossifrage", 1024); + test_eq(128, crypto_pk_private_sign(pk1, data2, data1, 10)); + test_eq(10, crypto_pk_public_checksig(pk1, data3, data2, 128)); + test_streq(data3, "Ossifrage"); + /* Try signing digests. */ + test_eq(128, crypto_pk_private_sign_digest(pk1, data2, data1, 10)); + test_eq(20, crypto_pk_public_checksig(pk1, data3, data2, 128)); + test_eq(0, crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128)); + test_eq(-1, crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128)); + /*XXXX test failed signing*/ + + /* Try encoding */ + crypto_free_pk_env(pk2); + pk2 = NULL; + i = crypto_pk_asn1_encode(pk1, data1, 1024); + test_assert(i>0); + pk2 = crypto_pk_asn1_decode(data1, i); + test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + + /* Try with hybrid encryption wrappers. */ + crypto_rand(data1, 1024); + for (i = 0; i < 3; ++i) { + for (j = 85; j < 140; ++j) { + memset(data2,0,1024); + memset(data3,0,1024); + if (i == 0 && j < 129) + continue; + p = (i==0)?PK_NO_PADDING: + (i==1)?PK_PKCS1_PADDING:PK_PKCS1_OAEP_PADDING; + len = crypto_pk_public_hybrid_encrypt(pk1,data2,data1,j,p,0); + test_assert(len>=0); + len = crypto_pk_private_hybrid_decrypt(pk1,data3,data2,len,p,1); + test_eq(len,j); + test_memeq(data1,data3,j); + } + } + + /* Try copy_full */ + crypto_free_pk_env(pk2); + pk2 = crypto_pk_copy_full(pk1); + test_assert(pk2 != NULL); + test_neq_ptr(pk1, pk2); + test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + + done: + if (pk1) + crypto_free_pk_env(pk1); + if (pk2) + crypto_free_pk_env(pk2); + tor_free(encoded); +} + +/** Run unit tests for misc crypto formatting functionality (base64, base32, + * fingerprints, etc) */ +static void +test_crypto_formats(void) +{ + char *data1 = NULL, *data2 = NULL, *data3 = NULL; + int i, j, idx; + + data1 = tor_malloc(1024); + data2 = tor_malloc(1024); + data3 = tor_malloc(1024); + test_assert(data1 && data2 && data3); + + /* Base64 tests */ + memset(data1, 6, 1024); + for (idx = 0; idx < 10; ++idx) { + i = base64_encode(data2, 1024, data1, idx); + test_assert(i >= 0); + j = base64_decode(data3, 1024, data2, i); + test_eq(j,idx); + test_memeq(data3, data1, idx); + } + + strlcpy(data1, "Test string that contains 35 chars.", 1024); + strlcat(data1, " 2nd string that contains 35 chars.", 1024); + + i = base64_encode(data2, 1024, data1, 71); + test_assert(i >= 0); + j = base64_decode(data3, 1024, data2, i); + test_eq(j, 71); + test_streq(data3, data1); + test_assert(data2[i] == '\0'); + + crypto_rand(data1, DIGEST_LEN); + memset(data2, 100, 1024); + digest_to_base64(data2, data1); + test_eq(BASE64_DIGEST_LEN, strlen(data2)); + test_eq(100, data2[BASE64_DIGEST_LEN+2]); + memset(data3, 99, 1024); + test_eq(digest_from_base64(data3, data2), 0); + test_memeq(data1, data3, DIGEST_LEN); + test_eq(99, data3[DIGEST_LEN+1]); + + test_assert(digest_from_base64(data3, "###") < 0); + + /* Encoding SHA256 */ + crypto_rand(data2, DIGEST256_LEN); + memset(data2, 100, 1024); + digest256_to_base64(data2, data1); + test_eq(BASE64_DIGEST256_LEN, strlen(data2)); + test_eq(100, data2[BASE64_DIGEST256_LEN+2]); + memset(data3, 99, 1024); + test_eq(digest256_from_base64(data3, data2), 0); + test_memeq(data1, data3, DIGEST256_LEN); + test_eq(99, data3[DIGEST256_LEN+1]); + + /* Base32 tests */ + strlcpy(data1, "5chrs", 1024); + /* bit pattern is: [35 63 68 72 73] -> + * [00110101 01100011 01101000 01110010 01110011] + * By 5s: [00110 10101 10001 10110 10000 11100 10011 10011] + */ + base32_encode(data2, 9, data1, 5); + test_streq(data2, "gvrwq4tt"); + + strlcpy(data1, "\xFF\xF5\x6D\x44\xAE\x0D\x5C\xC9\x62\xC4", 1024); + base32_encode(data2, 30, data1, 10); + test_streq(data2, "772w2rfobvomsywe"); + + /* Base16 tests */ + strlcpy(data1, "6chrs\xff", 1024); + base16_encode(data2, 13, data1, 6); + test_streq(data2, "3663687273FF"); + + strlcpy(data1, "f0d678affc000100", 1024); + i = base16_decode(data2, 8, data1, 16); + test_eq(i,0); + test_memeq(data2, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8); + + /* now try some failing base16 decodes */ + test_eq(-1, base16_decode(data2, 8, data1, 15)); /* odd input len */ + test_eq(-1, base16_decode(data2, 7, data1, 16)); /* dest too short */ + strlcpy(data1, "f0dz!8affc000100", 1024); + test_eq(-1, base16_decode(data2, 8, data1, 16)); + + tor_free(data1); + tor_free(data2); + tor_free(data3); + + /* Add spaces to fingerprint */ + { + data1 = tor_strdup("ABCD1234ABCD56780000ABCD1234ABCD56780000"); + test_eq(strlen(data1), 40); + data2 = tor_malloc(FINGERPRINT_LEN+1); + add_spaces_to_fp(data2, FINGERPRINT_LEN+1, data1); + test_streq(data2, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000"); + tor_free(data1); + tor_free(data2); + } + + /* Check fingerprint */ + { + test_assert(crypto_pk_check_fingerprint_syntax( + "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000")); + test_assert(!crypto_pk_check_fingerprint_syntax( + "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 000")); + test_assert(!crypto_pk_check_fingerprint_syntax( + "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 00000")); + test_assert(!crypto_pk_check_fingerprint_syntax( + "ABCD 1234 ABCD 5678 0000 ABCD1234 ABCD 5678 0000")); + test_assert(!crypto_pk_check_fingerprint_syntax( + "ABCD 1234 ABCD 5678 0000 ABCD1234 ABCD 5678 00000")); + test_assert(!crypto_pk_check_fingerprint_syntax( + "ACD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 00000")); + } + + done: + tor_free(data1); + tor_free(data2); + tor_free(data3); +} + +/** Run unit tests for our secret-to-key passphrase hashing functionality. */ +static void +test_crypto_s2k(void) +{ + char buf[29]; + char buf2[29]; + char *buf3 = NULL; + int i; + + memset(buf, 0, sizeof(buf)); + memset(buf2, 0, sizeof(buf2)); + buf3 = tor_malloc(65536); + memset(buf3, 0, 65536); + + secret_to_key(buf+9, 20, "", 0, buf); + crypto_digest(buf2+9, buf3, 1024); + test_memeq(buf, buf2, 29); + + memcpy(buf,"vrbacrda",8); + memcpy(buf2,"vrbacrda",8); + buf[8] = 96; + buf2[8] = 96; + secret_to_key(buf+9, 20, "12345678", 8, buf); + for (i = 0; i < 65536; i += 16) { + memcpy(buf3+i, "vrbacrda12345678", 16); + } + crypto_digest(buf2+9, buf3, 65536); + test_memeq(buf, buf2, 29); + + done: + tor_free(buf3); +} + +/** Test AES-CTR encryption and decryption with IV. */ +static void +test_crypto_aes_iv(void) +{ + crypto_cipher_env_t *cipher; + char *plain, *encrypted1, *encrypted2, *decrypted1, *decrypted2; + char plain_1[1], plain_15[15], plain_16[16], plain_17[17]; + char key1[16], key2[16]; + ssize_t encrypted_size, decrypted_size; + + plain = tor_malloc(4095); + encrypted1 = tor_malloc(4095 + 1 + 16); + encrypted2 = tor_malloc(4095 + 1 + 16); + decrypted1 = tor_malloc(4095 + 1); + decrypted2 = tor_malloc(4095 + 1); + + crypto_rand(plain, 4095); + crypto_rand(key1, 16); + crypto_rand(key2, 16); + crypto_rand(plain_1, 1); + crypto_rand(plain_15, 15); + crypto_rand(plain_16, 16); + crypto_rand(plain_17, 17); + key1[0] = key2[0] + 128; /* Make sure that contents are different. */ + /* Encrypt and decrypt with the same key. */ + cipher = crypto_create_init_cipher(key1, 1); + encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 4095, + plain, 4095); + 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 + * greater than 0, but its truth is not + * obvious to all analysis tools. */ + cipher = crypto_create_init_cipher(key1, 0); + decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 4095, + encrypted1, encrypted_size); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_eq(decrypted_size, 4095); + tor_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); + encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted2, 16 + 4095, + plain, 4095); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_eq(encrypted_size, 16 + 4095); + tor_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); + test_memeq(plain, decrypted2, 4095); + test_memneq(encrypted1, encrypted2, encrypted_size); + /* Decrypt with the wrong key. */ + cipher = crypto_create_init_cipher(key2, 0); + decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095, + encrypted1, encrypted_size); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_memneq(plain, decrypted2, encrypted_size); + /* Alter the initialization vector. */ + encrypted1[0] += 42; + cipher = crypto_create_init_cipher(key1, 0); + decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 4095, + encrypted1, encrypted_size); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_memneq(plain, decrypted2, 4095); + /* Special length case: 1. */ + cipher = crypto_create_init_cipher(key1, 1); + encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 1, + plain_1, 1); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_eq(encrypted_size, 16 + 1); + tor_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); + test_memeq(plain_1, decrypted1, 1); + /* Special length case: 15. */ + cipher = crypto_create_init_cipher(key1, 1); + encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 15, + plain_15, 15); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_eq(encrypted_size, 16 + 15); + tor_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); + test_memeq(plain_15, decrypted1, 15); + /* Special length case: 16. */ + cipher = crypto_create_init_cipher(key1, 1); + encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 16, + plain_16, 16); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_eq(encrypted_size, 16 + 16); + tor_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); + test_memeq(plain_16, decrypted1, 16); + /* Special length case: 17. */ + cipher = crypto_create_init_cipher(key1, 1); + encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 17, + plain_17, 17); + crypto_free_cipher_env(cipher); + cipher = NULL; + test_eq(encrypted_size, 16 + 17); + tor_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); + test_memeq(plain_17, decrypted1, 17); + + done: + /* Free memory. */ + tor_free(plain); + tor_free(encrypted1); + tor_free(encrypted2); + tor_free(decrypted1); + tor_free(decrypted2); + if (cipher) + crypto_free_cipher_env(cipher); +} + +/** Test base32 decoding. */ +static void +test_crypto_base32_decode(void) +{ + char plain[60], encoded[96 + 1], decoded[60]; + int res; + crypto_rand(plain, 60); + /* Encode and decode a random string. */ + base32_encode(encoded, 96 + 1, plain, 60); + res = base32_decode(decoded, 60, encoded, 96); + test_eq(res, 0); + test_memeq(plain, decoded, 60); + /* Encode, uppercase, and decode a random string. */ + base32_encode(encoded, 96 + 1, plain, 60); + tor_strupper(encoded); + res = base32_decode(decoded, 60, encoded, 96); + test_eq(res, 0); + test_memeq(plain, decoded, 60); + /* Change encoded string and decode. */ + if (encoded[0] == 'A' || encoded[0] == 'a') + encoded[0] = 'B'; + else + encoded[0] = 'A'; + res = base32_decode(decoded, 60, encoded, 96); + test_eq(res, 0); + test_memneq(plain, decoded, 60); + /* Bad encodings. */ + encoded[0] = '!'; + res = base32_decode(decoded, 60, encoded, 96); + test_assert(res < 0); + + done: + ; +} + +#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), + CRYPTO_LEGACY(sha), + CRYPTO_LEGACY(pk), + CRYPTO_LEGACY(dh), + CRYPTO_LEGACY(s2k), + CRYPTO_LEGACY(aes_iv), + CRYPTO_LEGACY(base32_decode), + END_OF_TESTCASES +}; + diff --git a/src/or/test_data.c b/src/test/test_data.c index f926ee17dd..f926ee17dd 100644 --- a/src/or/test_data.c +++ b/src/test/test_data.c diff --git a/src/test/test_dir.c b/src/test/test_dir.c new file mode 100644 index 0000000000..a0ad1914cc --- /dev/null +++ b/src/test/test_dir.c @@ -0,0 +1,1317 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#define DIRSERV_PRIVATE +#define DIRVOTE_PRIVATE +#define ROUTER_PRIVATE +#include "or.h" +#include "directory.h" +#include "dirserv.h" +#include "dirvote.h" +#include "networkstatus.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" +#include "test.h" + +static void +test_dir_nicknames(void) +{ + test_assert( is_legal_nickname("a")); + test_assert(!is_legal_nickname("")); + test_assert(!is_legal_nickname("abcdefghijklmnopqrst")); /* 20 chars */ + test_assert(!is_legal_nickname("hyphen-")); /* bad char */ + test_assert( is_legal_nickname("abcdefghijklmnopqrs")); /* 19 chars */ + test_assert(!is_legal_nickname("$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA")); + /* valid */ + test_assert( is_legal_nickname_or_hexdigest( + "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA")); + test_assert( is_legal_nickname_or_hexdigest( + "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA=fred")); + test_assert( is_legal_nickname_or_hexdigest( + "$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA~fred")); + /* too short */ + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); + /* illegal char */ + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); + /* hex part too long */ + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=fred")); + /* Bad nickname */ + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")); + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~")); + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~hyphen-")); + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~" + "abcdefghijklmnoppqrst")); + /* Bad extra char. */ + test_assert(!is_legal_nickname_or_hexdigest( + "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!")); + test_assert(is_legal_nickname_or_hexdigest("xyzzy")); + test_assert(is_legal_nickname_or_hexdigest("abcdefghijklmnopqrs")); + test_assert(!is_legal_nickname_or_hexdigest("abcdefghijklmnopqrst")); + done: + ; +} + +/** Run unit tests for router descriptor generation logic. */ +static void +test_dir_formats(void) +{ + char buf[8192], buf2[8192]; + char platform[256]; + char fingerprint[FINGERPRINT_LEN+1]; + char *pk1_str = NULL, *pk2_str = NULL, *pk3_str = NULL, *cp; + size_t pk1_str_len, pk2_str_len, pk3_str_len; + routerinfo_t *r1=NULL, *r2=NULL; + crypto_pk_env_t *pk1 = NULL, *pk2 = NULL, *pk3 = NULL; + routerinfo_t *rp1 = NULL; + addr_policy_t *ex1, *ex2; + routerlist_t *dir1 = NULL, *dir2 = NULL; + + pk1 = pk_generate(0); + pk2 = pk_generate(1); + pk3 = pk_generate(2); + + test_assert(pk1 && pk2 && pk3); + + get_platform_str(platform, sizeof(platform)); + r1 = tor_malloc_zero(sizeof(routerinfo_t)); + r1->address = tor_strdup("18.244.0.1"); + r1->addr = 0xc0a80001u; /* 192.168.0.1 */ + r1->cache_info.published_on = 0; + r1->or_port = 9000; + r1->dir_port = 9003; + r1->onion_pkey = crypto_pk_dup_key(pk1); + r1->identity_pkey = crypto_pk_dup_key(pk2); + r1->bandwidthrate = 1000; + r1->bandwidthburst = 5000; + r1->bandwidthcapacity = 10000; + r1->exit_policy = NULL; + r1->nickname = tor_strdup("Magri"); + r1->platform = tor_strdup(platform); + + ex1 = tor_malloc_zero(sizeof(addr_policy_t)); + ex2 = tor_malloc_zero(sizeof(addr_policy_t)); + ex1->policy_type = ADDR_POLICY_ACCEPT; + tor_addr_from_ipv4h(&ex1->addr, 0); + ex1->maskbits = 0; + ex1->prt_min = ex1->prt_max = 80; + ex2->policy_type = ADDR_POLICY_REJECT; + tor_addr_from_ipv4h(&ex2->addr, 18<<24); + ex2->maskbits = 8; + ex2->prt_min = ex2->prt_max = 24; + r2 = tor_malloc_zero(sizeof(routerinfo_t)); + r2->address = tor_strdup("1.1.1.1"); + r2->addr = 0x0a030201u; /* 10.3.2.1 */ + r2->platform = tor_strdup(platform); + r2->cache_info.published_on = 5; + r2->or_port = 9005; + r2->dir_port = 0; + r2->onion_pkey = crypto_pk_dup_key(pk2); + r2->identity_pkey = crypto_pk_dup_key(pk1); + r2->bandwidthrate = r2->bandwidthburst = r2->bandwidthcapacity = 3000; + r2->exit_policy = smartlist_create(); + smartlist_add(r2->exit_policy, ex2); + smartlist_add(r2->exit_policy, ex1); + r2->nickname = tor_strdup("Fred"); + + test_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str, + &pk1_str_len)); + test_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str, + &pk2_str_len)); + test_assert(!crypto_pk_write_public_key_to_string(pk3 , &pk3_str, + &pk3_str_len)); + + memset(buf, 0, 2048); + test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0); + + strlcpy(buf2, "router Magri 18.244.0.1 9000 0 9003\n" + "platform Tor "VERSION" on ", sizeof(buf2)); + strlcat(buf2, get_uname(), sizeof(buf2)); + strlcat(buf2, "\n" + "opt protocols Link 1 2 Circuit 1\n" + "published 1970-01-01 00:00:00\n" + "opt fingerprint ", sizeof(buf2)); + test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1)); + strlcat(buf2, fingerprint, sizeof(buf2)); + strlcat(buf2, "\nuptime 0\n" + /* XXX the "0" above is hard-coded, but even if we made it reflect + * uptime, that still wouldn't make it right, because the two + * descriptors might be made on different seconds... hm. */ + "bandwidth 1000 5000 10000\n" + "onion-key\n", sizeof(buf2)); + strlcat(buf2, pk1_str, sizeof(buf2)); + strlcat(buf2, "signing-key\n", sizeof(buf2)); + strlcat(buf2, pk2_str, sizeof(buf2)); + strlcat(buf2, "opt hidden-service-dir\n", sizeof(buf2)); + strlcat(buf2, "reject *:*\nrouter-signature\n", sizeof(buf2)); + buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same + * twice */ + + test_streq(buf, buf2); + + test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0); + cp = buf; + rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); + test_assert(rp1); + test_streq(rp1->address, r1->address); + test_eq(rp1->or_port, r1->or_port); + //test_eq(rp1->dir_port, r1->dir_port); + test_eq(rp1->bandwidthrate, r1->bandwidthrate); + test_eq(rp1->bandwidthburst, r1->bandwidthburst); + test_eq(rp1->bandwidthcapacity, r1->bandwidthcapacity); + test_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0); + test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0); + //test_assert(rp1->exit_policy == NULL); + +#if 0 + /* XXX Once we have exit policies, test this again. XXX */ + strlcpy(buf2, "router tor.tor.tor 9005 0 0 3000\n", sizeof(buf2)); + strlcat(buf2, pk2_str, sizeof(buf2)); + strlcat(buf2, "signing-key\n", sizeof(buf2)); + strlcat(buf2, pk1_str, sizeof(buf2)); + strlcat(buf2, "accept *:80\nreject 18.*:24\n\n", sizeof(buf2)); + test_assert(router_dump_router_to_string(buf, 2048, &r2, pk2)>0); + test_streq(buf, buf2); + + cp = buf; + rp2 = router_parse_entry_from_string(&cp,1); + test_assert(rp2); + test_streq(rp2->address, r2.address); + test_eq(rp2->or_port, r2.or_port); + test_eq(rp2->dir_port, r2.dir_port); + test_eq(rp2->bandwidth, r2.bandwidth); + test_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0); + test_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0); + test_eq(rp2->exit_policy->policy_type, EXIT_POLICY_ACCEPT); + test_streq(rp2->exit_policy->string, "accept *:80"); + test_streq(rp2->exit_policy->address, "*"); + test_streq(rp2->exit_policy->port, "80"); + test_eq(rp2->exit_policy->next->policy_type, EXIT_POLICY_REJECT); + test_streq(rp2->exit_policy->next->string, "reject 18.*:24"); + test_streq(rp2->exit_policy->next->address, "18.*"); + test_streq(rp2->exit_policy->next->port, "24"); + test_assert(rp2->exit_policy->next->next == NULL); + + /* Okay, now for the directories. */ + { + fingerprint_list = smartlist_create(); + crypto_pk_get_fingerprint(pk2, buf, 1); + add_fingerprint_to_dir("Magri", buf, fingerprint_list); + crypto_pk_get_fingerprint(pk1, buf, 1); + add_fingerprint_to_dir("Fred", buf, fingerprint_list); + } + + { + char d[DIGEST_LEN]; + const char *m; + /* XXXX NM re-enable. */ + /* Make sure routers aren't too far in the past any more. */ + r1->cache_info.published_on = time(NULL); + r2->cache_info.published_on = time(NULL)-3*60*60; + test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0); + test_eq(dirserv_add_descriptor(buf,&m,""), ROUTER_ADDED_NOTIFY_GENERATOR); + test_assert(router_dump_router_to_string(buf, 2048, r2, pk1)>0); + test_eq(dirserv_add_descriptor(buf,&m,""), ROUTER_ADDED_NOTIFY_GENERATOR); + get_options()->Nickname = tor_strdup("DirServer"); + test_assert(!dirserv_dump_directory_to_string(&cp,pk3, 0)); + crypto_pk_get_digest(pk3, d); + test_assert(!router_parse_directory(cp)); + test_eq(2, smartlist_len(dir1->routers)); + tor_free(cp); + } +#endif + dirserv_free_fingerprint_list(); + + done: + if (r1) + routerinfo_free(r1); + if (r2) + routerinfo_free(r2); + + tor_free(pk1_str); + tor_free(pk2_str); + tor_free(pk3_str); + if (pk1) crypto_free_pk_env(pk1); + if (pk2) crypto_free_pk_env(pk2); + if (pk3) crypto_free_pk_env(pk3); + if (rp1) routerinfo_free(rp1); + tor_free(dir1); /* XXXX And more !*/ + tor_free(dir2); /* And more !*/ +} + +static void +test_dir_versions(void) +{ + tor_version_t ver1; + + /* Try out version parsing functionality */ + test_eq(0, tor_version_parse("0.3.4pre2-cvs", &ver1)); + test_eq(0, ver1.major); + test_eq(3, ver1.minor); + test_eq(4, ver1.micro); + test_eq(VER_PRE, ver1.status); + test_eq(2, ver1.patchlevel); + test_eq(0, tor_version_parse("0.3.4rc1", &ver1)); + test_eq(0, ver1.major); + test_eq(3, ver1.minor); + test_eq(4, ver1.micro); + test_eq(VER_RC, ver1.status); + test_eq(1, ver1.patchlevel); + test_eq(0, tor_version_parse("1.3.4", &ver1)); + test_eq(1, ver1.major); + test_eq(3, ver1.minor); + test_eq(4, ver1.micro); + test_eq(VER_RELEASE, ver1.status); + test_eq(0, ver1.patchlevel); + test_eq(0, tor_version_parse("1.3.4.999", &ver1)); + test_eq(1, ver1.major); + test_eq(3, ver1.minor); + test_eq(4, ver1.micro); + test_eq(VER_RELEASE, ver1.status); + test_eq(999, ver1.patchlevel); + test_eq(0, tor_version_parse("0.1.2.4-alpha", &ver1)); + test_eq(0, ver1.major); + test_eq(1, ver1.minor); + test_eq(2, ver1.micro); + test_eq(4, ver1.patchlevel); + test_eq(VER_RELEASE, ver1.status); + test_streq("alpha", ver1.status_tag); + test_eq(0, tor_version_parse("0.1.2.4", &ver1)); + test_eq(0, ver1.major); + test_eq(1, ver1.minor); + test_eq(2, ver1.micro); + test_eq(4, ver1.patchlevel); + test_eq(VER_RELEASE, ver1.status); + test_streq("", ver1.status_tag); + +#define tt_versionstatus_op(vs1, op, vs2) \ + tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \ + (_val1 op _val2),"%d") +#define test_v_i_o(val, ver, lst) \ + tt_versionstatus_op(val, ==, tor_version_is_obsolete(ver, lst)) + + /* make sure tor_version_is_obsolete() works */ + test_v_i_o(VS_OLD, "0.0.1", "Tor 0.0.2"); + test_v_i_o(VS_OLD, "0.0.1", "0.0.2, Tor 0.0.3"); + test_v_i_o(VS_OLD, "0.0.1", "0.0.2,Tor 0.0.3"); + test_v_i_o(VS_OLD, "0.0.1","0.0.3,BetterTor 0.0.1"); + test_v_i_o(VS_RECOMMENDED, "0.0.2", "Tor 0.0.2,Tor 0.0.3"); + test_v_i_o(VS_NEW_IN_SERIES, "0.0.2", "Tor 0.0.2pre1,Tor 0.0.3"); + test_v_i_o(VS_OLD, "0.0.2", "Tor 0.0.2.1,Tor 0.0.3"); + test_v_i_o(VS_NEW, "0.1.0", "Tor 0.0.2,Tor 0.0.3"); + test_v_i_o(VS_RECOMMENDED, "0.0.7rc2", "0.0.7,Tor 0.0.7rc2,Tor 0.0.8"); + test_v_i_o(VS_OLD, "0.0.5.0", "0.0.5.1-cvs"); + test_v_i_o(VS_NEW_IN_SERIES, "0.0.5.1-cvs", "0.0.5, 0.0.6"); + /* Not on list, but newer than any in same series. */ + test_v_i_o(VS_NEW_IN_SERIES, "0.1.0.3", + "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); + /* Series newer than any on list. */ + test_v_i_o(VS_NEW, "0.1.2.3", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); + /* Series older than any on list. */ + test_v_i_o(VS_OLD, "0.0.1.3", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); + /* Not on list, not newer than any on same series. */ + test_v_i_o(VS_UNRECOMMENDED, "0.1.0.1", + "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); + /* On list, not newer than any on same series. */ + test_v_i_o(VS_UNRECOMMENDED, + "0.1.0.1", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0"); + test_eq(0, tor_version_as_new_as("Tor 0.0.5", "0.0.9pre1-cvs")); + test_eq(1, tor_version_as_new_as( + "Tor 0.0.8 on Darwin 64-121-192-100.c3-0." + "sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh", + "0.0.8rc2")); + test_eq(0, tor_version_as_new_as( + "Tor 0.0.8 on Darwin 64-121-192-100.c3-0." + "sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh", "0.0.8.2")); + + /* Now try svn revisions. */ + test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", + "Tor 0.2.1.0-dev (r99)")); + test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100) on Banana Jr", + "Tor 0.2.1.0-dev (r99) on Hal 9000")); + test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)", + "Tor 0.2.1.0-dev on Colossus")); + test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99)", + "Tor 0.2.1.0-dev (r100)")); + test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99) on MCP", + "Tor 0.2.1.0-dev (r100) on AM")); + test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev", + "Tor 0.2.1.0-dev (r99)")); + test_eq(1, tor_version_as_new_as("Tor 0.2.1.1", + "Tor 0.2.1.0-dev (r99)")); + + /* Now try git revisions */ + test_eq(0, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1)); + test_eq(0, ver1.major); + test_eq(5, ver1.minor); + test_eq(6, ver1.micro); + test_eq(7, ver1.patchlevel); + test_eq(3, ver1.git_tag_len); + test_memeq(ver1.git_tag, "\xff\x00\xff", 3); + test_eq(-1, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1)); + test_eq(-1, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1)); + test_eq(0, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1)); + done: + ; +} + +/** Run unit tests for directory fp_pair functions. */ +static void +test_dir_fp_pairs(void) +{ + smartlist_t *sl = smartlist_create(); + fp_pair_t *pair; + + dir_split_resource_into_fingerprint_pairs( + /* Two pairs, out of order, with one duplicate. */ + "73656372657420646174612E0000000000FFFFFF-" + "557365204145532d32353620696e73746561642e+" + "73656372657420646174612E0000000000FFFFFF-" + "557365204145532d32353620696e73746561642e+" + "48657861646563696d616c2069736e277420736f-" + "676f6f6420666f7220686964696e6720796f7572.z", sl); + + test_eq(smartlist_len(sl), 2); + pair = smartlist_get(sl, 0); + test_memeq(pair->first, "Hexadecimal isn't so", DIGEST_LEN); + test_memeq(pair->second, "good for hiding your", DIGEST_LEN); + pair = smartlist_get(sl, 1); + test_memeq(pair->first, "secret data.\0\0\0\0\0\xff\xff\xff", DIGEST_LEN); + test_memeq(pair->second, "Use AES-256 instead.", DIGEST_LEN); + + done: + SMARTLIST_FOREACH(sl, fp_pair_t *, pair, tor_free(pair)); + smartlist_free(sl); +} + +static void +test_dir_split_fps(void *testdata) +{ + smartlist_t *sl = smartlist_create(); + char *mem_op_hex_tmp = NULL; + (void)testdata; + + /* Some example hex fingerprints and their base64 equivalents */ +#define HEX1 "Fe0daff89127389bc67558691231234551193EEE" +#define HEX2 "Deadbeef99999991111119999911111111f00ba4" +#define HEX3 "b33ff00db33ff00db33ff00db33ff00db33ff00d" +#define HEX256_1 \ + "f3f3f3f3fbbbbf3f3f3f3fbbbf3f3f3f3fbbbbf3f3f3f3fbbbf3f3f3f3fbbbbf" +#define HEX256_2 \ + "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccCCc" +#define HEX256_3 \ + "0123456789ABCdef0123456789ABCdef0123456789ABCdef0123456789ABCdef" +#define B64_1 "/g2v+JEnOJvGdVhpEjEjRVEZPu4" +#define B64_2 "3q2+75mZmZERERmZmRERERHwC6Q" +#define B64_3 "sz/wDbM/8A2zP/ANsz/wDbM/8A0" +#define B64_256_1 "8/Pz8/u7vz8/Pz+7vz8/Pz+7u/Pz8/P7u/Pz8/P7u78" +#define B64_256_2 "zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMw" +#define B64_256_3 "ASNFZ4mrze8BI0VniavN7wEjRWeJq83vASNFZ4mrze8" + + /* no flags set */ + dir_split_resource_into_fingerprints("A+C+B", sl, NULL, 0); + tt_int_op(smartlist_len(sl), ==, 3); + tt_str_op(smartlist_get(sl, 0), ==, "A"); + tt_str_op(smartlist_get(sl, 1), ==, "C"); + tt_str_op(smartlist_get(sl, 2), ==, "B"); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* uniq strings. */ + dir_split_resource_into_fingerprints("A+C+B+A+B+B", sl, NULL, DSR_SORT_UNIQ); + tt_int_op(smartlist_len(sl), ==, 3); + tt_str_op(smartlist_get(sl, 0), ==, "A"); + tt_str_op(smartlist_get(sl, 1), ==, "B"); + tt_str_op(smartlist_get(sl, 2), ==, "C"); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Decode hex. */ + dir_split_resource_into_fingerprints(HEX1"+"HEX2, sl, NULL, DSR_HEX); + tt_int_op(smartlist_len(sl), ==, 2); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX1); + test_mem_op_hex(smartlist_get(sl, 1), ==, HEX2); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* decode hex and drop weirdness. */ + dir_split_resource_into_fingerprints(HEX1"+bogus+"HEX2"+"HEX256_1, + sl, NULL, DSR_HEX); + tt_int_op(smartlist_len(sl), ==, 2); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX1); + test_mem_op_hex(smartlist_get(sl, 1), ==, HEX2); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Decode long hex */ + dir_split_resource_into_fingerprints(HEX256_1"+"HEX256_2"+"HEX2"+"HEX256_3, + sl, NULL, DSR_HEX|DSR_DIGEST256); + tt_int_op(smartlist_len(sl), ==, 3); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX256_1); + test_mem_op_hex(smartlist_get(sl, 1), ==, HEX256_2); + test_mem_op_hex(smartlist_get(sl, 2), ==, HEX256_3); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Decode hex and sort. */ + dir_split_resource_into_fingerprints(HEX1"+"HEX2"+"HEX3"+"HEX2, + sl, NULL, DSR_HEX|DSR_SORT_UNIQ); + tt_int_op(smartlist_len(sl), ==, 3); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX3); + test_mem_op_hex(smartlist_get(sl, 1), ==, HEX2); + test_mem_op_hex(smartlist_get(sl, 2), ==, HEX1); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Decode long hex and sort */ + dir_split_resource_into_fingerprints(HEX256_1"+"HEX256_2"+"HEX256_3 + "+"HEX256_1, + sl, NULL, + DSR_HEX|DSR_DIGEST256|DSR_SORT_UNIQ); + tt_int_op(smartlist_len(sl), ==, 3); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX256_3); + test_mem_op_hex(smartlist_get(sl, 1), ==, HEX256_2); + test_mem_op_hex(smartlist_get(sl, 2), ==, HEX256_1); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Decode base64 */ + dir_split_resource_into_fingerprints(B64_1"-"B64_2, sl, NULL, DSR_BASE64); + tt_int_op(smartlist_len(sl), ==, 2); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX1); + test_mem_op_hex(smartlist_get(sl, 1), ==, HEX2); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + /* Decode long base64 */ + dir_split_resource_into_fingerprints(B64_256_1"-"B64_256_2, + sl, NULL, DSR_BASE64|DSR_DIGEST256); + tt_int_op(smartlist_len(sl), ==, 2); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX256_1); + test_mem_op_hex(smartlist_get(sl, 1), ==, HEX256_2); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + dir_split_resource_into_fingerprints(B64_256_1, + sl, NULL, DSR_BASE64|DSR_DIGEST256); + tt_int_op(smartlist_len(sl), ==, 1); + test_mem_op_hex(smartlist_get(sl, 0), ==, HEX256_1); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + done: + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_free(sl); + tor_free(mem_op_hex_tmp); +} + +static void +test_dir_measured_bw(void) +{ + measured_bw_line_t mbwl; + int i; + const char *lines_pass[] = { + "node_id=$557365204145532d32353620696e73746561642e bw=1024\n", + "node_id=$557365204145532d32353620696e73746561642e\t bw=1024 \n", + " node_id=$557365204145532d32353620696e73746561642e bw=1024\n", + "\tnoise\tnode_id=$557365204145532d32353620696e73746561642e " + "bw=1024 junk=007\n", + "misc=junk node_id=$557365204145532d32353620696e73746561642e " + "bw=1024 junk=007\n", + "end" + }; + const char *lines_fail[] = { + /* Test possible python stupidity on input */ + "node_id=None bw=1024\n", + "node_id=$None bw=1024\n", + "node_id=$557365204145532d32353620696e73746561642e bw=None\n", + "node_id=$557365204145532d32353620696e73746561642e bw=1024.0\n", + "node_id=$557365204145532d32353620696e73746561642e bw=.1024\n", + "node_id=$557365204145532d32353620696e73746561642e bw=1.024\n", + "node_id=$557365204145532d32353620696e73746561642e bw=1024 bw=0\n", + "node_id=$557365204145532d32353620696e73746561642e bw=1024 bw=None\n", + "node_id=$557365204145532d32353620696e73746561642e bw=-1024\n", + /* Test incomplete writes due to race conditions, partial copies, etc */ + "node_i", + "node_i\n", + "node_id=", + "node_id=\n", + "node_id=$557365204145532d32353620696e73746561642e bw=", + "node_id=$557365204145532d32353620696e73746561642e bw=1024", + "node_id=$557365204145532d32353620696e73746561642e bw=\n", + "node_id=$557365204145532d32353620696e7374", + "node_id=$557365204145532d32353620696e7374\n", + "", + "\n", + " \n ", + " \n\n", + /* Test assorted noise */ + " node_id= ", + "node_id==$557365204145532d32353620696e73746561642e bw==1024\n", + "node_id=$55736520414552d32353620696e73746561642e bw=1024\n", + "node_id=557365204145532d32353620696e73746561642e bw=1024\n", + "node_id= $557365204145532d32353620696e73746561642e bw=0.23\n", + "end" + }; + + for (i = 0; strcmp(lines_fail[i], "end"); i++) { + //fprintf(stderr, "Testing: %s\n", lines_fail[i]); + test_assert(measured_bw_line_parse(&mbwl, lines_fail[i]) == -1); + } + + for (i = 0; strcmp(lines_pass[i], "end"); i++) { + //fprintf(stderr, "Testing: %s %d\n", lines_pass[i], TOR_ISSPACE('\n')); + test_assert(measured_bw_line_parse(&mbwl, lines_pass[i]) == 0); + test_assert(mbwl.bw == 1024); + test_assert(strcmp(mbwl.node_hex, + "557365204145532d32353620696e73746561642e") == 0); + } + + done: + return; +} + +static void +test_dir_param_voting(void) +{ + networkstatus_t vote1, vote2, vote3, vote4; + smartlist_t *votes = smartlist_create(); + char *res = NULL; + + /* dirvote_compute_params only looks at the net_params field of the votes, + so that's all we need to set. + */ + memset(&vote1, 0, sizeof(vote1)); + memset(&vote2, 0, sizeof(vote2)); + memset(&vote3, 0, sizeof(vote3)); + memset(&vote4, 0, sizeof(vote4)); + vote1.net_params = smartlist_create(); + vote2.net_params = smartlist_create(); + vote3.net_params = smartlist_create(); + vote4.net_params = smartlist_create(); + smartlist_split_string(vote1.net_params, + "ab=90 abcd=20 cw=50 x-yz=-99", NULL, 0, 0); + smartlist_split_string(vote2.net_params, + "ab=27 cw=5 x-yz=88", NULL, 0, 0); + smartlist_split_string(vote3.net_params, + "abcd=20 c=60 cw=500 x-yz=-9 zzzzz=101", NULL, 0, 0); + smartlist_split_string(vote4.net_params, + "ab=900 abcd=200 c=1 cw=51 x-yz=100", NULL, 0, 0); + test_eq(100, networkstatus_get_param(&vote4, "x-yz", 50)); + test_eq(222, networkstatus_get_param(&vote4, "foobar", 222)); + + smartlist_add(votes, &vote1); + smartlist_add(votes, &vote2); + smartlist_add(votes, &vote3); + 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"); + + done: + tor_free(res); + SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(vote2.net_params, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(vote3.net_params, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(vote4.net_params, char *, cp, tor_free(cp)); + smartlist_free(vote1.net_params); + smartlist_free(vote2.net_params); + smartlist_free(vote3.net_params); + smartlist_free(vote4.net_params); + smartlist_free(votes); + + return; +} + +extern const char AUTHORITY_CERT_1[]; +extern const char AUTHORITY_SIGNKEY_1[]; +extern const char AUTHORITY_CERT_2[]; +extern const char AUTHORITY_SIGNKEY_2[]; +extern const char AUTHORITY_CERT_3[]; +extern const char AUTHORITY_SIGNKEY_3[]; + +/** Helper: Test that two networkstatus_voter_info_t do in fact represent the + * same voting authority, and that they do in fact have all the same + * information. */ +static void +test_same_voter(networkstatus_voter_info_t *v1, + networkstatus_voter_info_t *v2) +{ + test_streq(v1->nickname, v2->nickname); + test_memeq(v1->identity_digest, v2->identity_digest, DIGEST_LEN); + test_streq(v1->address, v2->address); + test_eq(v1->addr, v2->addr); + test_eq(v1->dir_port, v2->dir_port); + test_eq(v1->or_port, v2->or_port); + test_streq(v1->contact, v2->contact); + test_memeq(v1->vote_digest, v2->vote_digest, DIGEST_LEN); + done: + ; +} + +/** Helper: Make a new routerinfo containing the right information for a + * given vote_routerstatus_t. */ +static routerinfo_t * +generate_ri_from_rs(const vote_routerstatus_t *vrs) +{ + routerinfo_t *r; + const routerstatus_t *rs = &vrs->status; + static time_t published = 0; + + r = tor_malloc_zero(sizeof(routerinfo_t)); + memcpy(r->cache_info.identity_digest, rs->identity_digest, DIGEST_LEN); + memcpy(r->cache_info.signed_descriptor_digest, rs->descriptor_digest, + DIGEST_LEN); + r->cache_info.do_not_cache = 1; + r->cache_info.routerlist_index = -1; + r->cache_info.signed_descriptor_body = + tor_strdup("123456789012345678901234567890123"); + r->cache_info.signed_descriptor_len = + strlen(r->cache_info.signed_descriptor_body); + r->exit_policy = smartlist_create(); + r->cache_info.published_on = ++published + time(NULL); + return r; +} + +/** Helper: get a detached signatures document for one or two + * consensuses. */ +static char * +get_detached_sigs(networkstatus_t *ns, networkstatus_t *ns2) +{ + char *r; + smartlist_t *sl; + tor_assert(ns && ns->flavor == FLAV_NS); + sl = smartlist_create(); + smartlist_add(sl,ns); + if (ns2) + smartlist_add(sl,ns2); + r = networkstatus_get_detached_signatures(sl); + smartlist_free(sl); + return r; +} + +/** Run unit tests for generating and parsing V3 consensus networkstatus + * documents. */ +static void +test_dir_v3_networkstatus(void) +{ + authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL; + crypto_pk_env_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL; + crypto_pk_env_t *sign_skey_leg1=NULL; + const char *msg=NULL; + + time_t now = time(NULL); + networkstatus_voter_info_t *voter; + document_signature_t *sig; + networkstatus_t *vote=NULL, *v1=NULL, *v2=NULL, *v3=NULL, *con=NULL, + *con_md=NULL; + vote_routerstatus_t *vrs; + routerstatus_t *rs; + char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL, *cp; + smartlist_t *votes = smartlist_create(); + + /* For generating the two other consensuses. */ + char *detached_text1=NULL, *detached_text2=NULL; + char *consensus_text2=NULL, *consensus_text3=NULL; + char *consensus_text_md2=NULL, *consensus_text_md3=NULL; + char *consensus_text_md=NULL; + networkstatus_t *con2=NULL, *con_md2=NULL, *con3=NULL, *con_md3=NULL; + ns_detached_signatures_t *dsig1=NULL, *dsig2=NULL; + + /* Parse certificates and keys. */ + cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL); + test_assert(cert1); + test_assert(cert1->is_cross_certified); + cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL); + test_assert(cert2); + cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL); + test_assert(cert3); + sign_skey_1 = crypto_new_pk_env(); + sign_skey_2 = crypto_new_pk_env(); + sign_skey_3 = crypto_new_pk_env(); + sign_skey_leg1 = pk_generate(4); + + test_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, + AUTHORITY_SIGNKEY_1)); + test_assert(!crypto_pk_read_private_key_from_string(sign_skey_2, + AUTHORITY_SIGNKEY_2)); + test_assert(!crypto_pk_read_private_key_from_string(sign_skey_3, + AUTHORITY_SIGNKEY_3)); + + test_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key)); + test_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key)); + + /* + * Set up a vote; generate it; try to parse it. + */ + vote = tor_malloc_zero(sizeof(networkstatus_t)); + vote->type = NS_TYPE_VOTE; + vote->published = now; + vote->valid_after = now+1000; + vote->fresh_until = now+2000; + vote->valid_until = now+3000; + vote->vote_seconds = 100; + vote->dist_seconds = 200; + vote->supported_methods = smartlist_create(); + smartlist_split_string(vote->supported_methods, "1 2 3", NULL, 0, -1); + vote->client_versions = tor_strdup("0.1.2.14,0.1.2.15"); + vote->server_versions = tor_strdup("0.1.2.14,0.1.2.15,0.1.2.16"); + vote->known_flags = smartlist_create(); + smartlist_split_string(vote->known_flags, + "Authority Exit Fast Guard Running Stable V2Dir Valid", + 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + vote->voters = smartlist_create(); + voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t)); + voter->nickname = tor_strdup("Voter1"); + voter->address = tor_strdup("1.2.3.4"); + voter->addr = 0x01020304; + voter->dir_port = 80; + voter->or_port = 9000; + voter->contact = tor_strdup("voter@example.com"); + crypto_pk_get_digest(cert1->identity_key, voter->identity_digest); + smartlist_add(vote->voters, voter); + vote->cert = authority_cert_dup(cert1); + vote->net_params = smartlist_create(); + smartlist_split_string(vote->net_params, "circuitwindow=101 foo=990", + NULL, 0, 0); + vote->routerstatus_list = smartlist_create(); + /* add the first routerstatus. */ + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + vrs->version = tor_strdup("0.1.2.14"); + rs->published_on = now-1500; + strlcpy(rs->nickname, "router2", sizeof(rs->nickname)); + memset(rs->identity_digest, 3, DIGEST_LEN); + memset(rs->descriptor_digest, 78, DIGEST_LEN); + rs->addr = 0x99008801; + rs->or_port = 443; + rs->dir_port = 8000; + /* all flags but running cleared */ + rs->is_running = 1; + smartlist_add(vote->routerstatus_list, vrs); + test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); + + /* add the second routerstatus. */ + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + vrs->version = tor_strdup("0.2.0.5"); + rs->published_on = now-1000; + strlcpy(rs->nickname, "router1", sizeof(rs->nickname)); + memset(rs->identity_digest, 5, DIGEST_LEN); + memset(rs->descriptor_digest, 77, DIGEST_LEN); + 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_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); + + /* add the third routerstatus. */ + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + vrs->version = tor_strdup("0.1.0.3"); + rs->published_on = now-1000; + strlcpy(rs->nickname, "router3", sizeof(rs->nickname)); + memset(rs->identity_digest, 33, DIGEST_LEN); + memset(rs->descriptor_digest, 79, DIGEST_LEN); + rs->addr = 0xAA009901; + 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; + smartlist_add(vote->routerstatus_list, vrs); + test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); + + /* add a fourth routerstatus that is not running. */ + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + vrs->version = tor_strdup("0.1.6.3"); + rs->published_on = now-1000; + strlcpy(rs->nickname, "router4", sizeof(rs->nickname)); + memset(rs->identity_digest, 34, DIGEST_LEN); + memset(rs->descriptor_digest, 47, DIGEST_LEN); + rs->addr = 0xC0000203; + rs->or_port = 500; + rs->dir_port = 1999; + /* Running flag (and others) cleared */ + smartlist_add(vote->routerstatus_list, vrs); + test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); + + /* dump the vote and try to parse it. */ + v1_text = format_networkstatus_vote(sign_skey_1, vote); + test_assert(v1_text); + v1 = networkstatus_parse_vote_from_string(v1_text, NULL, NS_TYPE_VOTE); + test_assert(v1); + + /* Make sure the parsed thing was right. */ + test_eq(v1->type, NS_TYPE_VOTE); + test_eq(v1->published, vote->published); + test_eq(v1->valid_after, vote->valid_after); + test_eq(v1->fresh_until, vote->fresh_until); + test_eq(v1->valid_until, vote->valid_until); + test_eq(v1->vote_seconds, vote->vote_seconds); + test_eq(v1->dist_seconds, vote->dist_seconds); + test_streq(v1->client_versions, vote->client_versions); + test_streq(v1->server_versions, vote->server_versions); + test_assert(v1->voters && smartlist_len(v1->voters)); + voter = smartlist_get(v1->voters, 0); + test_streq(voter->nickname, "Voter1"); + test_streq(voter->address, "1.2.3.4"); + test_eq(voter->addr, 0x01020304); + test_eq(voter->dir_port, 80); + test_eq(voter->or_port, 9000); + test_streq(voter->contact, "voter@example.com"); + test_assert(v1->cert); + test_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key)); + cp = smartlist_join_strings(v1->known_flags, ":", 0, NULL); + test_streq(cp, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid"); + tor_free(cp); + test_eq(smartlist_len(v1->routerstatus_list), 4); + /* Check the first routerstatus. */ + vrs = smartlist_get(v1->routerstatus_list, 0); + rs = &vrs->status; + test_streq(vrs->version, "0.1.2.14"); + test_eq(rs->published_on, now-1500); + test_streq(rs->nickname, "router2"); + test_memeq(rs->identity_digest, + "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", + DIGEST_LEN); + test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); + test_eq(rs->addr, 0x99008801); + test_eq(rs->or_port, 443); + test_eq(rs->dir_port, 8000); + test_eq(vrs->flags, U64_LITERAL(16)); // no flags except "running" + /* Check the second routerstatus. */ + vrs = smartlist_get(v1->routerstatus_list, 1); + rs = &vrs->status; + test_streq(vrs->version, "0.2.0.5"); + test_eq(rs->published_on, now-1000); + test_streq(rs->nickname, "router1"); + test_memeq(rs->identity_digest, + "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", + DIGEST_LEN); + test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); + test_eq(rs->addr, 0x99009901); + test_eq(rs->or_port, 443); + test_eq(rs->dir_port, 0); + test_eq(vrs->flags, U64_LITERAL(254)); // all flags except "authority." + + { + measured_bw_line_t mbw; + memset(mbw.node_id, 33, sizeof(mbw.node_id)); + mbw.bw = 1024; + test_assert(measured_bw_line_apply(&mbw, + v1->routerstatus_list) == 1); + vrs = smartlist_get(v1->routerstatus_list, 2); + test_assert(vrs->status.has_measured_bw && + vrs->status.measured_bw == 1024); + } + + /* Generate second vote. It disagrees on some of the times, + * and doesn't list versions, and knows some crazy flags */ + vote->published = now+1; + vote->fresh_until = now+3005; + vote->dist_seconds = 300; + authority_cert_free(vote->cert); + vote->cert = authority_cert_dup(cert2); + vote->net_params = smartlist_create(); + smartlist_split_string(vote->net_params, "bar=2000000000 circuitwindow=20", + NULL, 0, 0); + tor_free(vote->client_versions); + tor_free(vote->server_versions); + voter = smartlist_get(vote->voters, 0); + tor_free(voter->nickname); + tor_free(voter->address); + voter->nickname = tor_strdup("Voter2"); + voter->address = tor_strdup("2.3.4.5"); + voter->addr = 0x02030405; + crypto_pk_get_digest(cert2->identity_key, voter->identity_digest); + smartlist_add(vote->known_flags, tor_strdup("MadeOfCheese")); + smartlist_add(vote->known_flags, tor_strdup("MadeOfTin")); + smartlist_sort_strings(vote->known_flags); + vrs = smartlist_get(vote->routerstatus_list, 2); + smartlist_del_keeporder(vote->routerstatus_list, 2); + tor_free(vrs->version); + tor_free(vrs); + vrs = smartlist_get(vote->routerstatus_list, 0); + vrs->status.is_fast = 1; + /* generate and parse. */ + v2_text = format_networkstatus_vote(sign_skey_2, vote); + test_assert(v2_text); + v2 = networkstatus_parse_vote_from_string(v2_text, NULL, NS_TYPE_VOTE); + test_assert(v2); + /* Check that flags come out right.*/ + cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL); + test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" + "Running:Stable:V2Dir:Valid"); + tor_free(cp); + vrs = smartlist_get(v2->routerstatus_list, 1); + /* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) */ + test_eq(vrs->flags, U64_LITERAL(974)); + + /* Generate the third vote. */ + vote->published = now; + vote->fresh_until = now+2003; + vote->dist_seconds = 250; + authority_cert_free(vote->cert); + vote->cert = authority_cert_dup(cert3); + vote->net_params = smartlist_create(); + smartlist_split_string(vote->net_params, "circuitwindow=80 foo=660", + NULL, 0, 0); + smartlist_add(vote->supported_methods, tor_strdup("4")); + vote->client_versions = tor_strdup("0.1.2.14,0.1.2.17"); + vote->server_versions = tor_strdup("0.1.2.10,0.1.2.15,0.1.2.16"); + voter = smartlist_get(vote->voters, 0); + tor_free(voter->nickname); + tor_free(voter->address); + voter->nickname = tor_strdup("Voter3"); + voter->address = tor_strdup("3.4.5.6"); + voter->addr = 0x03040506; + crypto_pk_get_digest(cert3->identity_key, voter->identity_digest); + /* This one has a legacy id. */ + memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN); + vrs = smartlist_get(vote->routerstatus_list, 0); + smartlist_del_keeporder(vote->routerstatus_list, 0); + tor_free(vrs->version); + tor_free(vrs); + vrs = smartlist_get(vote->routerstatus_list, 0); + memset(vrs->status.descriptor_digest, (int)'Z', DIGEST_LEN); + test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); + + v3_text = format_networkstatus_vote(sign_skey_3, vote); + test_assert(v3_text); + + v3 = networkstatus_parse_vote_from_string(v3_text, NULL, NS_TYPE_VOTE); + test_assert(v3); + + /* Compute a consensus as voter 3. */ + smartlist_add(votes, v3); + smartlist_add(votes, v1); + smartlist_add(votes, v2); + consensus_text = networkstatus_compute_consensus(votes, 3, + cert3->identity_key, + sign_skey_3, + "AAAAAAAAAAAAAAAAAAAA", + sign_skey_leg1, + FLAV_NS); + test_assert(consensus_text); + con = networkstatus_parse_vote_from_string(consensus_text, NULL, + NS_TYPE_CONSENSUS); + test_assert(con); + //log_notice(LD_GENERAL, "<<%s>>\n<<%s>>\n<<%s>>\n", + // v1_text, v2_text, v3_text); + consensus_text_md = networkstatus_compute_consensus(votes, 3, + cert3->identity_key, + sign_skey_3, + "AAAAAAAAAAAAAAAAAAAA", + sign_skey_leg1, + FLAV_MICRODESC); + test_assert(consensus_text_md); + con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL, + NS_TYPE_CONSENSUS); + test_assert(con_md); + test_eq(con_md->flavor, FLAV_MICRODESC); + + /* Check consensus contents. */ + test_assert(con->type == NS_TYPE_CONSENSUS); + test_eq(con->published, 0); /* this field only appears in votes. */ + test_eq(con->valid_after, now+1000); + test_eq(con->fresh_until, now+2003); /* median */ + test_eq(con->valid_until, now+3000); + test_eq(con->vote_seconds, 100); + test_eq(con->dist_seconds, 250); /* median */ + test_streq(con->client_versions, "0.1.2.14"); + test_streq(con->server_versions, "0.1.2.15,0.1.2.16"); + cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL); + test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:" + "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"); + tor_free(cp); + + test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/ + /* The voter id digests should be in this order. */ + test_assert(memcmp(cert2->cache_info.identity_digest, + cert1->cache_info.identity_digest,DIGEST_LEN)<0); + test_assert(memcmp(cert1->cache_info.identity_digest, + cert3->cache_info.identity_digest,DIGEST_LEN)<0); + test_same_voter(smartlist_get(con->voters, 1), + smartlist_get(v2->voters, 0)); + test_same_voter(smartlist_get(con->voters, 2), + smartlist_get(v1->voters, 0)); + test_same_voter(smartlist_get(con->voters, 3), + smartlist_get(v3->voters, 0)); + + test_assert(!con->cert); + test_eq(2, smartlist_len(con->routerstatus_list)); + /* There should be two listed routers: one with identity 3, one with + * identity 5. */ + /* This one showed up in 2 digests. */ + rs = smartlist_get(con->routerstatus_list, 0); + test_memeq(rs->identity_digest, + "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", + DIGEST_LEN); + test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN); + test_assert(!rs->is_authority); + test_assert(!rs->is_exit); + 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 */ + test_assert(!rs->is_v2_dir); + test_assert(!rs->is_valid); + test_assert(!rs->is_named); + /* XXXX check version */ + + rs = smartlist_get(con->routerstatus_list, 1); + /* This one showed up in 3 digests. Twice with ID 'M', once with 'Z'. */ + test_memeq(rs->identity_digest, + "\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5", + DIGEST_LEN); + test_streq(rs->nickname, "router1"); + test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN); + test_eq(rs->published_on, now-1000); + test_eq(rs->addr, 0x99009901); + test_eq(rs->or_port, 443); + test_eq(rs->dir_port, 0); + test_assert(!rs->is_authority); + test_assert(rs->is_exit); + 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_v2_dir); + test_assert(rs->is_valid); + test_assert(!rs->is_named); + /* XXXX check version */ + + /* Check signatures. the first voter is a pseudo-entry with a legacy key. + * The second one hasn't signed. The fourth one has signed: validate it. */ + voter = smartlist_get(con->voters, 1); + test_eq(smartlist_len(voter->sigs), 0); + + voter = smartlist_get(con->voters, 3); + test_eq(smartlist_len(voter->sigs), 1); + sig = smartlist_get(voter->sigs, 0); + test_assert(sig->signature); + test_assert(!sig->good_signature); + test_assert(!sig->bad_signature); + + test_assert(!networkstatus_check_document_signature(con, sig, cert3)); + test_assert(sig->signature); + test_assert(sig->good_signature); + test_assert(!sig->bad_signature); + + { + const char *msg=NULL; + /* Compute the other two signed consensuses. */ + smartlist_shuffle(votes); + consensus_text2 = networkstatus_compute_consensus(votes, 3, + cert2->identity_key, + sign_skey_2, NULL,NULL, + FLAV_NS); + consensus_text_md2 = networkstatus_compute_consensus(votes, 3, + cert2->identity_key, + sign_skey_2, NULL,NULL, + FLAV_MICRODESC); + smartlist_shuffle(votes); + consensus_text3 = networkstatus_compute_consensus(votes, 3, + cert1->identity_key, + sign_skey_1, NULL,NULL, + FLAV_NS); + consensus_text_md3 = networkstatus_compute_consensus(votes, 3, + cert1->identity_key, + sign_skey_1, NULL,NULL, + FLAV_MICRODESC); + test_assert(consensus_text2); + test_assert(consensus_text3); + test_assert(consensus_text_md2); + test_assert(consensus_text_md3); + con2 = networkstatus_parse_vote_from_string(consensus_text2, NULL, + NS_TYPE_CONSENSUS); + con3 = networkstatus_parse_vote_from_string(consensus_text3, NULL, + NS_TYPE_CONSENSUS); + con_md2 = networkstatus_parse_vote_from_string(consensus_text_md2, NULL, + NS_TYPE_CONSENSUS); + con_md3 = networkstatus_parse_vote_from_string(consensus_text_md3, NULL, + NS_TYPE_CONSENSUS); + test_assert(con2); + test_assert(con3); + test_assert(con_md2); + test_assert(con_md3); + + /* All three should have the same digest. */ + test_memeq(&con->digests, &con2->digests, sizeof(digests_t)); + test_memeq(&con->digests, &con3->digests, sizeof(digests_t)); + + test_memeq(&con_md->digests, &con_md2->digests, sizeof(digests_t)); + test_memeq(&con_md->digests, &con_md3->digests, sizeof(digests_t)); + + /* Extract a detached signature from con3. */ + detached_text1 = get_detached_sigs(con3, con_md3); + tor_assert(detached_text1); + /* Try to parse it. */ + dsig1 = networkstatus_parse_detached_signatures(detached_text1, NULL); + tor_assert(dsig1); + + /* Are parsed values as expected? */ + test_eq(dsig1->valid_after, con3->valid_after); + test_eq(dsig1->fresh_until, con3->fresh_until); + test_eq(dsig1->valid_until, con3->valid_until); + { + digests_t *dsig_digests = strmap_get(dsig1->digests, "ns"); + test_assert(dsig_digests); + test_memeq(dsig_digests->d[DIGEST_SHA1], con3->digests.d[DIGEST_SHA1], + DIGEST_LEN); + dsig_digests = strmap_get(dsig1->digests, "microdesc"); + test_assert(dsig_digests); + test_memeq(dsig_digests->d[DIGEST_SHA256], + con_md3->digests.d[DIGEST_SHA256], + DIGEST256_LEN); + } + { + smartlist_t *dsig_signatures = strmap_get(dsig1->signatures, "ns"); + test_assert(dsig_signatures); + test_eq(1, smartlist_len(dsig_signatures)); + sig = smartlist_get(dsig_signatures, 0); + test_memeq(sig->identity_digest, cert1->cache_info.identity_digest, + DIGEST_LEN); + test_eq(sig->alg, DIGEST_SHA1); + + dsig_signatures = strmap_get(dsig1->signatures, "microdesc"); + test_assert(dsig_signatures); + test_eq(1, smartlist_len(dsig_signatures)); + sig = smartlist_get(dsig_signatures, 0); + test_memeq(sig->identity_digest, cert1->cache_info.identity_digest, + DIGEST_LEN); + test_eq(sig->alg, DIGEST_SHA256); + } + + /* Try adding it to con2. */ + detached_text2 = get_detached_sigs(con2,con_md2); + test_eq(1, networkstatus_add_detached_signatures(con2, dsig1, &msg)); + tor_free(detached_text2); + test_eq(1, networkstatus_add_detached_signatures(con_md2, dsig1, &msg)); + tor_free(detached_text2); + detached_text2 = get_detached_sigs(con2,con_md2); + //printf("\n<%s>\n", detached_text2); + dsig2 = networkstatus_parse_detached_signatures(detached_text2, NULL); + test_assert(dsig2); + /* + printf("\n"); + SMARTLIST_FOREACH(dsig2->signatures, networkstatus_voter_info_t *, vi, { + char hd[64]; + base16_encode(hd, sizeof(hd), vi->identity_digest, DIGEST_LEN); + printf("%s\n", hd); + }); + */ + test_eq(2, + smartlist_len((smartlist_t*)strmap_get(dsig2->signatures, "ns"))); + test_eq(2, + smartlist_len((smartlist_t*)strmap_get(dsig2->signatures, + "microdesc"))); + + /* Try adding to con2 twice; verify that nothing changes. */ + test_eq(0, networkstatus_add_detached_signatures(con2, dsig1, &msg)); + + /* Add to con. */ + test_eq(2, networkstatus_add_detached_signatures(con, dsig2, &msg)); + /* Check signatures */ + voter = smartlist_get(con->voters, 1); + sig = smartlist_get(voter->sigs, 0); + test_assert(sig); + test_assert(!networkstatus_check_document_signature(con, sig, cert2)); + voter = smartlist_get(con->voters, 2); + sig = smartlist_get(voter->sigs, 0); + test_assert(sig); + test_assert(!networkstatus_check_document_signature(con, sig, cert1)); + } + + done: + smartlist_free(votes); + tor_free(v1_text); + tor_free(v2_text); + tor_free(v3_text); + tor_free(consensus_text); + tor_free(consensus_text_md); + + if (vote) + networkstatus_vote_free(vote); + if (v1) + networkstatus_vote_free(v1); + if (v2) + networkstatus_vote_free(v2); + if (v3) + networkstatus_vote_free(v3); + if (con) + networkstatus_vote_free(con); + if (con_md) + networkstatus_vote_free(con_md); + if (sign_skey_1) + crypto_free_pk_env(sign_skey_1); + if (sign_skey_2) + crypto_free_pk_env(sign_skey_2); + if (sign_skey_3) + crypto_free_pk_env(sign_skey_3); + if (sign_skey_leg1) + crypto_free_pk_env(sign_skey_leg1); + if (cert1) + authority_cert_free(cert1); + if (cert2) + authority_cert_free(cert2); + if (cert3) + authority_cert_free(cert3); + + tor_free(consensus_text2); + tor_free(consensus_text3); + tor_free(consensus_text_md2); + tor_free(consensus_text_md3); + tor_free(detached_text1); + tor_free(detached_text2); + if (con2) + networkstatus_vote_free(con2); + if (con3) + networkstatus_vote_free(con3); + if (con_md2) + networkstatus_vote_free(con_md2); + if (con_md3) + networkstatus_vote_free(con_md3); + if (dsig1) + ns_detached_signatures_free(dsig1); + if (dsig2) + ns_detached_signatures_free(dsig2); +} + +#define DIR_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_dir_ ## name } + +#define DIR(name) \ + { #name, test_dir_##name, 0, NULL, NULL } + +struct testcase_t dir_tests[] = { + DIR_LEGACY(nicknames), + DIR_LEGACY(formats), + DIR_LEGACY(versions), + DIR_LEGACY(fp_pairs), + DIR(split_fps), + DIR_LEGACY(measured_bw), + DIR_LEGACY(param_voting), + DIR_LEGACY(v3_networkstatus), + END_OF_TESTCASES +}; + diff --git a/src/test/test_util.c b/src/test/test_util.c new file mode 100644 index 0000000000..a14d548b8e --- /dev/null +++ b/src/test/test_util.c @@ -0,0 +1,1239 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#define CONTROL_PRIVATE +#define MEMPOOL_PRIVATE +#include "or.h" +#include "config.h" +#include "control.h" +#include "test.h" +#include "mempool.h" +#include "memarea.h" + +static void +test_util_time(void) +{ + struct timeval start, end; + struct tm a_time; + char timestr[RFC1123_TIME_LEN+1]; + time_t t_res; + int i; + + start.tv_sec = 5; + start.tv_usec = 5000; + + end.tv_sec = 5; + end.tv_usec = 5000; + + test_eq(0L, tv_udiff(&start, &end)); + + end.tv_usec = 7000; + + test_eq(2000L, tv_udiff(&start, &end)); + + end.tv_sec = 6; + + test_eq(1002000L, tv_udiff(&start, &end)); + + end.tv_usec = 0; + + test_eq(995000L, tv_udiff(&start, &end)); + + end.tv_sec = 4; + + test_eq(-1005000L, tv_udiff(&start, &end)); + + end.tv_usec = 999990; + start.tv_sec = 1; + start.tv_usec = 500; + + /* The test values here are confirmed to be correct on a platform + * with a working timegm. */ + a_time.tm_year = 2003-1900; + a_time.tm_mon = 7; + a_time.tm_mday = 30; + a_time.tm_hour = 6; + a_time.tm_min = 14; + a_time.tm_sec = 55; + test_eq((time_t) 1062224095UL, tor_timegm(&a_time)); + a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */ + test_eq((time_t) 1093846495UL, tor_timegm(&a_time)); + a_time.tm_mon = 1; /* Try a leap year, in feb. */ + a_time.tm_mday = 10; + test_eq((time_t) 1076393695UL, tor_timegm(&a_time)); + + format_rfc1123_time(timestr, 0); + test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr); + format_rfc1123_time(timestr, (time_t)1091580502UL); + test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr); + + t_res = 0; + i = parse_rfc1123_time(timestr, &t_res); + test_eq(i,0); + test_eq(t_res, (time_t)1091580502UL); + test_eq(-1, parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res)); + + tor_gettimeofday(&start); + /* now make sure time works. */ + tor_gettimeofday(&end); + /* We might've timewarped a little. */ + tt_int_op(tv_udiff(&start, &end), >=, -5000); + + done: + ; +} + +static void +test_util_config_line(void) +{ + char buf[1024]; + char *k=NULL, *v=NULL; + const char *str; + + /* Test parse_config_line_from_str */ + strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n" + "k2\n" + "k3 \n" "\n" " \n" "#comment\n" + "k4#a\n" "k5#abc\n" "k6 val #with comment\n" + "kseven \"a quoted 'string\"\n" + "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n" + "k9 a line that\\\n spans two lines.\n\n" + "k10 more than\\\n one contin\\\nuation\n" + "k11 \\\ncontinuation at the start\n" + "k12 line with a\\\n#comment\n embedded\n" + "k13\\\ncontinuation at the very start\n" + "k14 a line that has a comment and # ends with a slash \\\n" + "k15 this should be the next new line\n" + "k16 a line that has a comment and # ends without a slash \n" + "k17 this should be the next new line\n" + , sizeof(buf)); + str = buf; + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k"); + test_streq(v, "v"); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "key value with")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "key"); + test_streq(v, "value with spaces"); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "keykey")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "keykey"); + test_streq(v, "val"); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "k2\n")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k2"); + test_streq(v, ""); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "k3 \n")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k3"); + test_streq(v, ""); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "#comment")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k4"); + test_streq(v, ""); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "k5#abc")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k5"); + test_streq(v, ""); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "k6")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k6"); + test_streq(v, "val"); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "kseven")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "kseven"); + test_streq(v, "a quoted \'string"); + tor_free(k); tor_free(v); + test_assert(!strcmpstart(str, "k8 ")); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k8"); + test_streq(v, "a quoted\n\"str\\ing\t\x01\x01\x01\""); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k9"); + test_streq(v, "a line that spans two lines."); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k10"); + test_streq(v, "more than one continuation"); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k11"); + test_streq(v, "continuation at the start"); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k12"); + test_streq(v, "line with a embedded"); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k13"); + test_streq(v, "continuation at the very start"); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k14"); + test_streq(v, "a line that has a comment and" ); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k15"); + test_streq(v, "this should be the next new line"); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k16"); + test_streq(v, "a line that has a comment and" ); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str(str, &k, &v); + test_streq(k, "k17"); + test_streq(v, "this should be the next new line"); + tor_free(k); tor_free(v); + + test_streq(str, ""); + + done: + tor_free(k); + tor_free(v); +} + +/** Test basic string functionality. */ +static void +test_util_strmisc(void) +{ + char buf[1024]; + int i; + char *cp; + + /* Tests for corner cases of strl operations */ + test_eq(5, strlcpy(buf, "Hello", 0)); + strlcpy(buf, "Hello", sizeof(buf)); + test_eq(10, strlcat(buf, "Hello", 5)); + + /* Test tor_strstrip() */ + strlcpy(buf, "Testing 1 2 3", sizeof(buf)); + tor_strstrip(buf, ",!"); + test_streq(buf, "Testing 1 2 3"); + strlcpy(buf, "!Testing 1 2 3?", sizeof(buf)); + tor_strstrip(buf, "!? "); + test_streq(buf, "Testing123"); + + /* Test tor_parse_long. */ + test_eq(10L, tor_parse_long("10",10,0,100,NULL,NULL)); + test_eq(0L, tor_parse_long("10",10,50,100,NULL,NULL)); + test_eq(-50L, tor_parse_long("-50",10,-100,100,NULL,NULL)); + + /* Test tor_parse_ulong */ + test_eq(10UL, tor_parse_ulong("10",10,0,100,NULL,NULL)); + test_eq(0UL, tor_parse_ulong("10",10,50,100,NULL,NULL)); + + /* Test tor_parse_uint64. */ + test_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp)); + test_assert(i == 1); + test_streq(cp, " x"); + test_assert(U64_LITERAL(12345678901) == + tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp)); + test_assert(i == 1); + test_streq(cp, ""); + test_assert(U64_LITERAL(0) == + tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp)); + test_assert(i == 0); + + { + /* Test tor_parse_double. */ + double d = tor_parse_double("10", 0, UINT64_MAX,&i,NULL); + test_assert(i == 1); + test_assert(DBL_TO_U64(d) == 10); + d = tor_parse_double("0", 0, UINT64_MAX,&i,NULL); + test_assert(i == 1); + test_assert(DBL_TO_U64(d) == 0); + d = tor_parse_double(" ", 0, UINT64_MAX,&i,NULL); + test_assert(i == 0); + d = tor_parse_double(".0a", 0, UINT64_MAX,&i,NULL); + test_assert(i == 0); + d = tor_parse_double(".0a", 0, UINT64_MAX,&i,&cp); + test_assert(i == 1); + d = tor_parse_double("-.0", 0, UINT64_MAX,&i,NULL); + test_assert(i == 1); + } + + /* Test failing snprintf cases */ + test_eq(-1, tor_snprintf(buf, 0, "Foo")); + test_eq(-1, tor_snprintf(buf, 2, "Foo")); + + /* Test printf with uint64 */ + tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x", + U64_PRINTF_ARG(U64_LITERAL(12345678901))); + test_streq(buf, "x!12345678901!x"); + + /* Test for strcmpstart and strcmpend. */ + test_assert(strcmpstart("abcdef", "abcdef")==0); + test_assert(strcmpstart("abcdef", "abc")==0); + test_assert(strcmpstart("abcdef", "abd")<0); + test_assert(strcmpstart("abcdef", "abb")>0); + test_assert(strcmpstart("ab", "abb")<0); + + test_assert(strcmpend("abcdef", "abcdef")==0); + test_assert(strcmpend("abcdef", "def")==0); + test_assert(strcmpend("abcdef", "deg")<0); + test_assert(strcmpend("abcdef", "dee")>0); + test_assert(strcmpend("ab", "abb")<0); + + test_assert(strcasecmpend("AbcDEF", "abcdef")==0); + test_assert(strcasecmpend("abcdef", "dEF")==0); + test_assert(strcasecmpend("abcDEf", "deg")<0); + test_assert(strcasecmpend("abcdef", "DEE")>0); + test_assert(strcasecmpend("ab", "abB")<0); + + /* Test mem_is_zero */ + memset(buf,0,128); + buf[128] = 'x'; + test_assert(tor_digest_is_zero(buf)); + test_assert(tor_mem_is_zero(buf, 10)); + test_assert(tor_mem_is_zero(buf, 20)); + test_assert(tor_mem_is_zero(buf, 128)); + test_assert(!tor_mem_is_zero(buf, 129)); + buf[60] = (char)255; + test_assert(!tor_mem_is_zero(buf, 128)); + buf[0] = (char)1; + test_assert(!tor_mem_is_zero(buf, 10)); + + /* Test 'escaped' */ + test_streq("\"\"", escaped("")); + test_streq("\"abcd\"", escaped("abcd")); + test_streq("\"\\\\\\n\\r\\t\\\"\\'\"", escaped("\\\n\r\t\"\'")); + test_streq("\"z\\001abc\\277d\"", escaped("z\001abc\277d")); + test_assert(NULL == escaped(NULL)); + + /* Test strndup and memdup */ + { + const char *s = "abcdefghijklmnopqrstuvwxyz"; + cp = tor_strndup(s, 30); + test_streq(cp, s); /* same string, */ + test_neq(cp, s); /* but different pointers. */ + tor_free(cp); + + cp = tor_strndup(s, 5); + test_streq(cp, "abcde"); + tor_free(cp); + + s = "a\0b\0c\0d\0e\0"; + cp = tor_memdup(s,10); + test_memeq(cp, s, 10); /* same ram, */ + test_neq(cp, s); /* but different pointers. */ + tor_free(cp); + } + + /* Test str-foo functions */ + cp = tor_strdup("abcdef"); + test_assert(tor_strisnonupper(cp)); + cp[3] = 'D'; + test_assert(!tor_strisnonupper(cp)); + tor_strupper(cp); + test_streq(cp, "ABCDEF"); + test_assert(tor_strisprint(cp)); + cp[3] = 3; + 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)); + test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2); + test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2); + haystack = "ababcad"; + test_eq_ptr(tor_memmem(haystack, 7, "abc", 3), haystack + 2); + test_eq_ptr(tor_memstr(haystack, 7, "abc"), haystack + 2); + test_assert(!tor_memstr(haystack, 7, "fe")); + test_assert(!tor_memstr(haystack, 7, "longerthantheoriginal")); + } + + /* Test wrap_string */ + { + smartlist_t *sl = smartlist_create(); + wrap_string(sl, "This is a test of string wrapping functionality: woot.", + 10, "", ""); + cp = smartlist_join_strings(sl, "", 0, NULL); + test_streq(cp, + "This is a\ntest of\nstring\nwrapping\nfunctional\nity: woot.\n"); + tor_free(cp); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_clear(sl); + + wrap_string(sl, "This is a test of string wrapping functionality: woot.", + 16, "### ", "# "); + cp = smartlist_join_strings(sl, "", 0, NULL); + test_streq(cp, + "### This is a\n# test of string\n# wrapping\n# functionality:\n" + "# woot.\n"); + + tor_free(cp); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_free(sl); + } + done: + ; +} + +static void +test_util_pow2(void) +{ + /* Test tor_log2(). */ + test_eq(tor_log2(64), 6); + test_eq(tor_log2(65), 6); + test_eq(tor_log2(63), 5); + test_eq(tor_log2(1), 0); + test_eq(tor_log2(2), 1); + test_eq(tor_log2(3), 1); + test_eq(tor_log2(4), 2); + test_eq(tor_log2(5), 2); + test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55); + test_eq(tor_log2(UINT64_MAX), 63); + + /* Test round_to_power_of_2 */ + test_eq(round_to_power_of_2(120), 128); + test_eq(round_to_power_of_2(128), 128); + test_eq(round_to_power_of_2(130), 128); + test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)), + U64_LITERAL(1)<<55); + test_eq(round_to_power_of_2(0), 2); + + done: + ; +} + +/** mutex for thread test to stop the threads hitting data at the same time. */ +static tor_mutex_t *_thread_test_mutex = NULL; +/** mutexes for the thread test to make sure that the threads have to + * interleave somewhat. */ +static tor_mutex_t *_thread_test_start1 = NULL, + *_thread_test_start2 = NULL; +/** Shared strmap for the thread test. */ +static strmap_t *_thread_test_strmap = NULL; +/** The name of thread1 for the thread test */ +static char *_thread1_name = NULL; +/** The name of thread2 for the thread test */ +static char *_thread2_name = NULL; + +static void _thread_test_func(void* _s) ATTR_NORETURN; + +/** How many iterations have the threads in the unit test run? */ +static int t1_count = 0, t2_count = 0; + +/** Helper function for threading unit tests: This function runs in a + * subthread. It grabs its own mutex (start1 or start2) to make sure that it + * should start, then it repeatedly alters _test_thread_strmap protected by + * _thread_test_mutex. */ +static void +_thread_test_func(void* _s) +{ + char *s = _s; + int i, *count; + tor_mutex_t *m; + char buf[64]; + char **cp; + if (!strcmp(s, "thread 1")) { + m = _thread_test_start1; + cp = &_thread1_name; + count = &t1_count; + } else { + m = _thread_test_start2; + cp = &_thread2_name; + count = &t2_count; + } + + tor_snprintf(buf, sizeof(buf), "%lu", tor_get_thread_id()); + *cp = tor_strdup(buf); + + tor_mutex_acquire(m); + + for (i=0; i<10000; ++i) { + tor_mutex_acquire(_thread_test_mutex); + strmap_set(_thread_test_strmap, "last to run", *cp); + ++*count; + tor_mutex_release(_thread_test_mutex); + } + tor_mutex_acquire(_thread_test_mutex); + strmap_set(_thread_test_strmap, s, *cp); + tor_mutex_release(_thread_test_mutex); + + tor_mutex_release(m); + + spawn_exit(); +} + +/** Run unit tests for threading logic. */ +static void +test_util_threads(void) +{ + char *s1 = NULL, *s2 = NULL; + int done = 0, timedout = 0; + time_t started; +#ifndef MS_WINDOWS + struct timeval tv; + tv.tv_sec=0; + tv.tv_usec=10; +#endif +#ifndef TOR_IS_MULTITHREADED + /* Skip this test if we aren't threading. We should be threading most + * everywhere by now. */ + if (1) + return; +#endif + _thread_test_mutex = tor_mutex_new(); + _thread_test_start1 = tor_mutex_new(); + _thread_test_start2 = tor_mutex_new(); + _thread_test_strmap = strmap_new(); + s1 = tor_strdup("thread 1"); + s2 = tor_strdup("thread 2"); + tor_mutex_acquire(_thread_test_start1); + tor_mutex_acquire(_thread_test_start2); + spawn_func(_thread_test_func, s1); + spawn_func(_thread_test_func, s2); + tor_mutex_release(_thread_test_start2); + tor_mutex_release(_thread_test_start1); + started = time(NULL); + while (!done) { + tor_mutex_acquire(_thread_test_mutex); + strmap_assert_ok(_thread_test_strmap); + if (strmap_get(_thread_test_strmap, "thread 1") && + strmap_get(_thread_test_strmap, "thread 2")) { + done = 1; + } else if (time(NULL) > started + 25) { + timedout = done = 1; + } + tor_mutex_release(_thread_test_mutex); +#ifndef MS_WINDOWS + /* Prevent the main thread from starving the worker threads. */ + select(0, NULL, NULL, NULL, &tv); +#endif + } + tor_mutex_acquire(_thread_test_start1); + tor_mutex_release(_thread_test_start1); + tor_mutex_acquire(_thread_test_start2); + tor_mutex_release(_thread_test_start2); + + tor_mutex_free(_thread_test_mutex); + + if (timedout) { + printf("\nTimed out: %d %d", t1_count, t2_count); + test_assert(strmap_get(_thread_test_strmap, "thread 1")); + test_assert(strmap_get(_thread_test_strmap, "thread 2")); + test_assert(!timedout); + } + + /* different thread IDs. */ + test_assert(strcmp(strmap_get(_thread_test_strmap, "thread 1"), + strmap_get(_thread_test_strmap, "thread 2"))); + test_assert(!strcmp(strmap_get(_thread_test_strmap, "thread 1"), + strmap_get(_thread_test_strmap, "last to run")) || + !strcmp(strmap_get(_thread_test_strmap, "thread 2"), + strmap_get(_thread_test_strmap, "last to run"))); + + done: + tor_free(s1); + tor_free(s2); + tor_free(_thread1_name); + tor_free(_thread2_name); + if (_thread_test_strmap) + strmap_free(_thread_test_strmap, NULL); + if (_thread_test_start1) + tor_mutex_free(_thread_test_start1); + if (_thread_test_start2) + tor_mutex_free(_thread_test_start2); +} + +/** Run unit tests for compression functions */ +static void +test_util_gzip(void) +{ + char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2; + const char *ccp2; + size_t len1, len2; + tor_zlib_state_t *state = NULL; + + buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ"); + test_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD); + if (is_gzip_supported()) { + test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, + GZIP_METHOD)); + test_assert(buf2); + test_assert(!memcmp(buf2, "\037\213", 2)); /* Gzip magic. */ + test_assert(detect_compression_method(buf2, len1) == GZIP_METHOD); + + test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, + GZIP_METHOD, 1, LOG_INFO)); + test_assert(buf3); + test_streq(buf1,buf3); + + tor_free(buf2); + tor_free(buf3); + } + + test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, + ZLIB_METHOD)); + test_assert(buf2); + test_assert(!memcmp(buf2, "\x78\xDA", 2)); /* deflate magic. */ + test_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD); + + test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, + ZLIB_METHOD, 1, LOG_INFO)); + test_assert(buf3); + test_streq(buf1,buf3); + + /* Check whether we can uncompress concatenated, compressed strings. */ + tor_free(buf3); + buf2 = tor_realloc(buf2, len1*2); + memcpy(buf2+len1, buf2, len1); + test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2, + ZLIB_METHOD, 1, LOG_INFO)); + test_eq(len2, (strlen(buf1)+1)*2); + test_memeq(buf3, + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0", + (strlen(buf1)+1)*2); + + tor_free(buf1); + tor_free(buf2); + tor_free(buf3); + + /* Check whether we can uncompress partial strings. */ + buf1 = + 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); + /* when we allow an incomplete string, we should succeed.*/ + tor_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)); + + /* when we demand a complete string, this must fail. */ + tor_free(buf3); + tor_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16, + ZLIB_METHOD, 1, LOG_INFO)); + tor_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); + cp1 = buf1 = tor_malloc(1024); + len1 = 1024; + ccp2 = "ABCDEFGHIJABCDEFGHIJ"; + len2 = 21; + test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0) + == TOR_ZLIB_OK); + test_eq(len2, 0); /* Make sure we compressed it all. */ + test_assert(cp1 > buf1); + + len2 = 0; + cp2 = cp1; + test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1) + == TOR_ZLIB_DONE); + test_eq(len2, 0); + test_assert(cp1 > cp2); /* Make sure we really added something. */ + + tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1, + ZLIB_METHOD, 1, LOG_WARN)); + test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/ + + done: + if (state) + tor_zlib_free(state); + tor_free(buf2); + tor_free(buf3); + tor_free(buf1); +} + +/** Run unit tests for mmap() wrapper functionality. */ +static void +test_util_mmap(void) +{ + char *fname1 = tor_strdup(get_fname("mapped_1")); + char *fname2 = tor_strdup(get_fname("mapped_2")); + char *fname3 = tor_strdup(get_fname("mapped_3")); + const size_t buflen = 17000; + char *buf = tor_malloc(17000); + tor_mmap_t *mapping = NULL; + + crypto_rand(buf, buflen); + + mapping = tor_mmap_file(fname1); + test_assert(! mapping); + + write_str_to_file(fname1, "Short file.", 1); + write_bytes_to_file(fname2, buf, buflen, 1); + write_bytes_to_file(fname3, buf, 16384, 1); + + mapping = tor_mmap_file(fname1); + test_assert(mapping); + test_eq(mapping->size, strlen("Short file.")); + test_streq(mapping->data, "Short file."); +#ifdef MS_WINDOWS + tor_munmap_file(mapping); + mapping = NULL; + test_assert(unlink(fname1) == 0); +#else + /* make sure we can unlink. */ + test_assert(unlink(fname1) == 0); + test_streq(mapping->data, "Short file."); + tor_munmap_file(mapping); + mapping = NULL; +#endif + + /* Now a zero-length file. */ + write_str_to_file(fname1, "", 1); + mapping = tor_mmap_file(fname1); + test_eq(mapping, NULL); + test_eq(ERANGE, errno); + unlink(fname1); + + /* Make sure that we fail to map a no-longer-existent file. */ + mapping = tor_mmap_file(fname1); + test_assert(mapping == NULL); + + /* Now try a big file that stretches across a few pages and isn't aligned */ + mapping = tor_mmap_file(fname2); + test_assert(mapping); + test_eq(mapping->size, buflen); + test_memeq(mapping->data, buf, buflen); + tor_munmap_file(mapping); + mapping = NULL; + + /* Now try a big aligned file. */ + mapping = tor_mmap_file(fname3); + test_assert(mapping); + test_eq(mapping->size, 16384); + test_memeq(mapping->data, buf, 16384); + tor_munmap_file(mapping); + mapping = NULL; + + done: + unlink(fname1); + unlink(fname2); + unlink(fname3); + + tor_free(fname1); + tor_free(fname2); + tor_free(fname3); + tor_free(buf); + + if (mapping) + tor_munmap_file(mapping); +} + +/** Run unit tests for escaping/unescaping data for use by controllers. */ +static void +test_util_control_formats(void) +{ + char *out = NULL; + const char *inp = + "..This is a test\r\nof the emergency \nbroadcast\r\n..system.\r\nZ.\r\n"; + size_t sz; + + sz = read_escaped_data(inp, strlen(inp), &out); + test_streq(out, + ".This is a test\nof the emergency \nbroadcast\n.system.\nZ.\n"); + test_eq(sz, strlen(out)); + + done: + tor_free(out); +} + +static void +test_util_sscanf(void) +{ + unsigned u1, u2, u3; + char s1[10], s2[10], s3[10], ch; + int r; + + r = tor_sscanf("hello world", "hello world"); /* String match: success */ + test_eq(r, 0); + r = tor_sscanf("hello world 3", "hello worlb %u", &u1); /* String fail */ + test_eq(r, 0); + r = tor_sscanf("12345", "%u", &u1); /* Simple number */ + test_eq(r, 1); + test_eq(u1, 12345u); + r = tor_sscanf("", "%u", &u1); /* absent number */ + test_eq(r, 0); + r = tor_sscanf("A", "%u", &u1); /* bogus number */ + test_eq(r, 0); + r = tor_sscanf("4294967295", "%u", &u1); /* UINT32_MAX should work. */ + test_eq(r, 1); + test_eq(u1, 4294967295u); + r = tor_sscanf("4294967296", "%u", &u1); /* Always say -1 at 32 bits. */ + test_eq(r, 0); + r = tor_sscanf("123456", "%2u%u", &u1, &u2); /* Width */ + test_eq(r, 2); + test_eq(u1, 12u); + test_eq(u2, 3456u); + r = tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3); /* separators */ + test_eq(r, 3); + test_eq(u1, 12u); + test_eq(u2, 3u); + test_eq(u3, 456u); + r = tor_sscanf("12:3:045", "%2u:%2u:%3u", &u1, &u2, &u3); /* 0s */ + test_eq(r, 3); + test_eq(u1, 12u); + test_eq(u2, 3u); + test_eq(u3, 45u); + /* %u does not match space.*/ + r = tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3); + test_eq(r, 2); + /* %u does not match negative numbers. */ + r = tor_sscanf("12:3:-4", "%2u:%2u:%3u", &u1, &u2, &u3); + test_eq(r, 2); + /* Arbitrary amounts of 0-padding are okay */ + r = tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u", &u1, &u2, &u3); + test_eq(r, 3); + test_eq(u1, 12u); + test_eq(u2, 3u); + test_eq(u3, 99u); + + r = tor_sscanf("99% fresh", "%3u%% fresh", &u1); /* percents are scannable.*/ + test_eq(r, 1); + test_eq(u1, 99); + + r = tor_sscanf("hello", "%s", s1); /* %s needs a number. */ + test_eq(r, -1); + + r = tor_sscanf("hello", "%3s%7s", s1, s2); /* %s matches characters. */ + test_eq(r, 2); + test_streq(s1, "hel"); + test_streq(s2, "lo"); + r = tor_sscanf("WD40", "%2s%u", s3, &u1); /* %s%u */ + test_eq(r, 2); + test_streq(s3, "WD"); + test_eq(u1, 40); + r = tor_sscanf("76trombones", "%6u%9s", &u1, s1); /* %u%s */ + test_eq(r, 2); + test_eq(u1, 76); + test_streq(s1, "trombones"); + r = tor_sscanf("hello world", "%9s %9s", s1, s2); /* %s doesn't eat space. */ + test_eq(r, 2); + test_streq(s1, "hello"); + test_streq(s2, "world"); + r = tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3); /* %s can be empty. */ + test_eq(r, 3); + test_streq(s1, "hi"); + test_streq(s2, ""); + test_streq(s3, ""); + + r = tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch); + test_eq(r, 3); + r = tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch); + test_eq(r, 4); + + done: + ; +} + +/** Run unittests for memory pool allocator */ +static void +test_util_mempool(void) +{ + mp_pool_t *pool = NULL; + smartlist_t *allocated = NULL; + int i; + + pool = mp_pool_new(1, 100); + test_assert(pool); + test_assert(pool->new_chunk_capacity >= 100); + test_assert(pool->item_alloc_size >= sizeof(void*)+1); + mp_pool_destroy(pool); + pool = NULL; + + pool = mp_pool_new(241, 2500); + test_assert(pool); + test_assert(pool->new_chunk_capacity >= 10); + test_assert(pool->item_alloc_size >= sizeof(void*)+241); + test_eq(pool->item_alloc_size & 0x03, 0); + test_assert(pool->new_chunk_capacity < 60); + + allocated = smartlist_create(); + for (i = 0; i < 20000; ++i) { + if (smartlist_len(allocated) < 20 || crypto_rand_int(2)) { + void *m = mp_pool_get(pool); + memset(m, 0x09, 241); + smartlist_add(allocated, m); + //printf("%d: %p\n", i, m); + //mp_pool_assert_ok(pool); + } else { + int idx = crypto_rand_int(smartlist_len(allocated)); + void *m = smartlist_get(allocated, idx); + //printf("%d: free %p\n", i, m); + smartlist_del(allocated, idx); + mp_pool_release(m); + //mp_pool_assert_ok(pool); + } + if (crypto_rand_int(777)==0) + mp_pool_clean(pool, 1, 1); + + if (i % 777) + mp_pool_assert_ok(pool); + } + + done: + if (allocated) { + SMARTLIST_FOREACH(allocated, void *, m, mp_pool_release(m)); + mp_pool_assert_ok(pool); + mp_pool_clean(pool, 0, 0); + mp_pool_assert_ok(pool); + smartlist_free(allocated); + } + + if (pool) + mp_pool_destroy(pool); +} + +/** Run unittests for memory area allocator */ +static void +test_util_memarea(void) +{ + memarea_t *area = memarea_new(); + char *p1, *p2, *p3, *p1_orig; + void *malloced_ptr = NULL; + int i; + + test_assert(area); + + p1_orig = p1 = memarea_alloc(area,64); + p2 = memarea_alloc_zero(area,52); + p3 = memarea_alloc(area,11); + + test_assert(memarea_owns_ptr(area, p1)); + test_assert(memarea_owns_ptr(area, p2)); + test_assert(memarea_owns_ptr(area, p3)); + /* Make sure we left enough space. */ + test_assert(p1+64 <= p2); + test_assert(p2+52 <= p3); + /* Make sure we aligned. */ + test_eq(((uintptr_t)p1) % sizeof(void*), 0); + test_eq(((uintptr_t)p2) % sizeof(void*), 0); + test_eq(((uintptr_t)p3) % sizeof(void*), 0); + test_assert(!memarea_owns_ptr(area, p3+8192)); + test_assert(!memarea_owns_ptr(area, p3+30)); + test_assert(tor_mem_is_zero(p2, 52)); + /* Make sure we don't overalign. */ + p1 = memarea_alloc(area, 1); + p2 = memarea_alloc(area, 1); + test_eq(p1+sizeof(void*), p2); + { + malloced_ptr = tor_malloc(64); + test_assert(!memarea_owns_ptr(area, malloced_ptr)); + tor_free(malloced_ptr); + } + + /* memarea_memdup */ + { + malloced_ptr = tor_malloc(64); + crypto_rand((char*)malloced_ptr, 64); + p1 = memarea_memdup(area, malloced_ptr, 64); + test_assert(p1 != malloced_ptr); + test_memeq(p1, malloced_ptr, 64); + tor_free(malloced_ptr); + } + + /* memarea_strdup. */ + p1 = memarea_strdup(area,""); + p2 = memarea_strdup(area, "abcd"); + test_assert(p1); + test_assert(p2); + test_streq(p1, ""); + test_streq(p2, "abcd"); + + /* memarea_strndup. */ + { + const char *s = "Ad ogni porta batte la morte e grida: il nome!"; + /* (From Turandot, act 3.) */ + size_t len = strlen(s); + p1 = memarea_strndup(area, s, 1000); + p2 = memarea_strndup(area, s, 10); + test_streq(p1, s); + test_assert(p2 >= p1 + len + 1); + test_memeq(s, p2, 10); + test_eq(p2[10], '\0'); + p3 = memarea_strndup(area, s, len); + test_streq(p3, s); + p3 = memarea_strndup(area, s, len-1); + test_memeq(s, p3, len-1); + test_eq(p3[len-1], '\0'); + } + + memarea_clear(area); + p1 = memarea_alloc(area, 1); + test_eq(p1, p1_orig); + memarea_clear(area); + + /* Check for running over an area's size. */ + for (i = 0; i < 512; ++i) { + p1 = memarea_alloc(area, crypto_rand_int(5)+1); + test_assert(memarea_owns_ptr(area, p1)); + } + memarea_assert_ok(area); + /* Make sure we can allocate a too-big object. */ + p1 = memarea_alloc_zero(area, 9000); + p2 = memarea_alloc_zero(area, 16); + test_assert(memarea_owns_ptr(area, p1)); + test_assert(memarea_owns_ptr(area, p2)); + + done: + memarea_drop_all(area); + tor_free(malloced_ptr); +} + +/** Run unit tests for utility functions to get file names relative to + * the data directory. */ +static void +test_util_datadir(void) +{ + char buf[1024]; + char *f = NULL; + char *temp_dir = NULL; + + temp_dir = get_datadir_fname(NULL); + f = get_datadir_fname("state"); + tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir); + test_streq(f, buf); + tor_free(f); + f = get_datadir_fname2("cache", "thingy"); + tor_snprintf(buf, sizeof(buf), + "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir); + test_streq(f, buf); + tor_free(f); + f = get_datadir_fname2_suffix("cache", "thingy", ".foo"); + tor_snprintf(buf, sizeof(buf), + "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir); + test_streq(f, buf); + tor_free(f); + f = get_datadir_fname_suffix("cache", ".foo"); + tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo", + temp_dir); + test_streq(f, buf); + + done: + tor_free(f); + tor_free(temp_dir); +} + +static void +test_util_strtok(void) +{ + char buf[128]; + char buf2[128]; + char *cp1, *cp2; + strlcpy(buf, "Graved on the dark in gestures of descent", sizeof(buf)); + strlcpy(buf2, "they.seemed;their!own;most.perfect;monument", sizeof(buf2)); + /* -- "Year's End", Richard Wilbur */ + + test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1)); + test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2)); +#define S1() tor_strtok_r_impl(NULL, " ", &cp1) +#define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2) + test_streq("on", S1()); + test_streq("the", S1()); + test_streq("dark", S1()); + test_streq("seemed", S2()); + test_streq("their", S2()); + test_streq("own", S2()); + test_streq("in", S1()); + test_streq("gestures", S1()); + test_streq("of", S1()); + test_streq("most", S2()); + test_streq("perfect", S2()); + test_streq("descent", S1()); + test_streq("monument", S2()); + test_assert(NULL == S1()); + test_assert(NULL == S2()); + done: + ; +} + +static void +test_util_find_str_at_start_of_line(void *ptr) +{ + const char *long_string = + "hello world. hello world. hello hello. howdy.\n" + "hello hello world\n"; + + (void)ptr; + + /* not-found case. */ + tt_assert(! find_str_at_start_of_line(long_string, "fred")); + + /* not-found case where haystack doesn't end with \n */ + tt_assert(! find_str_at_start_of_line("foobar\nbaz", "fred")); + + /* start-of-string case */ + tt_assert(long_string == + find_str_at_start_of_line(long_string, "hello world.")); + + /* start-of-line case */ + tt_assert(strchr(long_string,'\n')+1 == + find_str_at_start_of_line(long_string, "hello hello")); + done: + ; +} + +static void +test_util_asprintf(void *ptr) +{ +#define LOREMIPSUM \ + "Lorem ipsum dolor sit amet, consectetur adipisicing elit" + char *cp=NULL, *cp2=NULL; + int r; + (void)ptr; + + /* empty string. */ + r = tor_asprintf(&cp, "%s", ""); + tt_assert(cp); + tt_int_op(r, ==, strlen(cp)); + tt_str_op(cp, ==, ""); + + /* Short string with some printing in it. */ + r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202); + tt_assert(cp2); + tt_int_op(r, ==, strlen(cp2)); + tt_str_op(cp2, ==, "First=101, Second=202"); + tt_assert(cp != cp2); + tor_free(cp); + tor_free(cp2); + + /* Glass-box test: a string exactly 128 characters long. */ + r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM); + tt_assert(cp); + tt_int_op(r, ==, 128); + tt_assert(cp[128] == '\0'); + tt_str_op(cp, ==, + "Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM); + tor_free(cp); + + /* String longer than 128 characters */ + r = tor_asprintf(&cp, "1: %s 2: %s 3: %s", + LOREMIPSUM, LOREMIPSUM, LOREMIPSUM); + tt_assert(cp); + tt_int_op(r, ==, strlen(cp)); + tt_str_op(cp, ==, "1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM); + + done: + tor_free(cp); + tor_free(cp2); +} + +static void +test_util_listdir(void *ptr) +{ + smartlist_t *dir_contents = NULL; + char *fname1=NULL, *fname2=NULL, *dirname=NULL; + (void)ptr; + + fname1 = tor_strdup(get_fname("hopscotch")); + fname2 = tor_strdup(get_fname("mumblety-peg")); + dirname = tor_strdup(get_fname(NULL)); + + tt_int_op(write_str_to_file(fname1, "X\n", 0), ==, 0); + tt_int_op(write_str_to_file(fname2, "Y\n", 0), ==, 0); + + dir_contents = tor_listdir(dirname); + tt_assert(dir_contents); + /* make sure that each filename is listed. */ + tt_assert(smartlist_string_isin_case(dir_contents, "hopscotch")); + tt_assert(smartlist_string_isin_case(dir_contents, "mumblety-peg")); + + tt_assert(!smartlist_string_isin(dir_contents, ".")); + tt_assert(!smartlist_string_isin(dir_contents, "..")); + + done: + tor_free(fname1); + tor_free(fname2); + tor_free(dirname); + if (dir_contents) { + SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp)); + smartlist_free(dir_contents); + } +} + +#ifdef MS_WINDOWS +static void +test_util_load_win_lib(void *ptr) +{ + HANDLE h = load_windows_system_library("advapi32.dll"); + + tt_assert(h); + done: + if (h) + CloseHandle(h); +} +#endif + +#define UTIL_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name } + +#define UTIL_TEST(name, flags) \ + { #name, test_util_ ## name, flags, NULL, NULL } + +struct testcase_t util_tests[] = { + UTIL_LEGACY(time), + UTIL_LEGACY(config_line), + UTIL_LEGACY(strmisc), + UTIL_LEGACY(pow2), + UTIL_LEGACY(gzip), + UTIL_LEGACY(datadir), + UTIL_LEGACY(mempool), + UTIL_LEGACY(memarea), + UTIL_LEGACY(control_formats), + UTIL_LEGACY(mmap), + UTIL_LEGACY(threads), + UTIL_LEGACY(sscanf), + UTIL_LEGACY(strtok), + UTIL_TEST(find_str_at_start_of_line, 0), + UTIL_TEST(asprintf, 0), + UTIL_TEST(listdir, 0), +#ifdef MS_WINDOWS + UTIL_TEST(load_win_lib, 0), +#endif + END_OF_TESTCASES +}; + diff --git a/src/test/tinytest.c b/src/test/tinytest.c new file mode 100644 index 0000000000..11ffc2fe56 --- /dev/null +++ b/src/test/tinytest.c @@ -0,0 +1,380 @@ +/* tinytest.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 + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#ifdef WIN32 +#include <windows.h> +#else +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#endif + +#ifndef __GNUC__ +#define __attribute__(x) +#endif + +#ifdef TINYTEST_LOCAL +#include "tinytest_local.h" +#endif +#include "tinytest.h" +#include "tinytest_macros.h" + +#define LONGEST_TEST_NAME 16384 + +static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ +static int n_ok = 0; /**< Number of tests that have passed */ +static int n_bad = 0; /**< Number of tests that have failed. */ +static int n_skipped = 0; /**< Number of tests that have been skipped. */ + +static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ +static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ +static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ +const char *verbosity_flag = ""; + +enum outcome { SKIP=2, OK=1, FAIL=0 }; +static enum outcome cur_test_outcome = 0; +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 +/** Pointer to argv[0] for win32. */ +static const char *commandname = NULL; +#endif + +static void usage(struct testgroup_t *groups, int list_groups) + __attribute__((noreturn)); + +static enum outcome +_testcase_run_bare(const struct testcase_t *testcase) +{ + void *env = NULL; + int outcome; + if (testcase->setup) { + env = testcase->setup->setup_fn(testcase); + if (!env) + return FAIL; + else if (env == (void*)TT_SKIP) + return SKIP; + } + + cur_test_outcome = OK; + testcase->fn(env); + outcome = cur_test_outcome; + + if (testcase->setup) { + if (testcase->setup->cleanup_fn(testcase, env) == 0) + outcome = FAIL; + } + + return outcome; +} + +#define MAGIC_EXITCODE 42 + +static enum outcome +_testcase_run_forked(const struct testgroup_t *group, + const struct testcase_t *testcase) +{ +#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 + want, and this time without forking. + + (No, threads aren't an option. The whole point of forking is to + share no state between tests.) + */ + int ok; + char buffer[LONGEST_TEST_NAME+256]; + STARTUPINFOA si; + PROCESS_INFORMATION info; + DWORD exitcode; + + if (!in_tinytest_main) { + printf("\nERROR. On Windows, _testcase_run_forked must be" + " called from within tinytest_main.\n"); + abort(); + } + if (opt_verbosity>0) + printf("[forking] "); + + snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", + commandname, verbosity_flag, group->prefix, testcase->name); + + memset(&si, 0, sizeof(si)); + memset(&info, 0, sizeof(info)); + si.cb = sizeof(si); + + ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, + 0, NULL, NULL, &si, &info); + if (!ok) { + printf("CreateProcess failed!\n"); + return 0; + } + WaitForSingleObject(info.hProcess, INFINITE); + GetExitCodeProcess(info.hProcess, &exitcode); + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + if (exitcode == 0) + return OK; + else if (exitcode == MAGIC_EXITCODE) + return SKIP; + else + return FAIL; +#else + int outcome_pipe[2]; + pid_t pid; + (void)group; + + if (pipe(outcome_pipe)) + perror("opening pipe"); + + if (opt_verbosity>0) + printf("[forking] "); + pid = fork(); + if (!pid) { + /* child. */ + int test_r, write_r; + char b[1]; + close(outcome_pipe[0]); + test_r = _testcase_run_bare(testcase); + assert(0<=(int)test_r && (int)test_r<=2); + b[0] = "NYS"[test_r]; + write_r = (int)write(outcome_pipe[1], b, 1); + if (write_r != 1) { + perror("write outcome to pipe"); + exit(1); + } + exit(0); + } else { + /* parent */ + int status, r; + char b[1]; + /* Close this now, so that if the other side closes it, + * our read fails. */ + close(outcome_pipe[1]); + r = (int)read(outcome_pipe[0], b, 1); + if (r == 0) { + printf("[Lost connection!] "); + return 0; + } else if (r != 1) { + perror("read outcome from pipe"); + } + waitpid(pid, &status, 0); + close(outcome_pipe[0]); + return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL); + } +#endif +} + +int +testcase_run_one(const struct testgroup_t *group, + const struct testcase_t *testcase) +{ + enum outcome outcome; + + if (testcase->flags & TT_SKIP) { + if (opt_verbosity>0) + printf("%s%s: SKIPPED\n", + group->prefix, testcase->name); + ++n_skipped; + return SKIP; + } + + if (opt_verbosity>0 && !opt_forked) { + printf("%s%s: ", group->prefix, testcase->name); + } else { + if (opt_verbosity==0) printf("."); + cur_test_prefix = group->prefix; + cur_test_name = testcase->name; + } + + if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) { + outcome = _testcase_run_forked(group, testcase); + } else { + outcome = _testcase_run_bare(testcase); + } + + if (outcome == OK) { + ++n_ok; + if (opt_verbosity>0 && !opt_forked) + puts(opt_verbosity==1?"OK":""); + } else if (outcome == SKIP) { + ++n_skipped; + if (opt_verbosity>0 && !opt_forked) + puts("SKIPPED"); + } else { + ++n_bad; + if (!opt_forked) + printf("\n [%s FAILED]\n", testcase->name); + } + + if (opt_forked) { + exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1)); + } else { + return (int)outcome; + } +} + +int +_tinytest_set_flag(struct testgroup_t *groups, const char *arg, unsigned long flag) +{ + int i, j; + size_t length = LONGEST_TEST_NAME; + char fullname[LONGEST_TEST_NAME]; + int found=0; + if (strstr(arg, "..")) + length = strstr(arg,"..")-arg; + for (i=0; groups[i].prefix; ++i) { + for (j=0; groups[i].cases[j].name; ++j) { + snprintf(fullname, sizeof(fullname), "%s%s", + groups[i].prefix, groups[i].cases[j].name); + if (!flag) /* Hack! */ + printf(" %s\n", fullname); + if (!strncmp(fullname, arg, length)) { + groups[i].cases[j].flags |= flag; + ++found; + } + } + } + return found; +} + +static void +usage(struct testgroup_t *groups, int list_groups) +{ + puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); + puts(" Specify tests by name, or using a prefix ending with '..'"); + puts(" To skip a test, list give its name prefixed with a colon."); + puts(" Use --list-tests for a list of tests."); + if (list_groups) { + puts("Known tests are:"); + _tinytest_set_flag(groups, "..", 0); + } + exit(0); +} + +int +tinytest_main(int c, const char **v, struct testgroup_t *groups) +{ + int i, j, n=0; + +#ifdef WIN32 + commandname = v[0]; +#endif + for (i=1; i<c; ++i) { + if (v[i][0] == '-') { + if (!strcmp(v[i], "--RUNNING-FORKED")) { + opt_forked = 1; + } else if (!strcmp(v[i], "--no-fork")) { + opt_nofork = 1; + } else if (!strcmp(v[i], "--quiet")) { + opt_verbosity = -1; + verbosity_flag = "--quiet"; + } else if (!strcmp(v[i], "--verbose")) { + opt_verbosity = 2; + verbosity_flag = "--verbose"; + } else if (!strcmp(v[i], "--terse")) { + opt_verbosity = 0; + verbosity_flag = "--terse"; + } else if (!strcmp(v[i], "--help")) { + usage(groups, 0); + } else if (!strcmp(v[i], "--list-tests")) { + usage(groups, 1); + } else { + printf("Unknown option %s. Try --help\n",v[i]); + return -1; + } + } else { + const char *test = v[i]; + int flag = _TT_ENABLED; + if (test[0] == ':') { + ++test; + flag = TT_SKIP; + } else { + ++n; + } + if (!_tinytest_set_flag(groups, test, flag)) { + printf("No such test as %s!\n", v[i]); + return -1; + } + } + } + if (!n) + _tinytest_set_flag(groups, "..", _TT_ENABLED); + + setvbuf(stdout, NULL, _IONBF, 0); + + ++in_tinytest_main; + for (i=0; groups[i].prefix; ++i) + for (j=0; groups[i].cases[j].name; ++j) + if (groups[i].cases[j].flags & _TT_ENABLED) + testcase_run_one(&groups[i], + &groups[i].cases[j]); + + --in_tinytest_main; + + if (opt_verbosity==0) + puts(""); + + if (n_bad) + printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad, + n_bad+n_ok,n_skipped); + else if (opt_verbosity >= 1) + printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped); + + return (n_bad == 0) ? 0 : 1; +} + +int +_tinytest_get_verbosity(void) +{ + return opt_verbosity; +} + +void +_tinytest_set_test_failed(void) +{ + if (opt_verbosity <= 0 && cur_test_name) { + if (opt_verbosity==0) puts(""); + printf("%s%s: ", cur_test_prefix, cur_test_name); + cur_test_name = NULL; + } + cur_test_outcome = 0; +} + +void +_tinytest_set_test_skipped(void) +{ + if (cur_test_outcome==OK) + cur_test_outcome = SKIP; +} + diff --git a/src/test/tinytest.h b/src/test/tinytest.h new file mode 100644 index 0000000000..cbe28b7f51 --- /dev/null +++ b/src/test/tinytest.h @@ -0,0 +1,87 @@ +/* tinytest.h -- Copyright 2009-2010 Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _TINYTEST_H +#define _TINYTEST_H + +/** Flag for a test that needs to run in a subprocess. */ +#define TT_FORK (1<<0) +/** Runtime flag for a test we've decided to skip. */ +#define TT_SKIP (1<<1) +/** Internal runtime flag for a test we've decided to run. */ +#define _TT_ENABLED (1<<2) +/** If you add your own flags, make them start at this point. */ +#define TT_FIRST_USER_FLAG (1<<3) + +typedef void (*testcase_fn)(void *); + +struct testcase_t; + +/** Functions to initialize/teardown a structure for a testcase. */ +struct testcase_setup_t { + /** Return a new structure for use by a given testcase. */ + void *(*setup_fn)(const struct testcase_t *); + /** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */ + int (*cleanup_fn)(const struct testcase_t *, void *); +}; + +/** A single test-case that you can run. */ +struct testcase_t { + const char *name; /**< An identifier for this case. */ + testcase_fn fn; /**< The function to run to implement this case. */ + unsigned long flags; /**< Bitfield of TT_* flags. */ + const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/ + void *setup_data; /**< Extra data usable by setup function */ +}; +#define END_OF_TESTCASES { NULL, NULL, 0, NULL, NULL } + +/** A group of tests that are selectable together. */ +struct testgroup_t { + const char *prefix; /**< Prefix to prepend to testnames. */ + struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */ +}; +#define END_OF_GROUPS { NULL, NULL} + +/** Implementation: called from a test to indicate failure, before logging. */ +void _tinytest_set_test_failed(void); +/** Implementation: called from a test to indicate that we're skipping. */ +void _tinytest_set_test_skipped(void); +/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */ +int _tinytest_get_verbosity(void); +/** Implementation: Set a flag on tests matching a name; returns number + * of tests that matched. */ +int _tinytest_set_flag(struct testgroup_t *, const char *, unsigned long); + +/** Set all tests in 'groups' matching the name 'named' to be skipped. */ +#define tinytest_skip(groups, named) \ + _tinytest_set_flag(groups, named, TT_SKIP) + +/** Run a single testcase in a single group. */ +int testcase_run_one(const struct testgroup_t *,const struct testcase_t *); +/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups, + as selected from the command line. */ +int tinytest_main(int argc, const char **argv, struct testgroup_t *groups); + +#endif diff --git a/src/test/tinytest_demo.c b/src/test/tinytest_demo.c new file mode 100644 index 0000000000..bd33cc37fa --- /dev/null +++ b/src/test/tinytest_demo.c @@ -0,0 +1,215 @@ +/* tinytest_demo.c -- Copyright 2009 Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + + +/* Welcome to the example file for tinytest! I'll show you how to set up + * some simple and not-so-simple testcases. */ + +/* Make sure you include these headers. */ +#include "tinytest.h" +#include "tinytest_macros.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +/* ============================================================ */ + +/* First, let's see if strcmp is working. (All your test cases should be + * functions declared to take a single void * as) an argument. */ +void +test_strcmp(void *data) +{ + (void)data; /* This testcase takes no data. */ + + /* Let's make sure the empty string is equal to itself */ + if (strcmp("","")) { + /* This macro tells tinytest to stop the current test + * and go straight to the "end" label. */ + tt_abort_msg("The empty string was not equal to itself"); + } + + /* Pretty often, calling tt_abort_msg to indicate failure is more + 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 + because a single assertion has failed. In that case, use + tt_want: */ + tt_want(strcmp("tinytest", "testcase") > 0); + + /* You can use the tt_*_op family of macros to compare values and to + fail unless they have the relationship you want. They produce + more useful output than tt_assert, since they display the actual + values of the failing things. + + Fail unless strcmp("abc, "abc") == 0 */ + tt_int_op(strcmp("abc", "abc"), ==, 0); + + /* Fail unless strcmp("abc, "abcd") is less than 0 */ + tt_int_op(strcmp("abc", "abcd"), < , 0); + + /* Incidentally, there's a test_str_op that uses strcmp internally. */ + tt_str_op("abc", <, "abcd"); + + + /* Every test-case function needs to finish with an "end:" + label and (optionally) code to clean up local variables. */ + end: + ; +} + +/* ============================================================ */ + +/* Now let's mess with setup and teardown functions! These are handy if + you have a bunch of tests that all need a similar environment, and you + want to reconstruct that environment freshly for each one. */ + +/* 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 + setup/teardown functions is probably overkill for this case. + + You could also do file descriptors, complicated handles, temporary + files, etc. */ + char buffer1[512]; + char buffer2[512]; +}; +/* The setup function needs to take a const struct testcase_t and return + void* */ +void * +setup_data_buffer(const struct testcase_t *testcase) +{ + struct data_buffer *db = malloc(sizeof(struct data_buffer)); + + /* If you had a complicated set of setup rules, you might behave + differently here depending on testcase->flags or + testcase->setup_data or even or testcase->name. */ + + /* Returning a NULL here would mean that we couldn't set up for this + test, so we don't need to test db for null. */ + return db; +} +/* The clean function deallocates storage carefully and returns true on + success. */ +int +clean_data_buffer(const struct testcase_t *testcase, void *ptr) +{ + struct data_buffer *db = ptr; + + if (db) { + free(db); + return 1; + } + return 0; +} +/* Finally, declare a testcase_setup_t with these functions. */ +struct testcase_setup_t data_buffer_setup = { + setup_data_buffer, clean_data_buffer +}; + + +/* Now let's write our test. */ +void +test_memcpy(void *ptr) +{ + /* This time, we use the argument. */ + struct data_buffer *db = ptr; + + /* We'll also introduce a local variable that might need cleaning up. */ + char *mem = NULL; + + /* Let's make sure that memcpy does what we'd like. */ + strcpy(db->buffer1, "String 0"); + memcpy(db->buffer2, db->buffer1, sizeof(db->buffer1)); + tt_str_op(db->buffer1, ==, db->buffer2); + + /* Now we've allocated memory that's referenced by a local variable. + The end block of the function will clean it up. */ + mem = strdup("Hello world."); + tt_assert(mem); + + /* Another rather trivial test. */ + tt_str_op(db->buffer1, !=, mem); + + end: + /* This time our end block has something to do. */ + if (mem) + free(mem); +} + +/* ============================================================ */ + +/* 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. +*/ + +struct testcase_t demo_tests[] = { + /* Here's a really simple test: it has a name you can refer to it + with, and a function to invoke it. */ + { "strcmp", test_strcmp, }, + + /* The second test has a flag, "TT_FORK", to make it run in a + subprocess, and a pointer to the testcase_setup_t that configures + its environment. */ + { "memcpy", test_memcpy, TT_FORK, &data_buffer_setup }, + + /* The array has to end with END_OF_TESTCASES. */ + END_OF_TESTCASES +}; + +/* Next, we make an array of testgroups. This is mandatory. Unlike more + heavy-duty testing frameworks, groups can't nest. */ +struct testgroup_t groups[] = { + + /* Every group has a 'prefix', and an array of tests. That's it. */ + { "demo/", demo_tests }, + + 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 + specific tests: + + tinytest-demo demo/memcpy + + or use a ..-wildcard to select multiple tests with a common + prefix: + + tinytest-demo demo/.. + + If you list no tests, you get them all by default, so that + "tinytest-demo" and "tinytest-demo .." mean the same thing. + + */ + return tinytest_main(c, v, groups); +} diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h new file mode 100644 index 0000000000..a7fa64a824 --- /dev/null +++ b/src/test/tinytest_macros.h @@ -0,0 +1,167 @@ +/* tinytest_macros.h -- Copyright 2009-2010 Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _TINYTEST_MACROS_H +#define _TINYTEST_MACROS_H + +/* Helpers for defining statement-like macros */ +#define TT_STMT_BEGIN do { +#define TT_STMT_END } while (0) + +/* Redefine this if your test functions want to abort with something besides + * "goto end;" */ +#ifndef TT_EXIT_TEST_FUNCTION +#define TT_EXIT_TEST_FUNCTION TT_STMT_BEGIN goto end; TT_STMT_END +#endif + +/* Redefine this if you want to note success/failure in some different way. */ +#ifndef TT_DECLARE +#define TT_DECLARE(prefix, args) \ + TT_STMT_BEGIN \ + printf("\n %s %s:%d: ",prefix,__FILE__,__LINE__); \ + printf args ; \ + TT_STMT_END +#endif + +/* Announce a failure. Args are parenthesized printf args. */ +#define TT_GRIPE(args) TT_DECLARE("FAIL", args) + +/* Announce a non-failure if we're verbose. */ +#define TT_BLATHER(args) \ + TT_STMT_BEGIN \ + if (_tinytest_get_verbosity()>1) TT_DECLARE(" OK", args); \ + TT_STMT_END + +#define TT_DIE(args) \ + TT_STMT_BEGIN \ + _tinytest_set_test_failed(); \ + TT_GRIPE(args); \ + TT_EXIT_TEST_FUNCTION; \ + TT_STMT_END + +#define TT_FAIL(args) \ + TT_STMT_BEGIN \ + _tinytest_set_test_failed(); \ + TT_GRIPE(args); \ + TT_STMT_END + +/* Fail and abort the current test for the reason in msg */ +#define tt_abort_printf(msg) TT_DIE(msg) +#define tt_abort_perror(op) TT_DIE(("%s: %s [%d]",(op),strerror(errno), errno)) +#define tt_abort_msg(msg) TT_DIE(("%s", msg)) +#define tt_abort() TT_DIE(("%s", "(Failed.)")) + +/* Fail but do not abort the current test for the reason in msg. */ +#define tt_fail_printf(msg) TT_FAIL(msg) +#define tt_fail_perror(op) TT_FAIL(("%s: %s [%d]",(op),strerror(errno), errno)) +#define tt_fail_msg(msg) TT_FAIL(("%s", msg)) +#define tt_fail() TT_FAIL(("%s", "(Failed.)")) + +/* End the current test, and indicate we are skipping it. */ +#define tt_skip() \ + TT_STMT_BEGIN \ + _tinytest_set_test_skipped(); \ + TT_EXIT_TEST_FUNCTION; \ + TT_STMT_END + +#define _tt_want(b, msg, fail) \ + TT_STMT_BEGIN \ + if (!(b)) { \ + _tinytest_set_test_failed(); \ + TT_GRIPE((msg)); \ + fail; \ + } else { \ + TT_BLATHER((msg)); \ + } \ + TT_STMT_END + +/* Assert b, but do not stop the test if b fails. Log msg on failure. */ +#define tt_want_msg(b, msg) \ + _tt_want(b, msg, ); + +/* Assert b and stop the test if b fails. Log msg on failure. */ +#define tt_assert_msg(b, msg) \ + _tt_want(b, msg, TT_EXIT_TEST_FUNCTION); + +/* Assert b, but do not stop the test if b fails. */ +#define tt_want(b) tt_want_msg( (b), "want("#b")") +/* Assert b, and stop the test if b fails. */ +#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) \ + TT_STMT_BEGIN \ + type _val1 = (type)(a); \ + type _val2 = (type)(b); \ + int _tt_status = (test); \ + if (!_tt_status || _tinytest_get_verbosity()>1) { \ + printf_type _print; \ + printf_type _print1; \ + printf_type _print2; \ + type _value = _val1; \ + setup_block; \ + _print1 = _print; \ + _value = _val2; \ + setup_block; \ + _print2 = _print; \ + TT_DECLARE(_tt_status?" OK":"FAIL", \ + ("assert(%s): "printf_fmt" vs "printf_fmt, \ + str_test, _print1, _print2)); \ + _print = _print1; \ + cleanup_block; \ + _print = _print2; \ + cleanup_block; \ + if (!_tt_status) { \ + _tinytest_set_test_failed(); \ + TT_EXIT_TEST_FUNCTION; \ + } \ + } \ + TT_STMT_END + +#define tt_assert_test_type(a,b,str_test,type,test,fmt) \ + tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \ + {_print=_value;},{}) + +/* 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) + +#define tt_int_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld") + +#define tt_uint_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ + (_val1 op _val2),"%lu") + +#define tt_ptr_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ + (_val1 op _val2),"%p") + +#define tt_str_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ + (strcmp(_val1,_val2) op 0),"<%s>") + +#endif diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 41786e4378..1bb5076849 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -3,16 +3,16 @@ noinst_PROGRAMS = tor-checkkey tor_resolve_SOURCES = tor-resolve.c tor_resolve_LDFLAGS = @TOR_LDFLAGS_libevent@ -tor_resolve_LDADD = ../common/libor.a @TOR_LIBEVENT_LIBS@ @TOR_LIB_WS32@ +tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIBEVENT_LIBS@ @TOR_LIB_WS32@ tor_gencert_SOURCES = tor-gencert.c tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ tor_gencert_LDADD = ../common/libor.a ../common/libor-crypto.a \ - -lz @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ + -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_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_LDADD = ../common/libor.a ../common/libor-crypto.a \ - -lz @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ + -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ diff --git a/src/tools/tor-checkkey.c b/src/tools/tor-checkkey.c index b29b52d8db..94c8cbd44c 100644 --- a/src/tools/tor-checkkey.c +++ b/src/tools/tor-checkkey.c @@ -6,19 +6,21 @@ #include <stdio.h> #include <stdlib.h> #include "crypto.h" -#include "log.h" -#include "util.h" +#include "torlog.h" +#include "../common/util.h" #include "compat.h" #include <openssl/bn.h> #include <openssl/rsa.h> -int main(int c, char **v) +int +main(int c, char **v) { crypto_pk_env_t *env; char *str; RSA *rsa; int wantdigest=0; int fname_idx; + char *fname=NULL; init_logging(); if (c < 2) { @@ -29,7 +31,7 @@ int main(int c, char **v) return 1; } - if (crypto_global_init(0)) { + if (crypto_global_init(0, NULL, NULL)) { fprintf(stderr, "Couldn't initialize crypto library.\n"); return 1; } @@ -46,7 +48,9 @@ int main(int c, char **v) fname_idx = 1; } - str = read_file_to_str(v[fname_idx], 0, NULL); + fname = expand_filename(v[fname_idx]); + str = read_file_to_str(fname, 0, NULL); + tor_free(fname); if (!str) { fprintf(stderr, "Couldn't read %s\n", v[fname_idx]); return 1; diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c index 3f449dc66e..bc99c24bd7 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -13,6 +13,7 @@ #include <openssl/evp.h> #include <openssl/pem.h> +#include <openssl/rsa.h> #include <openssl/objects.h> #include <openssl/obj_mac.h> #include <openssl/err.h> @@ -27,8 +28,8 @@ #define CRYPTO_PRIVATE #include "compat.h" -#include "util.h" -#include "log.h" +#include "../common/util.h" +#include "../common/torlog.h" #include "crypto.h" #include "address.h" @@ -63,7 +64,6 @@ show_help(void) "[-c certificate_file]\n" " [-m lifetime_in_months] [-a address:port] " "[--passphrase-fd <fd>]\n"); - } /* XXXX copied from crypto.c */ @@ -218,6 +218,20 @@ parse_commandline(int argc, char **argv) return 0; } +static RSA * +generate_key(int bits) +{ + RSA *rsa = NULL; + crypto_pk_env_t *env = crypto_new_pk_env(); + if (crypto_pk_generate_key_with_bits(env,bits)<0) + goto done; + rsa = _crypto_pk_env_get_rsa(env); + rsa = RSAPrivateKey_dup(rsa); + done: + crypto_free_pk_env(env); + return rsa; +} + /** Try to read the identity key from <b>identity_key_file</b>. If no such * file exists and create_identity_key is set, make a new identity key and * store it. Return 0 on success, nonzero on failure. @@ -238,7 +252,7 @@ load_identity_key(void) } log_notice(LD_GENERAL, "Generating %d-bit RSA identity key.", IDENTITY_KEY_BITS); - if (!(key = RSA_generate_key(IDENTITY_KEY_BITS, 65537, NULL, NULL))) { + if (!(key = generate_key(IDENTITY_KEY_BITS))) { log_err(LD_GENERAL, "Couldn't generate identity key."); crypto_log_errors(LOG_ERR, "Generating identity key"); return 1; @@ -323,7 +337,7 @@ generate_signing_key(void) RSA *key; log_notice(LD_GENERAL, "Generating %d-bit RSA signing key.", SIGNING_KEY_BITS); - if (!(key = RSA_generate_key(SIGNING_KEY_BITS, 65537, NULL, NULL))) { + if (!(key = generate_key(SIGNING_KEY_BITS))) { log_err(LD_GENERAL, "Couldn't generate signing key."); crypto_log_errors(LOG_ERR, "Generating signing key"); return 1; @@ -393,7 +407,6 @@ get_fingerprint(EVP_PKEY *pkey, char *out) return r; } - /** Set <b>out</b> to the hex-encoded fingerprint of <b>pkey</b>. */ static int get_digest(EVP_PKEY *pkey, char *out) @@ -487,7 +500,6 @@ generate_certificate(void) return 0; } - /** Entry point to tor-gencert */ int main(int argc, char **argv) @@ -496,7 +508,7 @@ main(int argc, char **argv) init_logging(); /* Don't bother using acceleration. */ - if (crypto_global_init(0)) { + if (crypto_global_init(0, NULL, NULL)) { fprintf(stderr, "Couldn't initialize crypto library.\n"); return 1; } diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c index 24c8a6406a..f5b0becaff 100644 --- a/src/tools/tor-resolve.c +++ b/src/tools/tor-resolve.c @@ -6,9 +6,9 @@ #include "orconfig.h" #include "compat.h" -#include "util.h" +#include "../common/util.h" #include "address.h" -#include "log.h" +#include "../common/torlog.h" #include <stdio.h> #include <stdlib.h> @@ -148,7 +148,7 @@ parse_socks4a_resolve_response(const char *hostname, static const char * socks5_reason_to_string(char reason) { - switch(reason) { + switch (reason) { case SOCKS5_SUCCEEDED: return "succeeded"; case SOCKS5_GENERAL_ERROR: @@ -251,7 +251,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, } if (parse_socks4a_resolve_response(hostname, reply_buf, RESPONSE_LEN_4, - result_addr)<0){ + result_addr)<0) { return -1; } } else { diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index 65804fe19d..b3cd1db50b 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -88,11 +88,18 @@ #define HAVE_STRING_H /* Define to 1 if you have the `strlcat' function. */ +#if defined (WINCE) +#define HAVE_STRLCAT +#else #undef HAVE_STRLCAT +#endif /* Define to 1 if you have the `strlcpy' function. */ +#if defined (WINCE) +#define HAVE_STRLCPY +#else #undef HAVE_STRLCPY - +#endif /* Define to 1 if you have the `strptime' function. */ #undef HAVE_STRPTIME @@ -226,6 +233,5 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.1.25" - +#define VERSION "0.2.2.19-alpha" |