diff options
Diffstat (limited to 'src')
213 files changed, 64804 insertions, 18956 deletions
diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index fa2dd560a6..0000000000 --- a/src/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ - -# leave in dependency order, since common must be built first -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 deleted file mode 100644 index 5e7684259a..0000000000 --- a/src/common/Makefile.am +++ /dev/null @@ -1,67 +0,0 @@ - -noinst_LIBRARIES = libor.a libor-crypto.a libor-event.a - -EXTRA_DIST = common_sha1.i sha256.c Makefile.nmake - -#CFLAGS = -Wall -Wpointer-arith -O2 - -if USE_OPENBSD_MALLOC -libor_extra_source=OpenBSD_malloc_Linux.c -else -libor_extra_source= -endif - -libor_a_SOURCES = \ - address.c \ - compat.c \ - container.c \ - di_ops.c \ - log.c \ - memarea.c \ - mempool.c \ - procmon.c \ - util.c \ - util_codedigest.c \ - $(libor_extra_source) - -libor_crypto_a_SOURCES = \ - aes.c \ - crypto.c \ - torgzip.c \ - tortls.c - -libor_event_a_SOURCES = compat_libevent.c - -noinst_HEADERS = \ - address.h \ - aes.h \ - ciphers.inc \ - compat.h \ - compat_libevent.h \ - container.h \ - crypto.h \ - di_ops.h \ - ht.h \ - memarea.h \ - mempool.h \ - procmon.h \ - strlcat.c \ - strlcpy.c \ - torgzip.h \ - torint.h \ - torlog.h \ - tortls.h \ - util.h - -common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) - if test "@SHA1SUM@" != none; then \ - (cd "$(srcdir)" && "@SHA1SUM@" $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | "@SED@" -n 's/^\(.*\)$$/"\1\\n"/p' > common_sha1.i; \ - elif test "@OPENSSL@" != none; then \ - (cd "$(srcdir)" && "@OPENSSL@" sha1 $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | "@SED@" -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > common_sha1.i; \ - else \ - rm common_sha1.i; \ - touch common_sha1.i; \ - fi - -util_codedigest.o: common_sha1.i -crypto.o: sha256.c diff --git a/src/common/Makefile.nmake b/src/common/Makefile.nmake index e548273670..0ebeaaaf71 100644 --- a/src/common/Makefile.nmake +++ b/src/common/Makefile.nmake @@ -1,15 +1,19 @@ all: libor.lib libor-crypto.lib libor-event.lib -CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include +CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\ext LIBOR_OBJECTS = address.obj compat.obj container.obj di_ops.obj \ log.obj memarea.obj mempool.obj procmon.obj util.obj \ util_codedigest.obj -LIBOR_CRYPTO_OBJECTS = aes.obj crypto.obj torgzip.obj tortls.obj +LIBOR_CRYPTO_OBJECTS = aes.obj crypto.obj torgzip.obj tortls.obj \ + crypto_curve25519.obj curve25519-donna.obj LIBOR_EVENT_OBJECTS = compat_libevent.obj +curve25519-donna.obj: ..\ext\curve25519_donna\curve25519-donna.c + $(CC) $(CFLAGS) /D inline=_inline /c ..\ext\curve25519_donna\curve25519-donna.c + libor.lib: $(LIBOR_OBJECTS) lib $(LIBOR_OBJECTS) /out:libor.lib @@ -18,3 +22,6 @@ libor-crypto.lib: $(LIBOR_CRYPTO_OBJECTS) libor-event.lib: $(LIBOR_EVENT_OBJECTS) lib $(LIBOR_EVENT_OBJECTS) /out:libor-event.lib + +clean: + del *.obj *.lib libor*.lib diff --git a/src/common/address.c b/src/common/address.c index df26f61f8f..14a7b6bc96 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -181,6 +181,16 @@ tor_addr_make_unspec(tor_addr_t *a) a->family = AF_UNSPEC; } +/** Set address <a>a</b> to the null address in address family <b>family</b>. + * The null address for AF_INET is 0.0.0.0. The null address for AF_INET6 is + * [::]. AF_UNSPEC is all null. */ +void +tor_addr_make_null(tor_addr_t *a, sa_family_t family) +{ + memset(a, 0, sizeof(*a)); + a->family = family; +} + /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set * *<b>addr</b> to the proper IP address and family. The <b>family</b> * argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a @@ -305,7 +315,8 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) * also treated as internal for now.) */ int -tor_addr_is_internal(const tor_addr_t *addr, int for_listening) +tor_addr_is_internal_(const tor_addr_t *addr, int for_listening, + const char *filename, int lineno) { uint32_t iph4 = 0; uint32_t iph6[4]; @@ -355,8 +366,8 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening) /* unknown address family... assume it's not safe for external use */ /* rather than tor_assert(0) */ - log_warn(LD_BUG, "tor_addr_is_internal() called with a non-IP address of " - "type %d", (int)v_family); + log_warn(LD_BUG, "tor_addr_is_internal() called from %s:%d with a " + "non-IP address of type %d", filename, lineno, (int)v_family); tor_fragile_assert(); return 1; } @@ -558,9 +569,22 @@ tor_addr_to_PTR_name(char *out, size_t outlen, * * Return an address family on success, or -1 if an invalid address string is * provided. + * + * If 'flags & TAPMP_EXTENDED_STAR' is false, then the wildcard address '*' + * yield an IPv4 wildcard. + * + * If 'flags & TAPMP_EXTENDED_STAR' is true, then the wildcard address '*' + * yields an AF_UNSPEC wildcard address, and the following change is made + * in the grammar above: + * Address ::= IPv4Address / "[" IPv6Address "]" / "*" / "*4" / "*6" + * with the new "*4" and "*6" productions creating a wildcard to match + * IPv4 or IPv6 addresses. + * */ int -tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out, +tor_addr_parse_mask_ports(const char *s, + unsigned flags, + tor_addr_t *addr_out, maskbits_t *maskbits_out, uint16_t *port_min_out, uint16_t *port_max_out) { @@ -617,9 +641,23 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out, memset(addr_out, 0, sizeof(tor_addr_t)); if (!strcmp(address, "*")) { - family = AF_INET; /* AF_UNSPEC ???? XXXX_IP6 */ + if (flags & TAPMP_EXTENDED_STAR) { + family = AF_UNSPEC; + tor_addr_make_unspec(addr_out); + } else { + family = AF_INET; + tor_addr_from_ipv4h(addr_out, 0); + } + any_flag = 1; + } else if (!strcmp(address, "*4") && (flags & TAPMP_EXTENDED_STAR)) { + family = AF_INET; tor_addr_from_ipv4h(addr_out, 0); any_flag = 1; + } else if (!strcmp(address, "*6") && (flags & TAPMP_EXTENDED_STAR)) { + static char nil_bytes[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; + family = AF_INET6; + tor_addr_from_ipv6_bytes(addr_out, nil_bytes); + any_flag = 1; } else if (tor_inet_pton(AF_INET6, address, &in6_tmp) > 0) { family = AF_INET6; tor_addr_from_in6(addr_out, &in6_tmp); @@ -1007,6 +1045,19 @@ fmt_addr_impl(const tor_addr_t *addr, int decorate) return "???"; } +/** Return a string representing the pair <b>addr</b> and <b>port</b>. + * This calls fmt_and_decorate_addr internally, so IPv6 addresses will + * have brackets, and the caveats of fmt_addr_impl apply. + */ +const char * +fmt_addrport(const tor_addr_t *addr, uint16_t port) +{ + /* Add space for a colon and up to 5 digits. */ + static char buf[TOR_ADDR_BUF_LEN + 6]; + tor_snprintf(buf, sizeof(buf), "%s:%u", fmt_and_decorate_addr(addr), port); + return buf; +} + /** Like fmt_addr(), but takes <b>addr</b> as a host-order IPv4 * addresses. Also not thread-safe, also clobbers its return buffer on * repeated calls. */ @@ -1136,6 +1187,8 @@ get_interface_addresses_raw(int severity) result = smartlist_new(); for (i = ifa; i; i = i->ifa_next) { tor_addr_t tmp; + if ((i->ifa_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) + continue; if (!i->ifa_addr) continue; if (i->ifa_addr->sa_family != AF_INET && @@ -1220,14 +1273,14 @@ get_interface_addresses_raw(int severity) /* This interface, AFAICT, only supports AF_INET addresses */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { - log(severity, LD_NET, "socket failed: %s", strerror(errno)); + tor_log(severity, LD_NET, "socket failed: %s", strerror(errno)); goto done; } /* Guess how much space we need. */ ifc.ifc_len = sz = 15*1024; ifc.ifc_ifcu.ifcu_req = tor_malloc(sz); if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { - log(severity, LD_NET, "ioctl failed: %s", strerror(errno)); + tor_log(severity, LD_NET, "ioctl failed: %s", strerror(errno)); close(fd); goto done; } @@ -1380,7 +1433,46 @@ is_internal_IP(uint32_t ip, int for_listening) return tor_addr_is_internal(&myaddr, for_listening); } -/** Given an address of the form "host:port", try to divide it into its host +/** Given an address of the form "ip:port", try to divide it into its + * ip and port portions, setting *<b>address_out</b> to a newly + * allocated string holding the address portion and *<b>port_out</b> + * to the port. + * + * Don't do DNS lookups and don't allow domain names in the <ip> field. + * Don't accept <b>addrport</b> of the form "<ip>" or "<ip>:0". + * + * Return 0 on success, -1 on failure. */ +int +tor_addr_port_parse(int severity, const char *addrport, + tor_addr_t *address_out, uint16_t *port_out) +{ + int retval = -1; + int r; + char *addr_tmp = NULL; + + tor_assert(addrport); + tor_assert(address_out); + tor_assert(port_out); + + r = tor_addr_port_split(severity, addrport, &addr_tmp, port_out); + if (r < 0) + goto done; + + if (!*port_out) + goto done; + + /* make sure that address_out is an IP address */ + if (tor_addr_parse(address_out, addr_tmp) < 0) + goto done; + + retval = 0; + + done: + tor_free(addr_tmp); + return retval; +} + +/** Given an address of the form "host[:port]", try to divide it into its host * ane port portions, setting *<b>address_out</b> to a newly allocated string * holding the address portion and *<b>port_out</b> to the port (or 0 if no * port is given). Return 0 on success, -1 on failure. */ @@ -1409,17 +1501,17 @@ addr_port_lookup(int severity, const char *addrport, char **address, uint32_t *addr, uint16_t *port_out) { const char *colon; - char *_address = NULL; - int _port; + char *address_ = NULL; + int port_; int ok = 1; tor_assert(addrport); colon = strrchr(addrport, ':'); if (colon) { - _address = tor_strndup(addrport, colon-addrport); - _port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL); - if (!_port) { + address_ = tor_strndup(addrport, colon-addrport); + port_ = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL); + if (!port_) { log_fn(severity, LD_GENERAL, "Port %s out of range", escaped(colon+1)); ok = 0; } @@ -1432,28 +1524,28 @@ addr_port_lookup(int severity, const char *addrport, char **address, ok = 0; } } else { - _address = tor_strdup(addrport); - _port = 0; + address_ = tor_strdup(addrport); + port_ = 0; } if (addr) { /* There's an addr pointer, so we need to resolve the hostname. */ - if (tor_lookup_hostname(_address,addr)) { - log_fn(severity, LD_NET, "Couldn't look up %s", escaped(_address)); + if (tor_lookup_hostname(address_,addr)) { + log_fn(severity, LD_NET, "Couldn't look up %s", escaped(address_)); ok = 0; *addr = 0; } } if (address && ok) { - *address = _address; + *address = address_; } else { if (address) *address = NULL; - tor_free(_address); + tor_free(address_); } if (port_out) - *port_out = ok ? ((uint16_t) _port) : 0; + *port_out = ok ? ((uint16_t) port_) : 0; return ok ? 0 : -1; } @@ -1476,32 +1568,6 @@ addr_mask_get_bits(uint32_t mask) return -1; } -/** Compare two addresses <b>a1</b> and <b>a2</b> for equality under a - * netmask of <b>mbits</b> bits. Return -1, 0, or 1. - * - * XXXX_IP6 Temporary function to allow masks as bitcounts everywhere. This - * will be replaced with an IPv6-aware version as soon as 32-bit addresses are - * no longer passed around. - */ -int -addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits) -{ - if (bits > 32) - bits = 32; - else if (bits == 0) - return 0; - - a1 >>= (32-bits); - a2 >>= (32-bits); - - if (a1 < a2) - return -1; - else if (a1 > a2) - return 1; - else - return 0; -} - /** Parse a string <b>s</b> in the format of (*|port(-maxport)?)?, setting the * various *out pointers as appropriate. Return 0 on success, -1 on failure. */ @@ -1554,93 +1620,6 @@ parse_port_range(const char *port, uint16_t *port_min_out, return 0; } -/** Parse a string <b>s</b> in the format of - * (IP(/mask|/mask-bits)?|*)(:(*|port(-maxport))?)?, setting the various - * *out pointers as appropriate. Return 0 on success, -1 on failure. - */ -int -parse_addr_and_port_range(const char *s, uint32_t *addr_out, - maskbits_t *maskbits_out, uint16_t *port_min_out, - uint16_t *port_max_out) -{ - char *address; - char *mask, *port, *endptr; - struct in_addr in; - int bits; - - tor_assert(s); - tor_assert(addr_out); - tor_assert(maskbits_out); - tor_assert(port_min_out); - tor_assert(port_max_out); - - address = tor_strdup(s); - /* Break 'address' into separate strings. - */ - mask = strchr(address,'/'); - port = strchr(mask?mask:address,':'); - if (mask) - *mask++ = '\0'; - if (port) - *port++ = '\0'; - /* Now "address" is the IP|'*' part... - * "mask" is the Mask|Maskbits part... - * and "port" is the *|port|min-max part. - */ - - if (strcmp(address,"*")==0) { - *addr_out = 0; - } else if (tor_inet_aton(address, &in) != 0) { - *addr_out = ntohl(in.s_addr); - } else { - log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.", - escaped(address)); - goto err; - } - - if (!mask) { - if (strcmp(address,"*")==0) - *maskbits_out = 0; - else - *maskbits_out = 32; - } else { - endptr = NULL; - bits = (int) strtol(mask, &endptr, 10); - if (!*endptr) { - /* strtol handled the whole mask. */ - if (bits < 0 || bits > 32) { - log_warn(LD_GENERAL, - "Bad number of mask bits on address range; rejecting."); - goto err; - } - *maskbits_out = bits; - } else if (tor_inet_aton(mask, &in) != 0) { - bits = addr_mask_get_bits(ntohl(in.s_addr)); - if (bits < 0) { - log_warn(LD_GENERAL, - "Mask %s on address range isn't a prefix; dropping", - escaped(mask)); - goto err; - } - *maskbits_out = bits; - } else { - log_warn(LD_GENERAL, - "Malformed mask %s on address range; rejecting.", - escaped(mask)); - goto err; - } - } - - if (parse_port_range(port, port_min_out, port_max_out)<0) - goto err; - - tor_free(address); - return 0; - err: - tor_free(address); - return -1; -} - /** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual), * write it as a string into the <b>buf_len</b>-byte buffer in * <b>buf</b>. @@ -1698,3 +1677,15 @@ tor_addr_hostname_is_local(const char *name) !strcasecmpend(name, ".local"); } +/** Return a newly allocated tor_addr_port_t with <b>addr</b> and + <b>port</b> filled in. */ +tor_addr_port_t * +tor_addr_port_new(const tor_addr_t *addr, uint16_t port) +{ + tor_addr_port_t *ap = tor_malloc_zero(sizeof(tor_addr_port_t)); + if (addr) + tor_addr_copy(&ap->addr, addr); + ap->port = port; + return ap; +} + diff --git a/src/common/address.h b/src/common/address.h index c6c126862a..77e5855346 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,8 +8,8 @@ * \brief Headers for address.h **/ -#ifndef _TOR_ADDRESS_H -#define _TOR_ADDRESS_H +#ifndef TOR_ADDRESS_H +#define TOR_ADDRESS_H #include "orconfig.h" #include "torint.h" @@ -40,7 +40,7 @@ typedef struct tor_addr_port_t uint16_t port; } tor_addr_port_t; -#define TOR_ADDR_NULL {AF_UNSPEC, {0}}; +#define TOR_ADDR_NULL {AF_UNSPEC, {0}} static INLINE const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a); static INLINE uint32_t tor_addr_to_ipv4n(const tor_addr_t *a); @@ -55,6 +55,7 @@ socklen_t tor_addr_to_sockaddr(const tor_addr_t *a, uint16_t port, int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa, uint16_t *port_out); void tor_addr_make_unspec(tor_addr_t *a); +void tor_addr_make_null(tor_addr_t *a, sa_family_t family); char *tor_sockaddr_to_str(const struct sockaddr *sa); /** Return an in6_addr* equivalent to <b>a</b>, or NULL if <b>a</b> is not @@ -145,6 +146,7 @@ char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC; * addresses. */ #define fmt_and_decorate_addr(a) fmt_addr_impl((a), 1) const char *fmt_addr_impl(const tor_addr_t *addr, int decorate); +const char *fmt_addrport(const tor_addr_t *addr, uint16_t port); const char * fmt_addr32(uint32_t addr); int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr); @@ -167,7 +169,10 @@ int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2, unsigned int tor_addr_hash(const tor_addr_t *addr); int tor_addr_is_v4(const tor_addr_t *addr); -int tor_addr_is_internal(const tor_addr_t *ip, int for_listening); +int tor_addr_is_internal_(const tor_addr_t *ip, int for_listening, + const char *filename, int lineno); +#define tor_addr_is_internal(addr, for_listening) \ + tor_addr_is_internal_((addr), (for_listening), SHORT_FILE__, __LINE__) /** Longest length that can be required for a reverse lookup name. */ /* 32 nybbles, 32 dots, 8 characters of "ip6.arpa", 1 NUL: 73 characters. */ @@ -179,7 +184,8 @@ int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address, int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out); -int tor_addr_parse_mask_ports(const char *s, +#define TAPMP_EXTENDED_STAR 1 +int tor_addr_parse_mask_ports(const char *s, unsigned flags, tor_addr_t *addr_out, maskbits_t *mask_out, uint16_t *port_min_out, uint16_t *port_max_out); const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, @@ -202,6 +208,9 @@ int tor_addr_is_loopback(const tor_addr_t *addr); int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out); +int tor_addr_port_parse(int severity, const char *addrport, + tor_addr_t *address_out, uint16_t *port_out); + int tor_addr_hostname_is_local(const char *name); /* IPv4 helpers */ @@ -210,16 +219,14 @@ int addr_port_lookup(int severity, const char *addrport, char **address, uint32_t *addr, uint16_t *port_out); int parse_port_range(const char *port, uint16_t *port_min_out, uint16_t *port_max_out); -int parse_addr_and_port_range(const char *s, uint32_t *addr_out, - maskbits_t *maskbits_out, uint16_t *port_min_out, - uint16_t *port_max_out); int addr_mask_get_bits(uint32_t mask); -int addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits); /** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/ #define INET_NTOA_BUF_LEN 16 int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len); char *tor_dup_ip(uint32_t addr) ATTR_MALLOC; int get_interface_address(int severity, uint32_t *addr); +tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port); + #endif diff --git a/src/common/aes.c b/src/common/aes.c index 295a90749a..f454a7f7b2 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001, Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -41,6 +41,7 @@ #include "aes.h" #include "util.h" #include "torlog.h" +#include "di_ops.h" #ifdef ANDROID /* Android's OpenSSL seems to have removed all of its Engine support. */ @@ -134,8 +135,8 @@ int evaluate_evp_for_aes(int force_val) { (void) force_val; - log_notice(LD_CRYPTO, "This version of OpenSSL has a known-good EVP " - "counter-mode implementation. Using it."); + log_info(LD_CRYPTO, "This version of OpenSSL has a known-good EVP " + "counter-mode implementation. Using it."); return 0; } int @@ -212,11 +213,11 @@ evaluate_evp_for_aes(int force_val) e = ENGINE_get_cipher_engine(NID_aes_128_ecb); if (e) { - log_notice(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.", + log_info(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.", ENGINE_get_name(e)); should_use_EVP = 1; } else { - log_notice(LD_CRYPTO, "No AES engine found; using AES_* functions."); + log_info(LD_CRYPTO, "No AES engine found; using AES_* functions."); should_use_EVP = 0; } #endif @@ -257,18 +258,18 @@ evaluate_ctr_for_aes(void) for (i=0; i<16; ++i) AES_ctr128_encrypt(&zero[i], &output[i], 1, &key, ivec, ivec_tmp, &pos); - if (memcmp(output, encrypt_zero, 16)) { + if (fast_memneq(output, encrypt_zero, 16)) { /* Counter mode is buggy */ log_notice(LD_CRYPTO, "This OpenSSL has a buggy version of counter mode; " "not using it."); } else { /* Counter mode is okay */ - log_notice(LD_CRYPTO, "This OpenSSL has a good implementation of counter " + log_info(LD_CRYPTO, "This OpenSSL has a good implementation of counter " "mode; using it."); should_use_openssl_CTR = 1; } #else - log_notice(LD_CRYPTO, "This version of OpenSSL has a slow implementation of " + log_info(LD_CRYPTO, "This version of OpenSSL has a slow implementation of " "counter mode; not using it."); #endif return 0; @@ -285,7 +286,7 @@ evaluate_ctr_for_aes(void) * value of the current counter. */ static INLINE void -_aes_fill_buf(aes_cnt_cipher_t *cipher) +aes_fill_buf_(aes_cnt_cipher_t *cipher) { /* We don't currently use OpenSSL's counter mode implementation because: * 1) some versions have known bugs @@ -340,7 +341,7 @@ aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) EVP_EncryptInit(&cipher->key.evp, c, (const unsigned char*)key, NULL); cipher->using_evp = 1; } else { - AES_set_encrypt_key((const unsigned char *)key, key_bits, &cipher->key.aes); + AES_set_encrypt_key((const unsigned char *)key, key_bits,&cipher->key.aes); cipher->using_evp = 0; } @@ -360,7 +361,7 @@ aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) memset(cipher->buf, 0, sizeof(cipher->buf)); else #endif - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } /** Release storage held by <b>cipher</b> @@ -387,9 +388,10 @@ aes_cipher_free(aes_cnt_cipher_t *cipher) #ifdef CAN_USE_OPENSSL_CTR /* Helper function to use EVP with openssl's counter-mode wrapper. */ -static void evp_block128_fn(const uint8_t in[16], - uint8_t out[16], - const void *key) +static void +evp_block128_fn(const uint8_t in[16], + uint8_t out[16], + const void *key) { EVP_CIPHER_CTX *ctx = (void*)key; int inl=16, outl=16; @@ -429,8 +431,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, &cipher->pos); } return; - } - else + } else #endif { int c = cipher->pos; @@ -453,7 +454,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, UPDATE_CTR_BUF(cipher, 1); } UPDATE_CTR_BUF(cipher, 0); - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } } } @@ -469,8 +470,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) if (should_use_openssl_CTR) { aes_crypt(cipher, data, len, data); return; - } - else + } else #endif { int c = cipher->pos; @@ -493,7 +493,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) UPDATE_CTR_BUF(cipher, 1); } UPDATE_CTR_BUF(cipher, 0); - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } } } @@ -515,7 +515,8 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv) #ifdef CAN_USE_OPENSSL_CTR if (!should_use_openssl_CTR) #endif - _aes_fill_buf(cipher); + aes_fill_buf_(cipher); } #endif + diff --git a/src/common/aes.h b/src/common/aes.h index bde567f87f..8ff28a7622 100644 --- a/src/common/aes.h +++ b/src/common/aes.h @@ -1,12 +1,12 @@ /* Copyright (c) 2003, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Implements a minimal interface to counter-mode AES. */ -#ifndef _TOR_AES_H -#define _TOR_AES_H +#ifndef TOR_AES_H +#define TOR_AES_H /** * \file aes.h diff --git a/src/common/ciphers.inc b/src/common/ciphers.inc index 137d78b117..ab4ac40724 100644 --- a/src/common/ciphers.inc +++ b/src/common/ciphers.inc @@ -4,86 +4,51 @@ * * This file was automatically generated by get_mozilla_ciphers.py. */ -#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - CIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) -#else - XCIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) -#endif -#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA - CIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA) -#else - XCIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA) -#endif -#ifdef TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - CIPHER(0x0088, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA) -#else - XCIPHER(0x0088, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA) -#endif -#ifdef TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA - CIPHER(0x0087, TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA) +#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + CIPHER(0xc02b, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) #else - XCIPHER(0x0087, TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA) + XCIPHER(0xc02b, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) #endif -#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA - CIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + CIPHER(0xc02f, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256) #else - XCIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) + XCIPHER(0xc02f, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256) #endif -#ifdef TLS1_TXT_DHE_DSS_WITH_AES_256_SHA - CIPHER(0x0038, TLS1_TXT_DHE_DSS_WITH_AES_256_SHA) +#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + CIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) #else - XCIPHER(0x0038, TLS1_TXT_DHE_DSS_WITH_AES_256_SHA) + XCIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) #endif -#ifdef TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA - CIPHER(0xc00f, TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA) +#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + CIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) #else - XCIPHER(0xc00f, TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA) + XCIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) #endif -#ifdef TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA - CIPHER(0xc005, TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA) +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA + CIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA) #else - XCIPHER(0xc005, TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA) + XCIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA) #endif -#ifdef TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA - CIPHER(0x0084, TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA) +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA + CIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA) #else - XCIPHER(0x0084, TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA) + XCIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA) #endif -#ifdef TLS1_TXT_RSA_WITH_AES_256_SHA - CIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA) +#ifdef TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA + CIPHER(0xc012, TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA) #else - XCIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA) + XCIPHER(0xc012, TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA) #endif #ifdef TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA CIPHER(0xc007, TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA) #else XCIPHER(0xc007, TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA) #endif -#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - CIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) -#else - XCIPHER(0xc009, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) -#endif #ifdef TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA CIPHER(0xc011, TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA) #else XCIPHER(0xc011, TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA) #endif -#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA - CIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA) -#else - XCIPHER(0xc013, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA) -#endif -#ifdef TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - CIPHER(0x0045, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA) -#else - XCIPHER(0x0045, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA) -#endif -#ifdef TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA - CIPHER(0x0044, TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA) -#else - XCIPHER(0x0044, TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA) -#endif #ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA CIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) #else @@ -94,89 +59,63 @@ #else XCIPHER(0x0032, TLS1_TXT_DHE_DSS_WITH_AES_128_SHA) #endif -#ifdef TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA - CIPHER(0xc00c, TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA) -#else - XCIPHER(0xc00c, TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA) -#endif -#ifdef TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA - CIPHER(0xc00e, TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA) -#else - XCIPHER(0xc00e, TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA) -#endif -#ifdef TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA - CIPHER(0xc002, TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA) -#else - XCIPHER(0xc002, TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA) -#endif -#ifdef TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA - CIPHER(0xc004, TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA) +#ifdef TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + CIPHER(0x0045, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA) #else - XCIPHER(0xc004, TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA) + XCIPHER(0x0045, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA) #endif -#ifdef TLS1_TXT_RSA_WITH_SEED_SHA - CIPHER(0x0096, TLS1_TXT_RSA_WITH_SEED_SHA) +#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA + CIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) #else - XCIPHER(0x0096, TLS1_TXT_RSA_WITH_SEED_SHA) + XCIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) #endif -#ifdef TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA - CIPHER(0x0041, TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA) +#ifdef TLS1_TXT_DHE_DSS_WITH_AES_256_SHA + CIPHER(0x0038, TLS1_TXT_DHE_DSS_WITH_AES_256_SHA) #else - XCIPHER(0x0041, TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA) + XCIPHER(0x0038, TLS1_TXT_DHE_DSS_WITH_AES_256_SHA) #endif -#ifdef SSL3_TXT_RSA_RC4_128_MD5 - CIPHER(0x0004, SSL3_TXT_RSA_RC4_128_MD5) +#ifdef TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + CIPHER(0x0088, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA) #else - XCIPHER(0x0004, SSL3_TXT_RSA_RC4_128_MD5) + XCIPHER(0x0088, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA) #endif -#ifdef SSL3_TXT_RSA_RC4_128_SHA - CIPHER(0x0005, SSL3_TXT_RSA_RC4_128_SHA) +#ifdef SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA + CIPHER(0x0016, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) #else - XCIPHER(0x0005, SSL3_TXT_RSA_RC4_128_SHA) + XCIPHER(0x0016, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) #endif #ifdef TLS1_TXT_RSA_WITH_AES_128_SHA CIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA) #else XCIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA) #endif -#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA - CIPHER(0xc008, TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA) -#else - XCIPHER(0xc008, TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA) -#endif -#ifdef TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA - CIPHER(0xc012, TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA) -#else - XCIPHER(0xc012, TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA) -#endif -#ifdef SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA - CIPHER(0x0016, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) +#ifdef TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA + CIPHER(0x0041, TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA) #else - XCIPHER(0x0016, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) + XCIPHER(0x0041, TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA) #endif -#ifdef SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA - CIPHER(0x0013, SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA) +#ifdef TLS1_TXT_RSA_WITH_AES_256_SHA + CIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA) #else - XCIPHER(0x0013, SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA) + XCIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA) #endif -#ifdef TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA - CIPHER(0xc00d, TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA) +#ifdef TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA + CIPHER(0x0084, TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA) #else - XCIPHER(0xc00d, TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA) + XCIPHER(0x0084, TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA) #endif -#ifdef TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA - CIPHER(0xc003, TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA) +#ifdef SSL3_TXT_RSA_DES_192_CBC3_SHA + CIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) #else - XCIPHER(0xc003, TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA) + XCIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) #endif -/* No openssl macro found for 0xfeff */ -#ifdef SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA - CIPHER(0xfeff, SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA) +#ifdef SSL3_TXT_RSA_RC4_128_SHA + CIPHER(0x0005, SSL3_TXT_RSA_RC4_128_SHA) #else - XCIPHER(0xfeff, SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA) + XCIPHER(0x0005, SSL3_TXT_RSA_RC4_128_SHA) #endif -#ifdef SSL3_TXT_RSA_DES_192_CBC3_SHA - CIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) +#ifdef SSL3_TXT_RSA_RC4_128_MD5 + CIPHER(0x0004, SSL3_TXT_RSA_RC4_128_MD5) #else - XCIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) + XCIPHER(0x0004, SSL3_TXT_RSA_RC4_128_MD5) #endif diff --git a/src/common/compat.c b/src/common/compat.c index 59e3898deb..d88c5f92de 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -18,7 +18,7 @@ /* XXXX024 We should just use AC_USE_SYSTEM_EXTENSIONS in our autoconf, * and get this (and other important stuff!) automatically. Once we do that, * make sure to also change the extern char **environ detection in - * configure.in, because whether that is declared or not depends on whether + * configure.ac, because whether that is declared or not depends on whether * we have _GNU_SOURCE defined! Maybe that means that once we take this out, * we can also take out the configure check. */ #define _GNU_SOURCE @@ -137,8 +137,13 @@ tor_open_cloexec(const char *path, int flags, unsigned mode) fd = open(path, flags, mode); #ifdef FD_CLOEXEC - if (fd >= 0) - fcntl(fd, F_SETFD, FD_CLOEXEC); + if (fd >= 0) { + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { + log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno)); + close(fd); + return -1; + } + } #endif return fd; } @@ -150,8 +155,13 @@ tor_fopen_cloexec(const char *path, const char *mode) { FILE *result = fopen(path, mode); #ifdef FD_CLOEXEC - if (result != NULL) - fcntl(fileno(result), F_SETFD, FD_CLOEXEC); + if (result != NULL) { + if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) { + log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno)); + fclose(result); + return NULL; + } + } #endif return result; } @@ -425,11 +435,10 @@ tor_vasprintf(char **strp, const char *fmt, va_list args) else *strp = strp_tmp; return r; -#elif defined(_MSC_VER) +#elif defined(HAVE__VSCPRINTF) /* 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; @@ -861,6 +870,9 @@ tor_lockfile_unlock(tor_lockfile_t *lockfile) /** @{ */ /** Some old versions of Unix didn't define constants for these values, * and instead expect you to say 0, 1, or 2. */ +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif @@ -891,6 +903,18 @@ tor_fd_seekend(int fd) #endif } +/** Move <b>fd</b> to position <b>pos</b> in the file. Return -1 on error, 0 + * on success. */ +int +tor_fd_setpos(int fd, off_t pos) +{ +#ifdef _WIN32 + return _lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0; +#else + return lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0; +#endif +} + #undef DEBUG_SOCKET_COUNTING #ifdef DEBUG_SOCKET_COUNTING /** A bitarray of all fds that should be passed to tor_socket_close(). Only @@ -1025,7 +1049,15 @@ tor_open_socket(int domain, int type, int protocol) return s; #if defined(FD_CLOEXEC) - fcntl(s, F_SETFD, FD_CLOEXEC); + if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) { + log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno)); +#if defined(_WIN32) + closesocket(s); +#else + close(s); +#endif + return -1; + } #endif goto socket_ok; /* So that socket_ok will not be unused. */ @@ -1060,7 +1092,11 @@ tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len) return s; #if defined(FD_CLOEXEC) - fcntl(s, F_SETFD, FD_CLOEXEC); + if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) { + log_warn(LD_NET, "Couldn't set FD_CLOEXEC: %s", strerror(errno)); + close(s); + return TOR_INVALID_SOCKET; + } #endif goto socket_ok; /* So that socket_ok will not be unused. */ @@ -1084,17 +1120,31 @@ get_n_open_sockets(void) return n; } -/** Turn <b>socket</b> into a nonblocking socket. +/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1 + * on failure. */ -void +int set_socket_nonblocking(tor_socket_t socket) { #if defined(_WIN32) unsigned long nonblocking = 1; ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking); #else - fcntl(socket, F_SETFL, O_NONBLOCK); + int flags; + + flags = fcntl(socket, F_GETFL, 0); + if (flags == -1) { + log_warn(LD_NET, "Couldn't get file status flags: %s", strerror(errno)); + return -1; + } + flags |= O_NONBLOCK; + if (fcntl(socket, F_SETFL, flags) == -1) { + log_warn(LD_NET, "Couldn't set file status flags: %s", strerror(errno)); + return -1; + } #endif + + return 0; } /** @@ -1137,10 +1187,22 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) return -errno; #if defined(FD_CLOEXEC) - if (SOCKET_OK(fd[0])) - fcntl(fd[0], F_SETFD, FD_CLOEXEC); - if (SOCKET_OK(fd[1])) - fcntl(fd[1], F_SETFD, FD_CLOEXEC); + if (SOCKET_OK(fd[0])) { + r = fcntl(fd[0], F_SETFD, FD_CLOEXEC); + if (r == -1) { + close(fd[0]); + close(fd[1]); + return -errno; + } + } + if (SOCKET_OK(fd[1])) { + r = fcntl(fd[1], F_SETFD, FD_CLOEXEC); + if (r == -1) { + close(fd[0]); + close(fd[1]); + return -errno; + } + } #endif goto sockets_ok; /* So that sockets_ok will not be unused. */ @@ -1163,9 +1225,9 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) * for now, and really, when localhost is down sometimes, we * have other problems too. */ - tor_socket_t listener = -1; - tor_socket_t connector = -1; - tor_socket_t acceptor = -1; + tor_socket_t listener = TOR_INVALID_SOCKET; + tor_socket_t connector = TOR_INVALID_SOCKET; + tor_socket_t acceptor = TOR_INVALID_SOCKET; struct sockaddr_in listen_addr; struct sockaddr_in connect_addr; int size; @@ -1219,7 +1281,6 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) goto tidy_up_and_fail; if (size != sizeof(listen_addr)) goto abort_tidy_up_and_fail; - tor_close_socket(listener); /* Now check we are talking to ourself by matching port and host on the two sockets. */ if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) @@ -1230,6 +1291,7 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) || listen_addr.sin_port != connect_addr.sin_port) { goto abort_tidy_up_and_fail; } + tor_close_socket(listener); fd[0] = connector; fd[1] = acceptor; @@ -1244,11 +1306,11 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) tidy_up_and_fail: if (saved_errno < 0) saved_errno = errno; - if (listener != -1) + if (SOCKET_OK(listener)) tor_close_socket(listener); - if (connector != -1) + if (SOCKET_OK(connector)) tor_close_socket(connector); - if (acceptor != -1) + if (SOCKET_OK(acceptor)) tor_close_socket(acceptor); return -saved_errno; #endif @@ -1256,7 +1318,7 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) /** Number of extra file descriptors to keep in reserve beyond those that we * tell Tor it's allowed to use. */ -#define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond _ConnLimit */ +#define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */ /** Learn the maximum allowed number of file descriptors, and tell the system * we want to use up to that number. (Some systems have a low soft limit, and @@ -2060,30 +2122,6 @@ tor_lookup_hostname(const char *name, uint32_t *addr) return -1; } -/** Initialize the insecure libc RNG. */ -void -tor_init_weak_random(unsigned seed) -{ -#ifdef _WIN32 - 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 _WIN32 - 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. */ @@ -2290,8 +2328,33 @@ compute_num_cpus_impl(void) return (int)info.dwNumberOfProcessors; else return -1; -#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF) - long cpus = sysconf(_SC_NPROCESSORS_CONF); +#elif defined(HAVE_SYSCONF) +#ifdef _SC_NPROCESSORS_CONF + long cpus_conf = sysconf(_SC_NPROCESSORS_CONF); +#else + long cpus_conf = -1; +#endif +#ifdef _SC_NPROCESSORS_ONLN + long cpus_onln = sysconf(_SC_NPROCESSORS_ONLN); +#else + long cpus_onln = -1; +#endif + long cpus = -1; + + if (cpus_conf > 0 && cpus_onln < 0) { + cpus = cpus_conf; + } else if (cpus_onln > 0 && cpus_conf < 0) { + cpus = cpus_onln; + } else if (cpus_onln > 0 && cpus_conf > 0) { + if (cpus_onln < cpus_conf) { + log_notice(LD_GENERAL, "I think we have %ld CPUS, but only %ld of them " + "are available. Telling Tor to only use %ld. You can over" + "ride this with the NumCPUs option", + cpus_conf, cpus_onln, cpus_onln); + } + cpus = cpus_onln; + } + if (cpus >= 1 && cpus < INT_MAX) return (int)cpus; else @@ -2759,7 +2822,7 @@ tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex) EnterCriticalSection(&cond->mutex); tor_assert(WaitForSingleObject(event, 0) == WAIT_TIMEOUT); - tor_assert(!smartlist_isin(cond->events, event)); + tor_assert(!smartlist_contains(cond->events, event)); smartlist_add(cond->events, event); LeaveCriticalSection(&cond->mutex); diff --git a/src/common/compat.h b/src/common/compat.h index 42648bb04b..51fb8c5273 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -1,10 +1,10 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_COMPAT_H -#define _TOR_COMPAT_H +#ifndef TOR_COMPAT_H +#define TOR_COMPAT_H #include "orconfig.h" #include "torint.h" @@ -53,13 +53,13 @@ #endif #include <stdio.h> +#include <errno.h> #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 */ @@ -74,6 +74,10 @@ #error "It seems your platform does not represent NULL as zero. We can't cope." #endif +#ifndef DOUBLE_0_REP_IS_ZERO_BYTES +#error "It seems your platform does not represent 0.0 as zeros. We can't cope." +#endif + #if 'a'!=97 || 'z'!=122 || 'A'!=65 || ' '!=32 #error "It seems that you encode characters in something other than ASCII." #endif @@ -132,6 +136,16 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #define DBL_TO_U64(x) ((uint64_t) (x)) #endif +#ifdef ENUM_VALS_ARE_SIGNED +#define ENUM_BF(t) unsigned +#else +/** Wrapper for having a bitfield of an enumerated type. Where possible, we + * just use the enumerated type (so the compiler can help us and notice + * problems), but if enumerated types are unsigned, we must use unsigned, + * so that the loss of precision doesn't make large values negative. */ +#define ENUM_BF(t) t +#endif + /* GCC has several useful attributes. */ #if defined(__GNUC__) && __GNUC__ >= 3 #define ATTR_NORETURN __attribute__((noreturn)) @@ -148,6 +162,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) { * * #define ATTR_NONNULL(x) __attribute__((nonnull x)) */ #define ATTR_NONNULL(x) +#define ATTR_UNUSED __attribute__ ((unused)) /** Macro: Evaluates to <b>exp</b> and hints the compiler that the value * of <b>exp</b> will probably be true. @@ -171,6 +186,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #define ATTR_MALLOC #define ATTR_NORETURN #define ATTR_NONNULL(x) +#define ATTR_UNUSED #define PREDICT_LIKELY(exp) (exp) #define PREDICT_UNLIKELY(exp) (exp) #endif @@ -239,6 +255,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2)); #define I64_FORMAT "%lld" #endif +#if (SIZEOF_INTPTR_T == SIZEOF_INT) +#define INTPTR_T_FORMAT "%d" +#define INTPTR_PRINTF_ARG(x) ((int)(x)) +#elif (SIZEOF_INTPTR_T == SIZEOF_LONG) +#define INTPTR_T_FORMAT "%ld" +#define INTPTR_PRINTF_ARG(x) ((long)(x)) +#elif (SIZEOF_INTPTR_T == 8) +#define INTPTR_T_FORMAT I64_FORMAT +#define INTPTR_PRINTF_ARG(x) I64_PRINTF_ARG(x) +#else +#error Unknown: SIZEOF_INTPTR_T +#endif + /** Represents an mmaped file. Allocated via tor_mmap_file; freed with * tor_munmap_file. */ typedef struct tor_mmap_t { @@ -308,10 +337,10 @@ char *tor_strtok_r_impl(char *str, const char *sep, char **lasts); #endif #ifdef _WIN32 -#define _SHORT_FILE_ (tor_fix_source_file(__FILE__)) +#define SHORT_FILE__ (tor_fix_source_file(__FILE__)) const char *tor_fix_source_file(const char *fname); #else -#define _SHORT_FILE_ (__FILE__) +#define SHORT_FILE__ (__FILE__) #define tor_fix_source_file(s) (s) #endif @@ -384,6 +413,7 @@ tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking, void tor_lockfile_unlock(tor_lockfile_t *lockfile); off_t tor_fd_getpos(int fd); +int tor_fd_setpos(int fd, off_t pos); int tor_fd_seekend(int fd); #ifdef _WIN32 @@ -403,11 +433,13 @@ typedef int socklen_t; * any inadvertant checks for the socket being <= 0 or > 0 will probably * still work. */ #define tor_socket_t intptr_t +#define TOR_SOCKET_T_FORMAT INTPTR_T_FORMAT #define SOCKET_OK(s) ((SOCKET)(s) != INVALID_SOCKET) #define TOR_INVALID_SOCKET INVALID_SOCKET #else /** Type used for a network socket. */ #define tor_socket_t int +#define TOR_SOCKET_T_FORMAT "%d" /** Macro: true iff 's' is a possible value for a valid initialized socket. */ #define SOCKET_OK(s) ((s) >= 0) /** Error/uninitialized value for a tor_socket_t. */ @@ -489,7 +521,7 @@ int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2)); const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len); int tor_inet_pton(int af, const char *src, void *dst); int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2)); -void set_socket_nonblocking(tor_socket_t socket); +int set_socket_nonblocking(tor_socket_t socket); int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]); int network_init(void); @@ -523,10 +555,15 @@ int tor_socket_errno(tor_socket_t sock); const char *tor_socket_strerror(int e); #else #define SOCK_ERRNO(e) e +#if EAGAIN == EWOULDBLOCK #define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN) +#else +#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == EWOULDBLOCK) +#endif #define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS) #define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS) -#define ERRNO_IS_ACCEPT_EAGAIN(e) ((e) == EAGAIN || (e) == ECONNABORTED) +#define ERRNO_IS_ACCEPT_EAGAIN(e) \ + (ERRNO_IS_EAGAIN(e) || (e) == ECONNABORTED) #define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \ ((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM) #define ERRNO_IS_EADDRINUSE(e) ((e) == EADDRINUSE) @@ -547,11 +584,6 @@ 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); diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 6655ca87d3..200a7c65fb 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2012, The Tor Project, Inc. */ +/* Copyright (c) 2009-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -54,7 +54,9 @@ typedef uint32_t le_version_t; * it is. */ #define LE_OTHER V(0,0,99) +#if 0 static le_version_t tor_get_libevent_version(const char **v_out); +#endif #if defined(HAVE_EVENT_SET_LOG_CALLBACK) || defined(RUNNING_DOXYGEN) /** A string which, if it appears in a libevent log, should be ignored. */ @@ -74,19 +76,19 @@ libevent_logging_callback(int severity, const char *msg) } switch (severity) { case _EVENT_LOG_DEBUG: - log(LOG_DEBUG, LD_NOCB|LD_NET, "Message from libevent: %s", buf); + log_debug(LD_NOCB|LD_NET, "Message from libevent: %s", buf); break; case _EVENT_LOG_MSG: - log(LOG_INFO, LD_NOCB|LD_NET, "Message from libevent: %s", buf); + log_info(LD_NOCB|LD_NET, "Message from libevent: %s", buf); break; case _EVENT_LOG_WARN: - log(LOG_WARN, LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf); + log_warn(LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf); break; case _EVENT_LOG_ERR: - log(LOG_ERR, LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf); + log_err(LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf); break; default: - log(LOG_WARN, LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s", + log_warn(LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s", severity, buf); break; } @@ -185,13 +187,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg) /* some paths below don't use torcfg, so avoid unused variable warnings */ (void)torcfg; -#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 { int attempts = 0; @@ -266,13 +261,13 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg) #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, + log_info(LD_GENERAL, "Initialized libevent version %s using method %s. Good.", event_get_version(), tor_libevent_get_method()); #else - log(LOG_NOTICE, LD_GENERAL, + log_notice(LD_GENERAL, "Initialized old libevent (version 1.0b or earlier)."); - log(LOG_WARN, LD_GENERAL, + 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 @@ -364,6 +359,7 @@ le_versions_compatibility(le_version_t v) return 5; } +#if 0 /** Return the version number of the currently running version of Libevent. * See le_version_t for info on the format. */ @@ -386,6 +382,7 @@ tor_get_libevent_version(const char **v_out) *v_out = v; return r; } +#endif /** Return a string representation of the version of the currently running * version of Libevent. */ @@ -407,77 +404,9 @@ 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); - - /* It would be better to disable known-buggy methods rather than warning - * about them. But the problem is that with older versions of Libevent, - * it's not trivial to get them to change their methods once they're - * initialized... and with newer versions of Libevent, they aren't actually - * broken. But we should revisit this if we ever find a post-1.4 version - * of Libevent where we need to disable a given method. */ - 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; + (void) m; + (void) server; + *badness_out = NULL; } #if defined(LIBEVENT_VERSION) @@ -511,7 +440,7 @@ tor_check_libevent_header_compatibility(void) verybad = compat1 != compat2; - log(verybad ? LOG_WARN : LOG_NOTICE, + tor_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()); diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index 56285ef80d..2472e2c49e 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -1,8 +1,8 @@ -/* Copyright (c) 2009-2012, The Tor Project, Inc. */ +/* Copyright (c) 2009-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_COMPAT_LIBEVENT_H -#define _TOR_COMPAT_LIBEVENT_H +#ifndef TOR_COMPAT_LIBEVENT_H +#define TOR_COMPAT_LIBEVENT_H #include "orconfig.h" diff --git a/src/common/container.c b/src/common/container.c index ede98eca5a..eec497a3e6 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -163,7 +163,7 @@ smartlist_string_remove(smartlist_t *sl, const char *element) /** Return true iff some element E of sl has E==element. */ int -smartlist_isin(const smartlist_t *sl, const void *element) +smartlist_contains(const smartlist_t *sl, const void *element) { int i; for (i=0; i < sl->num_used; i++) @@ -176,7 +176,7 @@ smartlist_isin(const smartlist_t *sl, const void *element) * !strcmp(E,<b>element</b>) */ int -smartlist_string_isin(const smartlist_t *sl, const char *element) +smartlist_contains_string(const smartlist_t *sl, const char *element) { int i; if (!sl) return 0; @@ -203,7 +203,7 @@ smartlist_string_pos(const smartlist_t *sl, const char *element) * !strcasecmp(E,<b>element</b>) */ int -smartlist_string_isin_case(const smartlist_t *sl, const char *element) +smartlist_contains_string_case(const smartlist_t *sl, const char *element) { int i; if (!sl) return 0; @@ -217,11 +217,11 @@ smartlist_string_isin_case(const smartlist_t *sl, const char *element) * to the decimal encoding of <b>num</b>. */ int -smartlist_string_num_isin(const smartlist_t *sl, int num) +smartlist_contains_int_as_string(const smartlist_t *sl, int num) { char buf[32]; /* long enough for 64-bit int, and then some. */ tor_snprintf(buf,sizeof(buf),"%d", num); - return smartlist_string_isin(sl, buf); + return smartlist_contains_string(sl, buf); } /** Return true iff the two lists contain the same strings in the same @@ -247,7 +247,7 @@ smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2) * tor_memeq(E,<b>element</b>,DIGEST_LEN) */ int -smartlist_digest_isin(const smartlist_t *sl, const char *element) +smartlist_contains_digest(const smartlist_t *sl, const char *element) { int i; if (!sl) return 0; @@ -257,19 +257,19 @@ smartlist_digest_isin(const smartlist_t *sl, const char *element) return 0; } -/** Return true iff some element E of sl2 has smartlist_isin(sl1,E). +/** Return true iff some element E of sl2 has smartlist_contains(sl1,E). */ int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2) { int i; for (i=0; i < sl2->num_used; i++) - if (smartlist_isin(sl1, sl2->list[i])) + if (smartlist_contains(sl1, sl2->list[i])) return 1; return 0; } -/** Remove every element E of sl1 such that !smartlist_isin(sl2,E). +/** Remove every element E of sl1 such that !smartlist_contains(sl2,E). * Does not preserve the order of sl1. */ void @@ -277,13 +277,13 @@ smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2) { int i; for (i=0; i < sl1->num_used; i++) - if (!smartlist_isin(sl2, sl1->list[i])) { + if (!smartlist_contains(sl2, sl1->list[i])) { sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */ i--; /* so we process the new i'th element */ } } -/** Remove every element E of sl1 such that smartlist_isin(sl2,E). +/** Remove every element E of sl1 such that smartlist_contains(sl2,E). * Does not preserve the order of sl1. */ void @@ -571,59 +571,116 @@ smartlist_bsearch_idx(const smartlist_t *sl, const void *key, int (*compare)(const void *key, const void **member), int *found_out) { - const int len = smartlist_len(sl); - int hi, lo, cmp, mid; + int hi, lo, cmp, mid, len, diff; + tor_assert(sl); + tor_assert(compare); + tor_assert(found_out); + + len = smartlist_len(sl); + + /* Check for the trivial case of a zero-length list */ if (len == 0) { *found_out = 0; + /* We already know smartlist_len(sl) is 0 in this case */ return 0; - } else if (len == 1) { - cmp = compare(key, (const void **) &sl->list[0]); - if (cmp == 0) { - *found_out = 1; - return 0; - } else if (cmp < 0) { - *found_out = 0; - return 0; - } else { - *found_out = 0; - return 1; - } } - hi = smartlist_len(sl) - 1; + /* Okay, we have a real search to do */ + tor_assert(len > 0); lo = 0; + hi = len - 1; + + /* + * These invariants are always true: + * + * For all i such that 0 <= i < lo, sl[i] < key + * For all i such that hi < i <= len, sl[i] > key + */ while (lo <= hi) { - mid = (lo + hi) / 2; + diff = hi - lo; + /* + * We want mid = (lo + hi) / 2, but that could lead to overflow, so + * instead diff = hi - lo (non-negative because of loop condition), and + * then hi = lo + diff, mid = (lo + lo + diff) / 2 = lo + (diff / 2). + */ + mid = lo + (diff / 2); cmp = compare(key, (const void**) &(sl->list[mid])); - if (cmp>0) { /* key > sl[mid] */ - lo = mid+1; - } else if (cmp<0) { /* key < sl[mid] */ - hi = mid-1; - } else { /* key == sl[mid] */ + if (cmp == 0) { + /* sl[mid] == key; we found it */ *found_out = 1; return mid; - } - } - /* lo > hi. */ - { - tor_assert(lo >= 0); - if (lo < smartlist_len(sl)) { - cmp = compare(key, (const void**) &(sl->list[lo])); + } else if (cmp > 0) { + /* + * key > sl[mid] and an index i such that sl[i] == key must + * have i > mid if it exists. + */ + + /* + * Since lo <= mid <= hi, hi can only decrease on each iteration (by + * being set to mid - 1) and hi is initially len - 1, mid < len should + * always hold, and this is not symmetric with the left end of list + * mid > 0 test below. A key greater than the right end of the list + * should eventually lead to lo == hi == mid == len - 1, and then + * we set lo to len below and fall out to the same exit we hit for + * a key in the middle of the list but not matching. Thus, we just + * assert for consistency here rather than handle a mid == len case. + */ + tor_assert(mid < len); + /* Move lo to the element immediately after sl[mid] */ + lo = mid + 1; + } else { + /* This should always be true in this case */ tor_assert(cmp < 0); - } else if (smartlist_len(sl)) { - cmp = compare(key, (const void**) &(sl->list[smartlist_len(sl)-1])); - tor_assert(cmp > 0); + + /* + * key < sl[mid] and an index i such that sl[i] == key must + * have i < mid if it exists. + */ + + if (mid > 0) { + /* Normal case, move hi to the element immediately before sl[mid] */ + hi = mid - 1; + } else { + /* These should always be true in this case */ + tor_assert(mid == lo); + tor_assert(mid == 0); + /* + * We were at the beginning of the list and concluded that every + * element e compares e > key. + */ + *found_out = 0; + return 0; + } } } + + /* + * lo > hi; we have no element matching key but we have elements falling + * on both sides of it. The lo index points to the first element > key. + */ + tor_assert(lo == hi + 1); /* All other cases should have been handled */ + tor_assert(lo >= 0); + tor_assert(lo <= len); + tor_assert(hi >= 0); + tor_assert(hi <= len); + + if (lo < len) { + cmp = compare(key, (const void **) &(sl->list[lo])); + tor_assert(cmp < 0); + } else { + cmp = compare(key, (const void **) &(sl->list[len-1])); + tor_assert(cmp > 0); + } + *found_out = 0; return lo; } /** Helper: compare two const char **s. */ static int -_compare_string_ptrs(const void **_a, const void **_b) +compare_string_ptrs_(const void **_a, const void **_b) { return strcmp((const char*)*_a, (const char*)*_b); } @@ -633,14 +690,14 @@ _compare_string_ptrs(const void **_a, const void **_b) void smartlist_sort_strings(smartlist_t *sl) { - smartlist_sort(sl, _compare_string_ptrs); + 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); + return smartlist_get_most_frequent(sl, compare_string_ptrs_); } /** Remove duplicate strings from a sorted list, and free them with tor_free(). @@ -648,7 +705,7 @@ smartlist_get_most_frequent_string(smartlist_t *sl) void smartlist_uniq_strings(smartlist_t *sl) { - smartlist_uniq(sl, _compare_string_ptrs, _tor_free); + smartlist_uniq(sl, compare_string_ptrs_, tor_free_); } /* Heap-based priority queue implementation for O(lg N) insert and remove. @@ -849,7 +906,7 @@ smartlist_pqueue_assert_ok(smartlist_t *sl, /** Helper: compare two DIGEST_LEN digests. */ static int -_compare_digests(const void **_a, const void **_b) +compare_digests_(const void **_a, const void **_b) { return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN); } @@ -858,7 +915,7 @@ _compare_digests(const void **_a, const void **_b) void smartlist_sort_digests(smartlist_t *sl) { - smartlist_sort(sl, _compare_digests); + smartlist_sort(sl, compare_digests_); } /** Remove duplicate digests from a sorted list, and free them with tor_free(). @@ -866,12 +923,12 @@ smartlist_sort_digests(smartlist_t *sl) void smartlist_uniq_digests(smartlist_t *sl) { - smartlist_uniq(sl, _compare_digests, _tor_free); + smartlist_uniq(sl, compare_digests_, tor_free_); } /** Helper: compare two DIGEST256_LEN digests. */ static int -_compare_digests256(const void **_a, const void **_b) +compare_digests256_(const void **_a, const void **_b) { return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN); } @@ -880,7 +937,7 @@ _compare_digests256(const void **_a, const void **_b) void smartlist_sort_digests256(smartlist_t *sl) { - smartlist_sort(sl, _compare_digests256); + smartlist_sort(sl, compare_digests256_); } /** Return the most frequent member of the sorted list of DIGEST256_LEN @@ -888,7 +945,7 @@ smartlist_sort_digests256(smartlist_t *sl) char * smartlist_get_most_frequent_digest256(smartlist_t *sl) { - return smartlist_get_most_frequent(sl, _compare_digests256); + return smartlist_get_most_frequent(sl, compare_digests256_); } /** Remove duplicate 256-bit digests from a sorted list, and free them with @@ -897,7 +954,7 @@ smartlist_get_most_frequent_digest256(smartlist_t *sl) void smartlist_uniq_digests256(smartlist_t *sl) { - smartlist_uniq(sl, _compare_digests256, _tor_free); + smartlist_uniq(sl, compare_digests256_, tor_free_); } /** Helper: Declare an entry type and a map type to implement a mapping using diff --git a/src/common/container.h b/src/common/container.h index dab3b83f37..fb93747945 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -1,10 +1,10 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_CONTAINER_H -#define _TOR_CONTAINER_H +#ifndef TOR_CONTAINER_H +#define TOR_CONTAINER_H #include "util.h" @@ -35,13 +35,13 @@ void smartlist_remove(smartlist_t *sl, const void *element); void *smartlist_pop_last(smartlist_t *sl); void smartlist_reverse(smartlist_t *sl); void smartlist_string_remove(smartlist_t *sl, const char *element); -int smartlist_isin(const smartlist_t *sl, const void *element); -int smartlist_string_isin(const smartlist_t *sl, const char *element); +int smartlist_contains(const smartlist_t *sl, const void *element); +int smartlist_contains_string(const smartlist_t *sl, const char *element); int smartlist_string_pos(const smartlist_t *, const char *elt); -int smartlist_string_isin_case(const smartlist_t *sl, const char *element); -int smartlist_string_num_isin(const smartlist_t *sl, int num); +int smartlist_contains_string_case(const smartlist_t *sl, const char *element); +int smartlist_contains_int_as_string(const smartlist_t *sl, int num); int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2); -int smartlist_digest_isin(const smartlist_t *sl, const char *element); +int smartlist_contains_digest(const smartlist_t *sl, const char *element); int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2); void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2); void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2); @@ -471,64 +471,74 @@ void* strmap_remove_lc(strmap_t *map, const char *key); #define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \ typedef struct maptype maptype; \ typedef struct prefix##iter_t prefix##iter_t; \ - static INLINE maptype* prefix##new(void) \ + ATTR_UNUSED static INLINE maptype* \ + prefix##new(void) \ { \ return (maptype*)digestmap_new(); \ } \ - static INLINE digestmap_t* prefix##to_digestmap(maptype *map) \ + ATTR_UNUSED static INLINE digestmap_t* \ + prefix##to_digestmap(maptype *map) \ { \ return (digestmap_t*)map; \ } \ - static INLINE valtype* prefix##get(maptype *map, const char *key) \ + ATTR_UNUSED static INLINE valtype* \ + prefix##get(maptype *map, const char *key) \ { \ return (valtype*)digestmap_get((digestmap_t*)map, key); \ } \ - static INLINE valtype* prefix##set(maptype *map, const char *key, \ - valtype *val) \ + ATTR_UNUSED static INLINE valtype* \ + prefix##set(maptype *map, const char *key, valtype *val) \ { \ return (valtype*)digestmap_set((digestmap_t*)map, key, val); \ } \ - static INLINE valtype* prefix##remove(maptype *map, const char *key) \ + ATTR_UNUSED static INLINE valtype* \ + prefix##remove(maptype *map, const char *key) \ { \ return (valtype*)digestmap_remove((digestmap_t*)map, key); \ } \ - static INLINE void prefix##free(maptype *map, void (*free_val)(void*)) \ + ATTR_UNUSED static INLINE void \ + prefix##free(maptype *map, void (*free_val)(void*)) \ { \ digestmap_free((digestmap_t*)map, free_val); \ } \ - static INLINE int prefix##isempty(maptype *map) \ + ATTR_UNUSED static INLINE int \ + prefix##isempty(maptype *map) \ { \ return digestmap_isempty((digestmap_t*)map); \ } \ - static INLINE int prefix##size(maptype *map) \ + ATTR_UNUSED static INLINE int \ + prefix##size(maptype *map) \ { \ return digestmap_size((digestmap_t*)map); \ } \ - static INLINE prefix##iter_t *prefix##iter_init(maptype *map) \ + ATTR_UNUSED static INLINE \ + prefix##iter_t *prefix##iter_init(maptype *map) \ { \ return (prefix##iter_t*) digestmap_iter_init((digestmap_t*)map); \ } \ - static INLINE prefix##iter_t *prefix##iter_next(maptype *map, \ - prefix##iter_t *iter) \ + ATTR_UNUSED static INLINE \ + prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter) \ { \ return (prefix##iter_t*) digestmap_iter_next( \ (digestmap_t*)map, (digestmap_iter_t*)iter); \ } \ - static INLINE prefix##iter_t *prefix##iter_next_rmv(maptype *map, \ - prefix##iter_t *iter) \ + ATTR_UNUSED static INLINE prefix##iter_t* \ + prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter) \ { \ return (prefix##iter_t*) digestmap_iter_next_rmv( \ (digestmap_t*)map, (digestmap_iter_t*)iter); \ } \ - static INLINE void prefix##iter_get(prefix##iter_t *iter, \ - const char **keyp, \ - valtype **valp) \ + ATTR_UNUSED static INLINE void \ + prefix##iter_get(prefix##iter_t *iter, \ + const char **keyp, \ + valtype **valp) \ { \ void *v; \ digestmap_iter_get((digestmap_iter_t*) iter, keyp, &v); \ *valp = v; \ } \ - static INLINE int prefix##iter_done(prefix##iter_t *iter) \ + ATTR_UNUSED static INLINE int \ + prefix##iter_done(prefix##iter_t *iter) \ { \ return digestmap_iter_done((digestmap_iter_t*)iter); \ } @@ -623,7 +633,7 @@ digestset_add(digestset_t *set, const char *digest) /** If <b>digest</b> is in <b>set</b>, return nonzero. Otherwise, * <em>probably</em> return zero. */ static INLINE int -digestset_isin(const digestset_t *set, const char *digest) +digestset_contains(const digestset_t *set, const char *digest) { const uint32_t *p = (const uint32_t *)digest; const uint32_t d1 = p[0] + (p[1]>>16); @@ -675,11 +685,6 @@ 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) -{ - return find_nth_long(array, n_elements, (n_elements-1)/2); -} #endif diff --git a/src/common/crypto.c b/src/common/crypto.c index 30990ecc8f..925beb3529 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001, Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -57,8 +57,8 @@ #include "container.h" #include "compat.h" -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,7) -#error "We require OpenSSL >= 0.9.7" +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) +#error "We require OpenSSL >= 0.9.8" #endif #ifdef ANDROID @@ -69,31 +69,6 @@ /** Longest recognized */ #define MAX_DNS_LABEL_SIZE 63 -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) && \ - !defined(RUNNING_DOXYGEN) -/** @{ */ -/** 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. These macros make it usable by us. */ -#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? */ @@ -101,9 +76,9 @@ SHA256(const unsigned char *m, size_t len, unsigned char *d) #ifdef TOR_IS_MULTITHREADED /** A number of preallocated mutexes for use by OpenSSL. */ -static tor_mutex_t **_openssl_mutexes = NULL; +static tor_mutex_t **openssl_mutexes_ = NULL; /** How many mutexes have we allocated for use by OpenSSL? */ -static int _n_openssl_mutexes = 0; +static int n_openssl_mutexes_ = 0; #endif /** A public key, or a public/private key-pair. */ @@ -138,8 +113,8 @@ crypto_get_rsa_padding_overhead(int padding) { switch (padding) { - case RSA_PKCS1_OAEP_PADDING: return 42; - case RSA_PKCS1_PADDING: return 11; + case RSA_PKCS1_OAEP_PADDING: return PKCS1_OAEP_PADDING_OVERHEAD; + case RSA_PKCS1_PADDING: return PKCS1_PADDING_OVERHEAD; default: tor_assert(0); return -1; } } @@ -158,7 +133,7 @@ crypto_get_rsa_padding(int padding) } /** Boolean: has OpenSSL's crypto been initialized? */ -static int _crypto_global_initialized = 0; +static int crypto_global_initialized_ = 0; /** Log all pending crypto errors at level <b>severity</b>. Use * <b>doing</b> to describe our current activities. @@ -176,10 +151,11 @@ crypto_log_errors(int severity, const char *doing) if (!lib) lib = "(null)"; if (!func) func = "(null)"; if (doing) { - log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)", - doing, msg, lib, func); + tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)", + doing, msg, lib, func); } else { - log(severity, LD_CRYPTO, "crypto error: %s (in %s:%s)", msg, lib, func); + tor_log(severity, LD_CRYPTO, "crypto error: %s (in %s:%s)", + msg, lib, func); } } } @@ -193,10 +169,10 @@ log_engine(const char *fn, ENGINE *e) const char *name, *id; name = ENGINE_get_name(e); id = ENGINE_get_id(e); - log(LOG_NOTICE, LD_CRYPTO, "Using OpenSSL engine %s [%s] for %s", - name?name:"?", id?id:"?", fn); + log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]", + fn, name?name:"?", id?id:"?"); } else { - log(LOG_INFO, LD_CRYPTO, "Using default implementation for %s", fn); + log_info(LD_CRYPTO, "Using default implementation for %s", fn); } } #endif @@ -221,16 +197,60 @@ try_load_engine(const char *path, const char *engine) } #endif +static char *crypto_openssl_version_str = NULL; +/* Return a human-readable version of the run-time openssl version number. */ +const char * +crypto_openssl_get_version_str(void) +{ + if (crypto_openssl_version_str == NULL) { + const char *raw_version = SSLeay_version(SSLEAY_VERSION); + const char *end_of_version = NULL; + /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's + trim that down. */ + if (!strcmpstart(raw_version, "OpenSSL ")) { + raw_version += strlen("OpenSSL "); + end_of_version = strchr(raw_version, ' '); + } + + if (end_of_version) + crypto_openssl_version_str = tor_strndup(raw_version, + end_of_version-raw_version); + else + crypto_openssl_version_str = tor_strdup(raw_version); + } + return crypto_openssl_version_str; +} + /** Initialize the crypto library. Return 0 on success, -1 on failure. */ int crypto_global_init(int useAccel, const char *accelName, const char *accelDir) { - if (!_crypto_global_initialized) { + if (!crypto_global_initialized_) { ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); - _crypto_global_initialized = 1; + crypto_global_initialized_ = 1; setup_openssl_threading(); + + if (SSLeay() == OPENSSL_VERSION_NUMBER && + !strcmp(SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_TEXT)) { + log_info(LD_CRYPTO, "OpenSSL version matches version from headers " + "(%lx: %s).", SSLeay(), SSLeay_version(SSLEAY_VERSION)); + } else { + log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the " + "version we're running with. If you get weird crashes, that " + "might be why. (Compiled with %lx: %s; running with %lx: %s).", + (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, + SSLeay(), SSLeay_version(SSLEAY_VERSION)); + } + + if (SSLeay() < OPENSSL_V_SERIES(1,0,0)) { + log_notice(LD_CRYPTO, + "Your OpenSSL version seems to be %s. We recommend 1.0.0 " + "or later.", + crypto_openssl_get_version_str()); + } + if (useAccel > 0) { #ifdef DISABLE_ENGINES (void)accelName; @@ -268,7 +288,7 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir) } log_engine("RSA", ENGINE_get_default_RSA()); log_engine("DH", ENGINE_get_default_DH()); - log_engine("RAND", ENGINE_get_default_RAND()); + log_engine("RAND (which we will not use)", 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)); @@ -277,6 +297,13 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir) log_info(LD_CRYPTO, "NOT using OpenSSL engine support."); } + if (RAND_get_rand_method() != RAND_SSLeay()) { + log_notice(LD_CRYPTO, "It appears that one of our engines has provided " + "a replacement the OpenSSL RNG. Resetting it to the default " + "implementation."); + RAND_set_rand_method(RAND_SSLeay()); + } + evaluate_evp_for_aes(-1); evaluate_ctr_for_aes(); @@ -294,7 +321,7 @@ crypto_thread_cleanup(void) /** used by tortls.c: wrap an RSA* in a crypto_pk_t. */ crypto_pk_t * -_crypto_new_pk_from_rsa(RSA *rsa) +crypto_new_pk_from_rsa_(RSA *rsa) { crypto_pk_t *env; tor_assert(rsa); @@ -307,7 +334,7 @@ _crypto_new_pk_from_rsa(RSA *rsa) /** Helper, used by tor-checkkey.c and tor-gencert.c. Return the RSA from a * crypto_pk_t. */ RSA * -_crypto_pk_get_rsa(crypto_pk_t *env) +crypto_pk_get_rsa_(crypto_pk_t *env) { return env->key; } @@ -315,7 +342,7 @@ _crypto_pk_get_rsa(crypto_pk_t *env) /** used by tortls.c: get an equivalent EVP_PKEY* for a crypto_pk_t. Iff * private is set, include the private-key portion of the key. */ EVP_PKEY * -_crypto_pk_get_evp_pkey(crypto_pk_t *env, int private) +crypto_pk_get_evp_pkey_(crypto_pk_t *env, int private) { RSA *key = NULL; EVP_PKEY *pkey = NULL; @@ -343,7 +370,7 @@ _crypto_pk_get_evp_pkey(crypto_pk_t *env, int private) /** Used by tortls.c: Get the DH* from a crypto_dh_t. */ DH * -_crypto_dh_get_dh(crypto_dh_t *dh) +crypto_dh_get_dh_(crypto_dh_t *dh) { return dh->dh; } @@ -358,7 +385,7 @@ crypto_pk_new(void) rsa = RSA_new(); tor_assert(rsa); - return _crypto_new_pk_from_rsa(rsa); + return crypto_new_pk_from_rsa_(rsa); } /** Release a reference to an asymmetric key; when all the references @@ -441,11 +468,7 @@ crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits) if (env->key) RSA_free(env->key); -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) - /* In OpenSSL 0.9.7, RSA_generate_key is all we have. */ - env->key = RSA_generate_key(bits, 65537, NULL, NULL); -#else - /* In OpenSSL 0.9.8, RSA_generate_key is deprecated. */ + { BIGNUM *e = BN_new(); RSA *r = NULL; @@ -463,11 +486,11 @@ crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits) r = NULL; done: if (e) - BN_free(e); + BN_clear_free(e); if (r) RSA_free(r); - } -#endif + } + if (!env->key) { crypto_log_errors(LOG_WARN, "generating RSA key"); return -1; @@ -711,19 +734,23 @@ crypto_pk_public_exponent_ok(crypto_pk_t *env) return BN_is_word(env->key->e, 65537); } -/** Compare the public-key components of a and b. Return -1 if a\<b, 0 - * if a==b, and 1 if a\>b. +/** Compare the public-key components of a and b. Return less than 0 + * if a\<b, 0 if a==b, and greater than 0 if a\>b. A NULL key is + * considered to be less than all non-NULL keys, and equal to itself. + * + * Note that this may leak information about the keys through timing. */ int crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b) { int result; + char a_is_non_null = (a != NULL) && (a->key != NULL); + char b_is_non_null = (b != NULL) && (b->key != NULL); + char an_argument_is_null = !a_is_non_null | !b_is_non_null; - if (!a || !b) - return -1; - - if (!a->key || !b->key) - return -1; + result = tor_memcmp(&a_is_non_null, &b_is_non_null, sizeof(a_is_non_null)); + if (an_argument_is_null) + return result; tor_assert(PUBLIC_KEY_OK(a)); tor_assert(PUBLIC_KEY_OK(b)); @@ -733,6 +760,18 @@ crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b) return BN_cmp((a->key)->e, (b->key)->e); } +/** Compare the public-key components of a and b. Return non-zero iff + * a==b. A NULL key is considered to be distinct from all non-NULL + * keys, and equal to itself. + * + * Note that this may leak information about the keys through timing. + */ +int +crypto_pk_eq_keys(crypto_pk_t *a, crypto_pk_t *b) +{ + return (crypto_pk_cmp_keys(a, b) == 0); +} + /** Return the size of the public key modulus in <b>env</b>, in bytes. */ size_t crypto_pk_keysize(crypto_pk_t *env) @@ -791,7 +830,7 @@ crypto_pk_copy_full(crypto_pk_t *env) return NULL; } - return _crypto_new_pk_from_rsa(new_key); + return crypto_new_pk_from_rsa_(new_key); } /** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key @@ -1158,7 +1197,7 @@ crypto_pk_asn1_decode(const char *str, size_t len) crypto_log_errors(LOG_WARN,"decoding public key"); return NULL; } - return _crypto_new_pk_from_rsa(rsa); + return crypto_new_pk_from_rsa_(rsa); } /** Given a private or public key <b>pk</b>, put a SHA1 hash of the @@ -1262,23 +1301,6 @@ crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space) return 0; } -/** Return true iff <b>s</b> is in the correct format for a fingerprint. - */ -int -crypto_pk_check_fingerprint_syntax(const char *s) -{ - int i; - for (i = 0; i < FINGERPRINT_LEN; ++i) { - if ((i%5) == 4) { - if (!TOR_ISSPACE(s[i])) return 0; - } else { - if (!TOR_ISXDIGIT(s[i])) return 0; - } - } - if (s[FINGERPRINT_LEN]) return 0; - return 1; -} - /* symmetric crypto */ /** Return a pointer to the key set for the cipher in <b>env</b>. @@ -1427,7 +1449,7 @@ crypto_digest256(char *digest, const char *m, size_t len, int crypto_digest_all(digests_t *ds_out, const char *m, size_t len) { - digest_algorithm_t i; + int i; tor_assert(ds_out); memset(ds_out, 0, sizeof(*ds_out)); if (crypto_digest(ds_out->d[DIGEST_SHA1], m, len) < 0) @@ -1474,7 +1496,7 @@ struct crypto_digest_t { SHA256_CTX sha2; /**< state for SHA256 */ } d; /**< State for the digest we're using. Only one member of the * union is usable, depending on the value of <b>algorithm</b>. */ - digest_algorithm_t algorithm : 8; /**< Which algorithm is in use? */ + ENUM_BF(digest_algorithm_t) algorithm : 8; /**< Which algorithm is in use? */ }; /** Allocate and return a new digest object to compute SHA1 digests. @@ -1599,6 +1621,29 @@ crypto_digest_assign(crypto_digest_t *into, memcpy(into,from,sizeof(crypto_digest_t)); } +/** 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, + * plus the optional string <b>append</b>, computed with the algorithm + * <b>alg</b>. + * <b>out_len</b> must be \<= DIGEST256_LEN. */ +void +crypto_digest_smartlist(char *digest_out, size_t len_out, + const smartlist_t *lst, const char *append, + digest_algorithm_t alg) +{ + crypto_digest_t *d; + if (alg == DIGEST_SHA1) + d = crypto_digest_new(); + else + d = crypto_digest256_new(alg); + SMARTLIST_FOREACH(lst, const char *, cp, + crypto_digest_add_bytes(d, cp, strlen(cp))); + if (append) + crypto_digest_add_bytes(d, append, strlen(append)); + crypto_digest_get_digest(d, digest_out, len_out); + crypto_digest_free(d); +} + /** Compute the HMAC-SHA-1 of the <b>msg_len</b> bytes in <b>msg</b>, using * the <b>key</b> of length <b>key_len</b>. Store the DIGEST_LEN-byte result * in <b>hmac_out</b>. @@ -1623,63 +1668,11 @@ crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len) { -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(0,9,8) /* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */ tor_assert(key_len < INT_MAX); tor_assert(msg_len < INT_MAX); HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len, (unsigned char*)hmac_out, NULL); -#else - /* OpenSSL doesn't have an EVP implementation for SHA256. We'll need - to do HMAC on our own. - - HMAC isn't so hard: To compute HMAC(key, msg): - 1. If len(key) > blocksize, key = H(key). - 2. If len(key) < blocksize, right-pad key up to blocksize with 0 bytes. - 3. let ipad = key xor 0x363636363636....36 - let opad = key xor 0x5c5c5c5c5c5c....5c - The result is H(opad | H( ipad | msg ) ) - */ -#define BLOCKSIZE 64 -#define DIGESTSIZE 32 - uint8_t k[BLOCKSIZE]; - uint8_t pad[BLOCKSIZE]; - uint8_t d[DIGESTSIZE]; - int i; - SHA256_CTX st; - - tor_assert(key_len < INT_MAX); - tor_assert(msg_len < INT_MAX); - - if (key_len <= BLOCKSIZE) { - memset(k, 0, sizeof(k)); - memcpy(k, key, key_len); /* not time invariant in key_len */ - } else { - SHA256((const uint8_t *)key, key_len, k); - memset(k+DIGESTSIZE, 0, sizeof(k)-DIGESTSIZE); - } - for (i = 0; i < BLOCKSIZE; ++i) - pad[i] = k[i] ^ 0x36; - SHA256_Init(&st); - SHA256_Update(&st, pad, BLOCKSIZE); - SHA256_Update(&st, (uint8_t*)msg, msg_len); - SHA256_Final(d, &st); - - for (i = 0; i < BLOCKSIZE; ++i) - pad[i] = k[i] ^ 0x5c; - SHA256_Init(&st); - SHA256_Update(&st, pad, BLOCKSIZE); - SHA256_Update(&st, d, DIGESTSIZE); - SHA256_Final((uint8_t*)hmac_out, &st); - - /* Now clear everything. */ - memwipe(k, 0, sizeof(k)); - memwipe(pad, 0, sizeof(pad)); - memwipe(d, 0, sizeof(d)); - memwipe(&st, 0, sizeof(st)); -#undef BLOCKSIZE -#undef DIGESTSIZE -#endif } /* DH */ @@ -1929,7 +1922,7 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) /* If the space is occupied, free the previous TLS DH prime */ if (dh_param_p_tls) { - BN_free(dh_param_p_tls); + BN_clear_free(dh_param_p_tls); dh_param_p_tls = NULL; } @@ -2057,6 +2050,16 @@ crypto_dh_new(int dh_type) return NULL; } +/** Return a copy of <b>dh</b>, sharing its internal state. */ +crypto_dh_t * +crypto_dh_dup(const crypto_dh_t *dh) +{ + crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t)); + dh_new->dh = dh->dh; + DH_up_ref(dh->dh); + return dh_new; +} + /** Return the length of the DH key in <b>dh</b>, in bytes. */ int @@ -2081,8 +2084,8 @@ crypto_dh_generate_public(crypto_dh_t *dh) 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. */ - BN_free(dh->dh->pub_key); - BN_free(dh->dh->priv_key); + BN_clear_free(dh->dh->pub_key); + BN_clear_free(dh->dh->priv_key); dh->dh->pub_key = dh->dh->priv_key = NULL; goto again; } @@ -2144,10 +2147,10 @@ tor_check_dh_key(int severity, BIGNUM *bn) log_fn(severity, LD_CRYPTO, "DH key must be at most p-2."); goto err; } - BN_free(x); + BN_clear_free(x); return 0; err: - BN_free(x); + BN_clear_free(x); s = BN_bn2hex(bn); log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s); OPENSSL_free(s); @@ -2195,8 +2198,8 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh, goto error; } secret_len = result; - if (crypto_expand_key_material(secret_tmp, secret_len, - secret_out, secret_bytes_out)<0) + if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len, + (uint8_t*)secret_out, secret_bytes_out)<0) goto error; secret_len = secret_bytes_out; @@ -2206,7 +2209,7 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh, done: crypto_log_errors(LOG_WARN, "completing DH handshake"); if (pubkey_bn) - BN_free(pubkey_bn); + BN_clear_free(pubkey_bn); if (secret_tmp) { memwipe(secret_tmp, 0, secret_tmp_len); tor_free(secret_tmp); @@ -2222,15 +2225,18 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh, * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of * H(K | [00]) | H(K | [01]) | .... * + * This is the key expansion algorithm used in the "TAP" circuit extension + * mechanism; it shouldn't be used for new protocols. + * * Return 0 on success, -1 on failure. */ int -crypto_expand_key_material(const char *key_in, size_t key_in_len, - char *key_out, size_t key_out_len) +crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len, + uint8_t *key_out, size_t key_out_len) { int i; - char *cp, *tmp = tor_malloc(key_in_len+1); - char digest[DIGEST_LEN]; + uint8_t *cp, *tmp = tor_malloc(key_in_len+1); + uint8_t digest[DIGEST_LEN]; /* If we try to get more than this amount of key data, we'll repeat blocks.*/ tor_assert(key_out_len <= DIGEST_LEN*256); @@ -2239,7 +2245,7 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len, for (cp = key_out, i=0; cp < key_out+key_out_len; ++i, cp += DIGEST_LEN) { tmp[key_in_len] = i; - if (crypto_digest(digest, tmp, key_in_len+1)) + if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1)) goto err; memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out))); } @@ -2255,6 +2261,65 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len, return -1; } +/** Expand some secret key material according to RFC5869, using SHA256 as the + * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the + * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the + * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt" + * and "info" parameters respectively. On success, write <b>key_out_len</b> + * bytes to <b>key_out</b> and return 0. On failure, return -1. + */ +int +crypto_expand_key_material_rfc5869_sha256( + const uint8_t *key_in, size_t key_in_len, + const uint8_t *salt_in, size_t salt_in_len, + const uint8_t *info_in, size_t info_in_len, + uint8_t *key_out, size_t key_out_len) +{ + uint8_t prk[DIGEST256_LEN]; + uint8_t tmp[DIGEST256_LEN + 128 + 1]; + uint8_t mac[DIGEST256_LEN]; + int i; + uint8_t *outp; + size_t tmp_len; + + crypto_hmac_sha256((char*)prk, + (const char*)salt_in, salt_in_len, + (const char*)key_in, key_in_len); + + /* If we try to get more than this amount of key data, we'll repeat blocks.*/ + tor_assert(key_out_len <= DIGEST256_LEN * 256); + tor_assert(info_in_len <= 128); + memset(tmp, 0, sizeof(tmp)); + outp = key_out; + i = 1; + + while (key_out_len) { + size_t n; + if (i > 1) { + memcpy(tmp, mac, DIGEST256_LEN); + memcpy(tmp+DIGEST256_LEN, info_in, info_in_len); + tmp[DIGEST256_LEN+info_in_len] = i; + tmp_len = DIGEST256_LEN + info_in_len + 1; + } else { + memcpy(tmp, info_in, info_in_len); + tmp[info_in_len] = i; + tmp_len = info_in_len + 1; + } + crypto_hmac_sha256((char*)mac, + (const char*)prk, DIGEST256_LEN, + (const char*)tmp, tmp_len); + n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN; + memcpy(outp, mac, n); + key_out_len -= n; + outp += n; + ++i; + } + + memwipe(tmp, 0, sizeof(tmp)); + memwipe(mac, 0, sizeof(mac)); + return 0; +} + /** Free a DH key exchange object. */ void @@ -2282,35 +2347,27 @@ crypto_dh_free(crypto_dh_t *dh) * that fd without checking whether it fit in the fd_set. Thus, if the * system has not just been started up, it is unsafe to call */ #define RAND_POLL_IS_SAFE \ - ((OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,7,'j') && \ - OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8)) || \ - OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,8,'c')) + (OPENSSL_VERSION_NUMBER >= OPENSSL_V(0,9,8,'c')) /** Set the seed of the weak RNG to a random value. */ -static void -seed_weak_rng(void) +void +crypto_seed_weak_rng(tor_weak_rng_t *rng) { unsigned seed; crypto_rand((void*)&seed, sizeof(seed)); - tor_init_weak_random(seed); + tor_init_weak_random(rng, 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. +/** Try to get <b>out_len</b> bytes of the strongest entropy we can generate, + * storing it into <b>out</b>. */ int -crypto_seed_rng(int startup) +crypto_strongest_rand(uint8_t *out, size_t out_len) { - int rand_poll_status = 0; - - /* local variables */ #ifdef _WIN32 - unsigned char buf[ADD_ENTROPY]; static int provider_set = 0; static HCRYPTPROV provider; #else - char buf[ADD_ENTROPY]; static const char *filenames[] = { "/dev/srandom", "/dev/urandom", "/dev/random", NULL }; @@ -2318,58 +2375,77 @@ crypto_seed_rng(int startup) size_t n; #endif - /* OpenSSL has a RAND_poll function that knows about more kinds of - * entropy than we do. We'll try calling that, *and* calling our own entropy - * functions. If one succeeds, we'll accept the RNG as seeded. */ - if (startup || RAND_POLL_IS_SAFE) { - rand_poll_status = RAND_poll(); - if (rand_poll_status == 0) - log_warn(LD_CRYPTO, "RAND_poll() failed."); - } - #ifdef _WIN32 if (!provider_set) { if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { if ((unsigned long)GetLastError() != (unsigned long)NTE_BAD_KEYSET) { log_warn(LD_CRYPTO, "Can't get CryptoAPI provider [1]"); - return rand_poll_status ? 0 : -1; + return -1; } } provider_set = 1; } - if (!CryptGenRandom(provider, sizeof(buf), buf)) { + if (!CryptGenRandom(provider, out_len, out)) { log_warn(LD_CRYPTO, "Can't get entropy from CryptoAPI."); - return rand_poll_status ? 0 : -1; + return -1; } - RAND_seed(buf, sizeof(buf)); - memwipe(buf, 0, sizeof(buf)); - seed_weak_rng(); + return 0; #else for (i = 0; filenames[i]; ++i) { fd = open(filenames[i], O_RDONLY, 0); if (fd<0) continue; - log_info(LD_CRYPTO, "Seeding RNG from \"%s\"", filenames[i]); - n = read_all(fd, buf, sizeof(buf), 0); + log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]); + n = read_all(fd, (char*)out, out_len, 0); close(fd); - if (n != sizeof(buf)) { + if (n != out_len) { log_warn(LD_CRYPTO, "Error reading from entropy source (read only %lu bytes).", (unsigned long)n); return -1; } - RAND_seed(buf, (int)sizeof(buf)); - memwipe(buf, 0, sizeof(buf)); - seed_weak_rng(); + return 0; } - log_warn(LD_CRYPTO, "Cannot seed RNG -- no entropy source found."); - return rand_poll_status ? 0 : -1; + log_warn(LD_CRYPTO, "Cannot get strong entropy: no entropy source found."); + return -1; #endif } +/** 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. + */ +int +crypto_seed_rng(int startup) +{ + int rand_poll_ok = 0, load_entropy_ok = 0; + uint8_t buf[ADD_ENTROPY]; + + /* OpenSSL has a RAND_poll function that knows about more kinds of + * entropy than we do. We'll try calling that, *and* calling our own entropy + * functions. If one succeeds, we'll accept the RNG as seeded. */ + if (startup || RAND_POLL_IS_SAFE) { + rand_poll_ok = RAND_poll(); + if (rand_poll_ok == 0) + log_warn(LD_CRYPTO, "RAND_poll() failed."); + } + + load_entropy_ok = !crypto_strongest_rand(buf, sizeof(buf)); + if (load_entropy_ok) { + RAND_seed(buf, sizeof(buf)); + } + + memwipe(buf, 0, sizeof(buf)); + + if (rand_poll_ok || load_entropy_ok) + return 0; + else + return -1; +} + /** Write <b>n</b> bytes of strong random data to <b>to</b>. Return 0 on * success, -1 on failure. */ @@ -2517,7 +2593,7 @@ smartlist_shuffle(smartlist_t *sl) } } -/** Base-64 encode <b>srclen</b> bytes of data from <b>src</b>. Write +/** Base64 encode <b>srclen</b> bytes of data from <b>src</b>. Write * the result into <b>dest</b>, if it will fit within <b>destlen</b> * bytes. Return the number of bytes written on success; -1 if * destlen is too short, or other failure. @@ -2576,7 +2652,7 @@ static const uint8_t base64_decode_table[256] = { X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, }; -/** Base-64 decode <b>srclen</b> bytes of data from <b>src</b>. Write +/** Base64 decode <b>srclen</b> bytes of data from <b>src</b>. Write * the result into <b>dest</b>, if it will fit within <b>destlen</b> * bytes. Return the number of bytes written on success; -1 if * destlen is too short, or other failure. @@ -2683,7 +2759,7 @@ base64_decode(char *dest, size_t destlen, const char *src, size_t srclen) #undef SP #undef PAD -/** Base-64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing = +/** Base64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing = * and newline characters, and store the nul-terminated result in the first * BASE64_DIGEST_LEN+1 bytes of <b>d64</b>. */ int @@ -2696,7 +2772,7 @@ digest_to_base64(char *d64, const char *digest) return 0; } -/** Given a base-64 encoded, nul-terminated digest in <b>d64</b> (without +/** Given a base64 encoded, nul-terminated digest in <b>d64</b> (without * trailing newline or = characters), decode it and store the result in the * first DIGEST_LEN bytes at <b>digest</b>. */ int @@ -2721,7 +2797,7 @@ digest_from_base64(char *digest, const char *d64) #endif } -/** Base-64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the +/** Base64 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 @@ -2734,7 +2810,7 @@ digest256_to_base64(char *d64, const char *digest) return 0; } -/** Given a base-64 encoded, nul-terminated digest in <b>d64</b> (without +/** Given a base64 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 @@ -2759,7 +2835,7 @@ digest256_from_base64(char *digest, const char *d64) #endif } -/** Implements base32 encoding as in rfc3548. Limitation: Requires +/** Implements base32 encoding as in RFC 4648. Limitation: Requires * that srclen*8 is a multiple of 5. */ void @@ -2784,7 +2860,7 @@ base32_encode(char *dest, size_t destlen, const char *src, size_t srclen) dest[i] = '\0'; } -/** Implements base32 decoding as in rfc3548. Limitation: Requires +/** Implements base32 decoding as in RFC 4648. Limitation: Requires * that srclen*5 is a multiple of 8. Returns 0 if successful, -1 otherwise. */ int @@ -2937,21 +3013,27 @@ memwipe(void *mem, uint8_t byte, size_t sz) } #ifdef TOR_IS_MULTITHREADED + +#ifndef OPENSSL_THREADS +#error OpenSSL has been built without thread support. Tor requires an \ + OpenSSL library with thread support enabled. +#endif + /** Helper: OpenSSL uses this callback to manipulate mutexes. */ static void -_openssl_locking_cb(int mode, int n, const char *file, int line) +openssl_locking_cb_(int mode, int n, const char *file, int line) { (void)file; (void)line; - if (!_openssl_mutexes) + if (!openssl_mutexes_) /* This is not a really good fix for the * "release-freed-lock-from-separate-thread-on-shutdown" problem, but * it can't hurt. */ return; if (mode & CRYPTO_LOCK) - tor_mutex_acquire(_openssl_mutexes[n]); + tor_mutex_acquire(openssl_mutexes_[n]); else - tor_mutex_release(_openssl_mutexes[n]); + tor_mutex_release(openssl_mutexes_[n]); } /** OpenSSL helper type: wraps a Tor mutex so that OpenSSL can use it @@ -2963,7 +3045,7 @@ struct CRYPTO_dynlock_value { /** OpenSSL callback function to allocate a lock: see CRYPTO_set_dynlock_* * documentation in OpenSSL's docs for more info. */ static struct CRYPTO_dynlock_value * -_openssl_dynlock_create_cb(const char *file, int line) +openssl_dynlock_create_cb_(const char *file, int line) { struct CRYPTO_dynlock_value *v; (void)file; @@ -2976,7 +3058,7 @@ _openssl_dynlock_create_cb(const char *file, int line) /** OpenSSL callback function to acquire or release a lock: see * CRYPTO_set_dynlock_* documentation in OpenSSL's docs for more info. */ static void -_openssl_dynlock_lock_cb(int mode, struct CRYPTO_dynlock_value *v, +openssl_dynlock_lock_cb_(int mode, struct CRYPTO_dynlock_value *v, const char *file, int line) { (void)file; @@ -2990,7 +3072,7 @@ _openssl_dynlock_lock_cb(int mode, struct CRYPTO_dynlock_value *v, /** OpenSSL callback function to free a lock: see CRYPTO_set_dynlock_* * documentation in OpenSSL's docs for more info. */ static void -_openssl_dynlock_destroy_cb(struct CRYPTO_dynlock_value *v, +openssl_dynlock_destroy_cb_(struct CRYPTO_dynlock_value *v, const char *file, int line) { (void)file; @@ -3007,15 +3089,15 @@ setup_openssl_threading(void) { int i; int n = CRYPTO_num_locks(); - _n_openssl_mutexes = n; - _openssl_mutexes = tor_malloc(n*sizeof(tor_mutex_t *)); + n_openssl_mutexes_ = n; + openssl_mutexes_ = tor_malloc(n*sizeof(tor_mutex_t *)); for (i=0; i < n; ++i) - _openssl_mutexes[i] = tor_mutex_new(); - CRYPTO_set_locking_callback(_openssl_locking_cb); + openssl_mutexes_[i] = tor_mutex_new(); + CRYPTO_set_locking_callback(openssl_locking_cb_); CRYPTO_set_id_callback(tor_get_thread_id); - CRYPTO_set_dynlock_create_callback(_openssl_dynlock_create_cb); - CRYPTO_set_dynlock_lock_callback(_openssl_dynlock_lock_cb); - CRYPTO_set_dynlock_destroy_callback(_openssl_dynlock_destroy_cb); + CRYPTO_set_dynlock_create_callback(openssl_dynlock_create_cb_); + CRYPTO_set_dynlock_lock_callback(openssl_dynlock_lock_cb_); + CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy_cb_); return 0; } #else @@ -3036,11 +3118,11 @@ crypto_global_cleanup(void) ERR_free_strings(); if (dh_param_p) - BN_free(dh_param_p); + BN_clear_free(dh_param_p); if (dh_param_p_tls) - BN_free(dh_param_p_tls); + BN_clear_free(dh_param_p_tls); if (dh_param_g) - BN_free(dh_param_g); + BN_clear_free(dh_param_g); #ifndef DISABLE_ENGINES ENGINE_cleanup(); @@ -3049,18 +3131,19 @@ crypto_global_cleanup(void) CONF_modules_unload(1); CRYPTO_cleanup_all_ex_data(); #ifdef TOR_IS_MULTITHREADED - if (_n_openssl_mutexes) { - int n = _n_openssl_mutexes; - tor_mutex_t **ms = _openssl_mutexes; + if (n_openssl_mutexes_) { + int n = n_openssl_mutexes_; + tor_mutex_t **ms = openssl_mutexes_; int i; - _openssl_mutexes = NULL; - _n_openssl_mutexes = 0; + openssl_mutexes_ = NULL; + n_openssl_mutexes_ = 0; for (i=0;i<n;++i) { tor_mutex_free(ms[i]); } tor_free(ms); } #endif + tor_free(crypto_openssl_version_str); return 0; } diff --git a/src/common/crypto.h b/src/common/crypto.h index 7d56271785..2fbca4c260 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001, Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,8 +10,8 @@ * \brief Headers for crypto.c **/ -#ifndef _TOR_CRYPTO_H -#define _TOR_CRYPTO_H +#ifndef TOR_CRYPTO_H +#define TOR_CRYPTO_H #include <stdio.h> #include "torint.h" @@ -51,7 +51,7 @@ /** 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). */ + * this is just sha256, but it could be any other 256-bit digest.) */ #define DIGEST256_LEN 32 /** Length of our symmetric cipher's keys. */ #define CIPHER_KEY_LEN 16 @@ -111,6 +111,7 @@ typedef struct crypto_digest_t crypto_digest_t; typedef struct crypto_dh_t crypto_dh_t; /* global state */ +const char * crypto_openssl_get_version_str(void); int crypto_global_init(int hardwareAccel, const char *accelName, const char *accelPath); @@ -147,6 +148,7 @@ int crypto_pk_write_private_key_to_filename(crypto_pk_t *env, int crypto_pk_check_key(crypto_pk_t *env); int crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b); +int crypto_pk_eq_keys(crypto_pk_t *a, crypto_pk_t *b); size_t crypto_pk_keysize(crypto_pk_t *env); int crypto_pk_num_bits(crypto_pk_t *env); crypto_pk_t *crypto_pk_dup_key(crypto_pk_t *orig); @@ -181,7 +183,6 @@ crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len); int crypto_pk_get_digest(crypto_pk_t *pk, char *digest_out); int crypto_pk_get_all_digests(crypto_pk_t *pk, digests_t *digests_out); int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space); -int crypto_pk_check_fingerprint_syntax(const char *s); /* symmetric crypto */ const char *crypto_cipher_get_key(crypto_cipher_t *env); @@ -204,6 +205,10 @@ 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); +struct smartlist_t; +void crypto_digest_smartlist(char *digest_out, size_t len_out, + const struct smartlist_t *lst, const char *append, + digest_algorithm_t alg); const char *crypto_digest_algorithm_get_name(digest_algorithm_t alg); int crypto_digest_algorithm_parse_name(const char *name); crypto_digest_t *crypto_digest_new(void); @@ -228,6 +233,7 @@ void crypto_hmac_sha256(char *hmac_out, #define DH_TYPE_REND 2 #define DH_TYPE_TLS 3 crypto_dh_t *crypto_dh_new(int dh_type); +crypto_dh_t *crypto_dh_dup(const crypto_dh_t *dh); int crypto_dh_get_bytes(crypto_dh_t *dh); int crypto_dh_generate_public(crypto_dh_t *dh); int crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out, @@ -236,15 +242,25 @@ ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh, const char *pubkey, size_t pubkey_len, char *secret_out, size_t secret_out_len); void crypto_dh_free(crypto_dh_t *dh); -int crypto_expand_key_material(const char *key_in, size_t in_len, - char *key_out, size_t key_out_len); + +int crypto_expand_key_material_TAP(const uint8_t *key_in, + size_t key_in_len, + uint8_t *key_out, size_t key_out_len); +int crypto_expand_key_material_rfc5869_sha256( + const uint8_t *key_in, size_t key_in_len, + const uint8_t *salt_in, size_t salt_in_len, + const uint8_t *info_in, size_t info_in_len, + uint8_t *key_out, size_t key_out_len); /* random numbers */ int crypto_seed_rng(int startup); int crypto_rand(char *to, size_t n); +int crypto_strongest_rand(uint8_t *out, size_t out_len); int crypto_rand_int(unsigned int max); uint64_t crypto_rand_uint64(uint64_t max); double crypto_rand_double(void); +struct tor_weak_rng_t; +void crypto_seed_weak_rng(struct tor_weak_rng_t *rng); char *crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix, const char *suffix); @@ -255,7 +271,7 @@ void smartlist_shuffle(struct smartlist_t *sl); int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen); int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen); -/** Characters that can appear (case-insensitively) in a base-32 encoding. */ +/** Characters that can appear (case-insensitively) in a base32 encoding. */ #define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567" void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen); int base32_decode(char *dest, size_t destlen, const char *src, size_t srclen); @@ -280,11 +296,11 @@ void memwipe(void *mem, uint8_t byte, size_t sz); struct rsa_st; struct evp_pkey_st; struct dh_st; -struct rsa_st *_crypto_pk_get_rsa(crypto_pk_t *env); -crypto_pk_t *_crypto_new_pk_from_rsa(struct rsa_st *rsa); -struct evp_pkey_st *_crypto_pk_get_evp_pkey(crypto_pk_t *env, +struct rsa_st *crypto_pk_get_rsa_(crypto_pk_t *env); +crypto_pk_t *crypto_new_pk_from_rsa_(struct rsa_st *rsa); +struct evp_pkey_st *crypto_pk_get_evp_pkey_(crypto_pk_t *env, int private); -struct dh_st *_crypto_dh_get_dh(crypto_dh_t *dh); +struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh); /* Prototypes for private functions only used by crypto.c and test.c*/ void add_spaces_to_fp(char *out, size_t outlen, const char *in); #endif diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c new file mode 100644 index 0000000000..88c723f37c --- /dev/null +++ b/src/common/crypto_curve25519.c @@ -0,0 +1,191 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* Wrapper code for a curve25519 implementation. */ + +#define CRYPTO_CURVE25519_PRIVATE +#include "orconfig.h" +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#include "crypto.h" +#include "crypto_curve25519.h" +#include "util.h" +#include "torlog.h" + +/* ============================== + Part 1: wrap a suitable curve25519 implementation as curve25519_impl + ============================== */ + +#ifdef USE_CURVE25519_DONNA +int curve25519_donna(uint8_t *mypublic, + const uint8_t *secret, const uint8_t *basepoint); +#endif +#ifdef USE_CURVE25519_NACL +#ifdef HAVE_CRYPTO_SCALARMULT_CURVE25519_H +#include <crypto_scalarmult_curve25519.h> +#elif defined(HAVE_NACL_CRYPTO_SCALARMULT_CURVE25519_H) +#include <nacl/crypto_scalarmult_curve25519.h> +#endif +#endif + +int +curve25519_impl(uint8_t *output, const uint8_t *secret, + const uint8_t *basepoint) +{ + uint8_t bp[CURVE25519_PUBKEY_LEN]; + int r; + memcpy(bp, basepoint, CURVE25519_PUBKEY_LEN); + /* Clear the high bit, in case our backend foolishly looks at it. */ + bp[31] &= 0x7f; +#ifdef USE_CURVE25519_DONNA + r = curve25519_donna(output, secret, bp); +#elif defined(USE_CURVE25519_NACL) + r = crypto_scalarmult_curve25519(output, secret, bp); +#else +#error "No implementation of curve25519 is available." +#endif + memwipe(bp, 0, sizeof(bp)); + return r; +} + +/* ============================== + Part 2: Wrap curve25519_impl with some convenience types and functions. + ============================== */ + +/** + * Return true iff a curve25519_public_key_t seems valid. (It's not necessary + * to see if the point is on the curve, since the twist is also secure, but we + * do need to make sure that it isn't the point at infinity.) */ +int +curve25519_public_key_is_ok(const curve25519_public_key_t *key) +{ + return !safe_mem_is_zero(key->public_key, CURVE25519_PUBKEY_LEN); +} + +/** Generate a new keypair and return the secret key. If <b>extra_strong</b> + * is true, this key is possibly going to get used more than once, so + * use a better-than-usual RNG. Return 0 on success, -1 on failure. */ +int +curve25519_secret_key_generate(curve25519_secret_key_t *key_out, + int extra_strong) +{ + uint8_t k_tmp[CURVE25519_SECKEY_LEN]; + + if (crypto_rand((char*)key_out->secret_key, CURVE25519_SECKEY_LEN) < 0) + return -1; + if (extra_strong && !crypto_strongest_rand(k_tmp, CURVE25519_SECKEY_LEN)) { + /* If they asked for extra-strong entropy and we have some, use it as an + * HMAC key to improve not-so-good entropy rather than using it directly, + * just in case the extra-strong entropy is less amazing than we hoped. */ + crypto_hmac_sha256((char *)key_out->secret_key, + (const char *)k_tmp, sizeof(k_tmp), + (const char *)key_out->secret_key, CURVE25519_SECKEY_LEN); + } + memwipe(k_tmp, 0, sizeof(k_tmp)); + key_out->secret_key[0] &= 248; + key_out->secret_key[31] &= 127; + key_out->secret_key[31] |= 64; + + return 0; +} + +void +curve25519_public_key_generate(curve25519_public_key_t *key_out, + const curve25519_secret_key_t *seckey) +{ + static const uint8_t basepoint[32] = {9}; + + curve25519_impl(key_out->public_key, seckey->secret_key, basepoint); +} + +int +curve25519_keypair_generate(curve25519_keypair_t *keypair_out, + int extra_strong) +{ + if (curve25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0) + return -1; + curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey); + return 0; +} + +int +curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair, + const char *fname, + const char *tag) +{ + char contents[32 + CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN]; + int r; + + memset(contents, 0, sizeof(contents)); + tor_snprintf(contents, sizeof(contents), "== c25519v1: %s ==", tag); + tor_assert(strlen(contents) <= 32); + memcpy(contents+32, keypair->seckey.secret_key, CURVE25519_SECKEY_LEN); + memcpy(contents+32+CURVE25519_SECKEY_LEN, + keypair->pubkey.public_key, CURVE25519_PUBKEY_LEN); + + r = write_bytes_to_file(fname, contents, sizeof(contents), 1); + + memwipe(contents, 0, sizeof(contents)); + return r; +} + +int +curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out, + char **tag_out, + const char *fname) +{ + char prefix[33]; + char *content; + struct stat st; + int r = -1; + + *tag_out = NULL; + + st.st_size = 0; + content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st); + if (! content) + goto end; + if (st.st_size != 32 + CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN) + goto end; + + memcpy(prefix, content, 32); + prefix[32] = '\0'; + if (strcmpstart(prefix, "== c25519v1: ") || + strcmpend(prefix, " ==")) + goto end; + + *tag_out = tor_strndup(prefix+strlen("== c25519v1: "), + strlen(prefix) - strlen("== c25519v1: ==")); + + memcpy(keypair_out->seckey.secret_key, content+32, CURVE25519_SECKEY_LEN); + curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey); + if (tor_memneq(keypair_out->pubkey.public_key, + content + 32 + CURVE25519_SECKEY_LEN, + CURVE25519_PUBKEY_LEN)) + goto end; + + r = 0; + + end: + if (content) { + memwipe(content, 0, (size_t) st.st_size); + tor_free(content); + } + if (r != 0) { + memset(keypair_out, 0, sizeof(*keypair_out)); + tor_free(*tag_out); + } + return r; +} + +/** Perform the curve25519 ECDH handshake with <b>skey</b> and <b>pkey</b>, + * writing CURVE25519_OUTPUT_LEN bytes of output into <b>output</b>. */ +void +curve25519_handshake(uint8_t *output, + const curve25519_secret_key_t *skey, + const curve25519_public_key_t *pkey) +{ + curve25519_impl(output, skey->secret_key, pkey->public_key); +} + diff --git a/src/common/crypto_curve25519.h b/src/common/crypto_curve25519.h new file mode 100644 index 0000000000..652f1883c6 --- /dev/null +++ b/src/common/crypto_curve25519.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_CRYPTO_CURVE25519_H +#define TOR_CRYPTO_CURVE25519_H + +#include "torint.h" + +/** Length of a curve25519 public key when encoded. */ +#define CURVE25519_PUBKEY_LEN 32 +/** Length of a curve25519 secret key when encoded. */ +#define CURVE25519_SECKEY_LEN 32 +/** Length of the result of a curve25519 handshake. */ +#define CURVE25519_OUTPUT_LEN 32 + +/** Wrapper type for a curve25519 public key */ +typedef struct curve25519_public_key_t { + uint8_t public_key[CURVE25519_PUBKEY_LEN]; +} curve25519_public_key_t; + +/** Wrapper type for a curve25519 secret key */ +typedef struct curve25519_secret_key_t { + uint8_t secret_key[CURVE25519_SECKEY_LEN]; +} curve25519_secret_key_t; + +/** A paired public and private key for curve25519. **/ +typedef struct curve25519_keypair_t { + curve25519_public_key_t pubkey; + curve25519_secret_key_t seckey; +} curve25519_keypair_t; + +#ifdef CURVE25519_ENABLED +int curve25519_public_key_is_ok(const curve25519_public_key_t *); + +int curve25519_secret_key_generate(curve25519_secret_key_t *key_out, + int extra_strong); +void curve25519_public_key_generate(curve25519_public_key_t *key_out, + const curve25519_secret_key_t *seckey); +int curve25519_keypair_generate(curve25519_keypair_t *keypair_out, + int extra_strong); + +void curve25519_handshake(uint8_t *output, + const curve25519_secret_key_t *, + const curve25519_public_key_t *); + +int curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair, + const char *fname, + const char *tag); + +int curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out, + char **tag_out, + const char *fname); + +#ifdef CRYPTO_CURVE25519_PRIVATE +int curve25519_impl(uint8_t *output, const uint8_t *secret, + const uint8_t *basepoint); +#endif +#endif + +#define CURVE25519_BASE64_PADDED_LEN 44 + +int curve25519_public_from_base64(curve25519_public_key_t *pkey, + const char *input); +int curve25519_public_to_base64(char *output, + const curve25519_public_key_t *pkey); + +#endif + diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c new file mode 100644 index 0000000000..93932f839c --- /dev/null +++ b/src/common/crypto_format.c @@ -0,0 +1,46 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* Formatting and parsing code for crypto-related data structures. */ + +#define CRYPTO_CURVE25519_PRIVATE +#include "orconfig.h" +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#include "crypto.h" +#include "crypto_curve25519.h" +#include "util.h" +#include "torlog.h" + +int +curve25519_public_to_base64(char *output, + const curve25519_public_key_t *pkey) +{ + char buf[128]; + base64_encode(buf, sizeof(buf), + (const char*)pkey->public_key, CURVE25519_PUBKEY_LEN); + buf[CURVE25519_BASE64_PADDED_LEN] = '\0'; + memcpy(output, buf, CURVE25519_BASE64_PADDED_LEN+1); + return 0; +} + +int +curve25519_public_from_base64(curve25519_public_key_t *pkey, + const char *input) +{ + size_t len = strlen(input); + if (len == CURVE25519_BASE64_PADDED_LEN - 1) { + /* not padded */ + return digest256_from_base64((char*)pkey->public_key, input); + } else if (len == CURVE25519_BASE64_PADDED_LEN) { + char buf[128]; + if (base64_decode(buf, sizeof(buf), input, len) != CURVE25519_PUBKEY_LEN) + return -1; + memcpy(pkey->public_key, buf, CURVE25519_PUBKEY_LEN); + return 0; + } else { + return -1; + } +} + diff --git a/src/common/di_ops.c b/src/common/di_ops.c index 7683c59dee..14a1443400 100644 --- a/src/common/di_ops.c +++ b/src/common/di_ops.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Tor Project, Inc. */ +/* Copyright (c) 2011-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,6 +8,8 @@ #include "orconfig.h" #include "di_ops.h" +#include "torlog.h" +#include "util.h" /** * Timing-safe version of memcmp. As memcmp, compare the <b>sz</b> bytes at @@ -123,7 +125,7 @@ tor_memeq(const void *a, const void *b, size_t sz) * * If any_difference != 0: * 0 < any_difference < 256, so - * 0 < any_difference - 1 < 255 + * 0 <= any_difference - 1 < 255 * (any_difference - 1) >> 8 == 0 * 1 & ((any_difference - 1) >> 8) == 0 */ @@ -131,3 +133,90 @@ tor_memeq(const void *a, const void *b, size_t sz) return 1 & ((any_difference - 1) >> 8); } +/* Implement di_digest256_map_t as a linked list of entries. */ +struct di_digest256_map_t { + struct di_digest256_map_t *next; + uint8_t key[32]; + void *val; +}; + +/** Release all storage held in <b>map</b>, calling free_fn on each value + * as we go. */ +void +dimap_free(di_digest256_map_t *map, dimap_free_fn free_fn) +{ + while (map) { + di_digest256_map_t *victim = map; + map = map->next; + if (free_fn) + free_fn(victim->val); + tor_free(victim); + } +} + +/** Adjust the map at *<b>map</b>, adding an entry for <b>key</b> -> + * <b>val</b>, where <b>key</b> is a DIGEST256_LEN-byte key. + * + * The caller MUST NOT add a key that already appears in the map. + */ +void +dimap_add_entry(di_digest256_map_t **map, + const uint8_t *key, void *val) +{ + di_digest256_map_t *new_ent; + { + void *old_val = dimap_search(*map, key, NULL); + tor_assert(! old_val); + tor_assert(val); + } + new_ent = tor_malloc_zero(sizeof(di_digest256_map_t)); + new_ent->next = *map; + memcpy(new_ent->key, key, 32); + new_ent->val = val; + *map = new_ent; +} + +/** Search the map at <b>map</b> for an entry whose key is <b>key</b> (a + * DIGEST256_LEN-byte key) returning the corresponding value if we found one, + * and returning <b>dflt_val</b> if the key wasn't found. + * + * This operation takes an amount of time dependent only on the length of + * <b>map</b>, not on the position or presence of <b>key</b> within <b>map</b>. + */ +void * +dimap_search(const di_digest256_map_t *map, const uint8_t *key, + void *dflt_val) +{ + uintptr_t result = (uintptr_t)dflt_val; + + while (map) { + uintptr_t r = (uintptr_t) tor_memeq(map->key, key, 32); + r -= 1; /* Now r is (uintptr_t)-1 if memeq returned false, and + * 0 if memeq returned true. */ + + result &= r; + result |= ((uintptr_t)(map->val)) & ~r; + + map = map->next; + } + + return (void *)result; +} + +/** + * Return true iff the <b>sz</b> bytes at <b>mem</b> are all zero. Runs in + * time independent of the contents of <b>mem</b>. + */ +int +safe_mem_is_zero(const void *mem, size_t sz) +{ + uint32_t total = 0; + const uint8_t *ptr = mem; + + while (sz--) { + total |= *ptr++; + } + + return 1 & ((total - 1) >> 8); +} + diff --git a/src/common/di_ops.h b/src/common/di_ops.h index 8f0bb698f9..d93534b69b 100644 --- a/src/common/di_ops.h +++ b/src/common/di_ops.h @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -27,5 +27,21 @@ int tor_memeq(const void *a, const void *b, size_t sz); #define fast_memeq(a,b,c) (0==memcmp((a),(b),(c))) #define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c))) +int safe_mem_is_zero(const void *mem, size_t sz); + +/** A type for a map from DIGEST256_LEN-byte blobs to void*, such that + * data lookups take an amount of time proportional only to the size + * of the map, and not to the position or presence of the item in the map. + * + * Not efficient for large maps! */ +typedef struct di_digest256_map_t di_digest256_map_t; +typedef void (*dimap_free_fn)(void *); + +void dimap_free(di_digest256_map_t *map, dimap_free_fn free_fn); +void dimap_add_entry(di_digest256_map_t **map, + const uint8_t *key, void *val); +void *dimap_search(const di_digest256_map_t *map, const uint8_t *key, + void *dflt_val); + #endif diff --git a/src/common/gen_server_ciphers.py b/src/common/gen_server_ciphers.py new file mode 100755 index 0000000000..97ed9d0469 --- /dev/null +++ b/src/common/gen_server_ciphers.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# Copyright 2014, The Tor Project, Inc +# See LICENSE for licensing information + +# This script parses openssl headers to find ciphersuite names, determines +# which ones we should be willing to use as a server, and sorts them according +# to preference rules. +# +# Run it on all the files in your openssl include directory. + +import re +import sys + +EPHEMERAL_INDICATORS = [ "_EDH_", "_DHE_", "_ECDHE_" ] +BAD_STUFF = [ "_DES_40_", "MD5", "_RC4_", "_DES_64_", + "_SEED_", "_CAMELLIA_", "_NULL" ] + +# these never get #ifdeffed. +MANDATORY = [ + "TLS1_TXT_DHE_RSA_WITH_AES_256_SHA", + "TLS1_TXT_DHE_RSA_WITH_AES_128_SHA", + "SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA", +] + +def find_ciphers(filename): + with open(filename) as f: + for line in f: + m = re.search(r'(?:SSL3|TLS1)_TXT_\w+', line) + if m: + yield m.group(0) + +def usable_cipher(ciph): + ephemeral = False + for e in EPHEMERAL_INDICATORS: + if e in ciph: + ephemeral = True + if not ephemeral: + return False + + if "_RSA_" not in ciph: + return False + + for b in BAD_STUFF: + if b in ciph: + return False + return True + +# All fields we sort on, in order of priority. +FIELDS = [ 'cipher', 'fwsec', 'mode', 'digest', 'bitlength' ] +# Map from sorted fields to recognized value in descending order of goodness +FIELD_VALS = { 'cipher' : [ 'AES', 'DES'], + 'fwsec' : [ 'ECDHE', 'DHE' ], + 'mode' : [ 'GCM', 'CBC' ], + 'digest' : [ 'SHA384', 'SHA256', 'SHA' ], + 'bitlength' : [ '256', '128', '192' ], +} + +class Ciphersuite(object): + def __init__(self, name, fwsec, cipher, bitlength, mode, digest): + self.name = name + self.fwsec = fwsec + self.cipher = cipher + self.bitlength = bitlength + self.mode = mode + self.digest = digest + + for f in FIELDS: + assert(getattr(self, f) in FIELD_VALS[f]) + + def sort_key(self): + return tuple(FIELD_VALS[f].index(getattr(self,f)) for f in FIELDS) + + +def parse_cipher(ciph): + m = re.match('(?:TLS1|SSL3)_TXT_(EDH|DHE|ECDHE)_RSA(?:_WITH)?_(AES|DES)_(256|128|192)(|_CBC|_CBC3|_GCM)_(SHA|SHA256|SHA384)$', ciph) + + if not m: + print "/* Couldn't parse %s ! */"%ciph + return None + + fwsec, cipher, bits, mode, digest = m.groups() + if fwsec == 'EDH': + fwsec = 'DHE' + + if mode in [ '_CBC3', '_CBC', '' ]: + mode = 'CBC' + elif mode == '_GCM': + mode = 'GCM' + + return Ciphersuite(ciph, fwsec, cipher, bits, mode, digest) + +ALL_CIPHERS = [] + +for fname in sys.argv[1:]: + ALL_CIPHERS += (parse_cipher(c) + for c in find_ciphers(fname) + if usable_cipher(c) ) + +ALL_CIPHERS.sort(key=Ciphersuite.sort_key) + +for c in ALL_CIPHERS: + if c is ALL_CIPHERS[-1]: + colon = ';' + else: + colon = ' ":"' + + if c.name in MANDATORY: + print " /* Required */" + print ' %s%s'%(c.name,colon) + else: + print "#ifdef %s"%c.name + print ' %s%s'%(c.name,colon) + print "#endif" + + diff --git a/src/common/get_mozilla_ciphers.py b/src/common/get_mozilla_ciphers.py index c7e9a84a0e..0636eb3658 100644 --- a/src/common/get_mozilla_ciphers.py +++ b/src/common/get_mozilla_ciphers.py @@ -41,12 +41,12 @@ fileA = open(ff('security/manager/ssl/src/nsNSSComponent.cpp'),'r') inCipherSection = False cipherLines = [] for line in fileA: - if line.startswith('static CipherPref CipherPrefs'): + if line.startswith('static const CipherPref sCipherPrefs[]'): # Get the starting boundary of the Cipher Preferences inCipherSection = True elif inCipherSection: line = line.strip() - if line.startswith('{NULL, 0}'): + if line.startswith('{ nullptr, 0}'): # At the ending boundary of the Cipher Prefs break else: @@ -56,12 +56,30 @@ fileA.close() # Parse the lines and put them into a dict ciphers = {} cipher_pref = {} +key_pending = None for line in cipherLines: - m = re.search(r'^{\s*\"([^\"]+)\",\s*(\S*)\s*}', line) + m = re.search(r'^{\s*\"([^\"]+)\",\s*(\S+)\s*(?:,\s*(true|false))?\s*}', line) if m: - key,value = m.groups() - ciphers[key] = value - cipher_pref[value] = key + assert not key_pending + key,value,enabled = m.groups() + if enabled == 'true': + ciphers[key] = value + cipher_pref[value] = key + continue + m = re.search(r'^{\s*\"([^\"]+)\",', line) + if m: + assert not key_pending + key_pending = m.group(1) + continue + m = re.search(r'^\s*(\S+)(?:,\s*(true|false))?\s*}', line) + if m: + assert key_pending + key = key_pending + value,enabled = m.groups() + key_pending = None + if enabled == 'true': + ciphers[key] = value + cipher_pref[value] = key #### # Now find the correct order for the ciphers diff --git a/src/common/include.am b/src/common/include.am new file mode 100644 index 0000000000..b796ebfae8 --- /dev/null +++ b/src/common/include.am @@ -0,0 +1,96 @@ + +noinst_LIBRARIES+= src/common/libor.a src/common/libor-crypto.a src/common/libor-event.a + +EXTRA_DIST+= \ + src/common/common_sha1.i \ + src/common/Makefile.nmake + +#CFLAGS = -Wall -Wpointer-arith -O2 +AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common + +if USE_OPENBSD_MALLOC +libor_extra_source=src/ext/OpenBSD_malloc_Linux.c +else +libor_extra_source= +endif + +if BUILD_CURVE25519_DONNA +src_common_libcurve25519_donna_a_SOURCES=\ + src/ext/curve25519_donna/curve25519-donna.c +noinst_LIBRARIES+=src/common/libcurve25519_donna.a +LIBDONNA=src/common/libcurve25519_donna.a +else +if BUILD_CURVE25519_DONNA_C64 +src_common_libcurve25519_donna_a_SOURCES=\ + src/ext/curve25519_donna/curve25519-donna-c64.c +noinst_LIBRARIES+=src/common/libcurve25519_donna.a +LIBDONNA=src/common/libcurve25519_donna.a +else +LIBDONNA= +endif +endif + +src_common_libcurve25519_donna_a_CFLAGS = + +if CURVE25519_ENABLED +libcrypto_extra_source=src/common/crypto_curve25519.c +endif + +src_common_libor_a_SOURCES = \ + src/common/address.c \ + src/common/compat.c \ + src/common/container.c \ + src/common/di_ops.c \ + src/common/log.c \ + src/common/memarea.c \ + src/common/mempool.c \ + src/common/procmon.c \ + src/common/util.c \ + src/common/util_codedigest.c \ + $(libor_extra_source) + +src_common_libor_crypto_a_SOURCES = \ + src/common/aes.c \ + src/common/crypto.c \ + src/common/crypto_format.c \ + src/common/torgzip.c \ + src/common/tortls.c \ + $(libcrypto_extra_source) + +src_common_libor_event_a_SOURCES = src/common/compat_libevent.c + +COMMONHEADERS = \ + src/common/address.h \ + src/common/aes.h \ + src/common/ciphers.inc \ + src/common/compat.h \ + src/common/compat_libevent.h \ + src/common/container.h \ + src/common/crypto.h \ + src/common/crypto_curve25519.h \ + src/common/di_ops.h \ + src/common/memarea.h \ + src/common/mempool.h \ + src/common/procmon.h \ + src/common/torgzip.h \ + src/common/torint.h \ + src/common/torlog.h \ + src/common/tortls.h \ + src/common/util.h + +noinst_HEADERS+= $(COMMONHEADERS) + +DISTCLEANFILES+= src/common/common_sha1.i + +src/common/common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(COMMONHEADERS) + $(AM_V_GEN)if test "@SHA1SUM@" != none; then \ + (cd "$(srcdir)" && "@SHA1SUM@" $(src_common_libor_SOURCES) $(src_common_libor_crypto_a_SOURCES) $(COMMONHEADERS)) | "@SED@" -n 's/^\(.*\)$$/"\1\\n"/p' > $@; \ + elif test "@OPENSSL@" != none; then \ + (cd "$(srcdir)" && "@OPENSSL@" sha1 $(src_common_libor_SOURCES) $(src_Common_libor_crypto_a_SOURCES) $(COMMONHEADERS)) | "@SED@" -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > $@; \ + else \ + rm $@; \ + touch $@; \ + fi + +src/common/util_codedigest.o: src/common/common_sha1.i + diff --git a/src/common/log.c b/src/common/log.c index 5e2e6b5b50..e196a11287 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001, Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -131,7 +131,7 @@ static smartlist_t *pending_cb_messages = NULL; /** What's the lowest log level anybody cares about? Checking this lets us * bail out early from log_debug if we aren't debugging. */ -int _log_global_min_severity = LOG_NOTICE; +int log_global_min_severity_ = LOG_NOTICE; static void delete_log(logfile_t *victim); static void close_log(logfile_t *victim); @@ -140,11 +140,12 @@ static char *domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen); static INLINE char *format_msg(char *buf, size_t buf_len, log_domain_mask_t domain, int severity, const char *funcname, + const char *suffix, const char *format, va_list ap, size_t *msg_len_out) - CHECK_PRINTF(6,0); + CHECK_PRINTF(7,0); static void logv(int severity, log_domain_mask_t domain, const char *funcname, - const char *format, va_list ap) - CHECK_PRINTF(4,0); + const char *suffix, const char *format, va_list ap) + CHECK_PRINTF(5,0); /** Name of the application: used to generate the message we write at the * start of each new log. */ @@ -177,7 +178,7 @@ set_log_time_granularity(int granularity_msec) * <b>buf_len</b> character buffer in <b>buf</b>. */ static INLINE size_t -_log_prefix(char *buf, size_t buf_len, int severity) +log_prefix_(char *buf, size_t buf_len, int severity) { time_t t; struct timeval now; @@ -230,7 +231,7 @@ log_tor_version(logfile_t *lf, int reset) /* We are resetting, but we aren't at the start of the file; no * need to log again. */ return 0; - n = _log_prefix(buf, sizeof(buf), LOG_NOTICE); + n = log_prefix_(buf, sizeof(buf), LOG_NOTICE); if (appname) { tor_snprintf(buf+n, sizeof(buf)-n, "%s opening %slog file.\n", appname, is_new?"new ":""); @@ -251,6 +252,7 @@ log_tor_version(logfile_t *lf, int reset) static INLINE char * format_msg(char *buf, size_t buf_len, log_domain_mask_t domain, int severity, const char *funcname, + const char *suffix, const char *format, va_list ap, size_t *msg_len_out) { size_t n; @@ -262,7 +264,7 @@ format_msg(char *buf, size_t buf_len, buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */ buf_end = buf+buf_len; /* point *after* the last char we can write to */ - n = _log_prefix(buf, buf_len, severity); + n = log_prefix_(buf, buf_len, severity); end_of_prefix = buf+n; if (log_domains_are_logged) { @@ -312,6 +314,13 @@ format_msg(char *buf, size_t buf_len, n = buf_len; } else { n += r; + if (suffix) { + size_t suffix_len = strlen(suffix); + if (buf_len-n >= suffix_len) { + memcpy(buf+n, suffix, suffix_len); + n += suffix_len; + } + } } buf[n]='\n'; buf[n+1]='\0'; @@ -325,7 +334,7 @@ format_msg(char *buf, size_t buf_len, */ static void logv(int severity, log_domain_mask_t domain, const char *funcname, - const char *format, va_list ap) + const char *suffix, const char *format, va_list ap) { char buf[10024]; size_t msg_len = 0; @@ -361,8 +370,8 @@ logv(int severity, log_domain_mask_t domain, const char *funcname, if (!formatted) { end_of_prefix = - format_msg(buf, sizeof(buf), domain, severity, funcname, format, ap, - &msg_len); + format_msg(buf, sizeof(buf), domain, severity, funcname, suffix, + format, ap, &msg_len); formatted = 1; } @@ -423,10 +432,10 @@ void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (severity > _log_global_min_severity) + if (severity > log_global_min_severity_) return; va_start(ap,format); - logv(severity, domain, NULL, format, ap); + logv(severity, domain, NULL, NULL, format, ap); va_end(ap); } @@ -436,89 +445,121 @@ tor_log(int severity, log_domain_mask_t domain, const char *format, ...) * variadic macros. All arguments are as for log_fn, except for * <b>fn</b>, which is the name of the calling functions. */ void -_log_fn(int severity, log_domain_mask_t domain, const char *fn, +log_fn_(int severity, log_domain_mask_t domain, const char *fn, const char *format, ...) { va_list ap; - if (severity > _log_global_min_severity) + if (severity > log_global_min_severity_) return; va_start(ap,format); - logv(severity, domain, fn, format, ap); + logv(severity, domain, fn, NULL, format, ap); + va_end(ap); +} +void +log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain, + const char *fn, const char *format, ...) +{ + va_list ap; + char *m; + if (severity > log_global_min_severity_) + return; + m = rate_limit_log(ratelim, approx_time()); + if (m == NULL) + return; + va_start(ap, format); + logv(severity, domain, fn, m, format, ap); va_end(ap); + tor_free(m); } #else /** @{ */ /** Variant implementation of log_fn, log_debug, log_info,... for C compilers * without variadic macros. In this case, the calling function sets - * _log_fn_function_name to the name of the function, then invokes the - * appropriate _log_fn, _log_debug, etc. */ -const char *_log_fn_function_name=NULL; + * log_fn_function_name_ to the name of the function, then invokes the + * appropriate log_fn_, log_debug_, etc. */ +const char *log_fn_function_name_=NULL; void -_log_fn(int severity, log_domain_mask_t domain, const char *format, ...) +log_fn_(int severity, log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (severity > _log_global_min_severity) + if (severity > log_global_min_severity_) return; va_start(ap,format); - logv(severity, domain, _log_fn_function_name, format, ap); + logv(severity, domain, log_fn_function_name_, NULL, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_debug(log_domain_mask_t domain, const char *format, ...) +log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain, + const char *format, ...) +{ + va_list ap; + char *m; + if (severity > log_global_min_severity_) + return; + m = rate_limit_log(ratelim, approx_time()); + if (m == NULL) + return; + va_start(ap, format); + logv(severity, domain, log_fn_function_name_, m, format, ap); + va_end(ap); + tor_free(m); +} +void +log_debug_(log_domain_mask_t domain, const char *format, ...) { va_list ap; /* For GCC we do this check in the macro. */ - if (PREDICT_LIKELY(LOG_DEBUG > _log_global_min_severity)) + if (PREDICT_LIKELY(LOG_DEBUG > log_global_min_severity_)) return; va_start(ap,format); - logv(LOG_DEBUG, domain, _log_fn_function_name, format, ap); + logv(LOG_DEBUG, domain, log_fn_function_name_, NULL, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_info(log_domain_mask_t domain, const char *format, ...) +log_info_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_INFO > _log_global_min_severity) + if (LOG_INFO > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_INFO, domain, _log_fn_function_name, format, ap); + logv(LOG_INFO, domain, log_fn_function_name_, NULL, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_notice(log_domain_mask_t domain, const char *format, ...) +log_notice_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_NOTICE > _log_global_min_severity) + if (LOG_NOTICE > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_NOTICE, domain, _log_fn_function_name, format, ap); + logv(LOG_NOTICE, domain, log_fn_function_name_, NULL, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_warn(log_domain_mask_t domain, const char *format, ...) +log_warn_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_WARN > _log_global_min_severity) + if (LOG_WARN > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_WARN, domain, _log_fn_function_name, format, ap); + logv(LOG_WARN, domain, log_fn_function_name_, NULL, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } void -_log_err(log_domain_mask_t domain, const char *format, ...) +log_err_(log_domain_mask_t domain, const char *format, ...) { va_list ap; - if (LOG_ERR > _log_global_min_severity) + if (LOG_ERR > log_global_min_severity_) return; va_start(ap,format); - logv(LOG_ERR, domain, _log_fn_function_name, format, ap); + logv(LOG_ERR, domain, log_fn_function_name_, NULL, format, ap); va_end(ap); - _log_fn_function_name = NULL; + log_fn_function_name_ = NULL; } /** @} */ #endif @@ -638,7 +679,7 @@ add_stream_log_impl(const log_severity_list_t *severity, lf->next = logfiles; logfiles = lf; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); } /** Add a log handler named <b>name</b> to send all messages in <b>severity</b> @@ -706,7 +747,7 @@ add_callback_log(const log_severity_list_t *severity, log_callback cb) LOCK_LOGS(); logfiles = lf; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); return 0; } @@ -726,7 +767,7 @@ change_callback_log_severity(int loglevelMin, int loglevelMax, memcpy(lf->severities, &severities, sizeof(severities)); } } - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); } @@ -792,7 +833,7 @@ close_temp_logs(void) } } - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); } @@ -833,14 +874,16 @@ add_file_log(const log_severity_list_t *severity, const char *filename) fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644); if (fd<0) return -1; - if (tor_fd_seekend(fd)<0) + if (tor_fd_seekend(fd)<0) { + close(fd); return -1; + } LOCK_LOGS(); add_stream_log_impl(severity, filename, fd); logfiles->needs_close = 1; lf = logfiles; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); if (log_tor_version(lf, 0) < 0) { delete_log(lf); @@ -871,7 +914,7 @@ add_syslog_log(const log_severity_list_t *severity) LOCK_LOGS(); lf->next = logfiles; logfiles = lf; - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); return 0; } @@ -907,7 +950,7 @@ log_level_to_string(int level) static const char *domain_list[] = { "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM", "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV", - "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", NULL + "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL", NULL }; /** Return a bitmask for the log domain for which <b>domain</b> is the name, @@ -1106,7 +1149,7 @@ switch_logs_debug(void) for (i = LOG_DEBUG; i >= LOG_ERR; --i) lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u; } - _log_global_min_severity = get_min_log_level(); + log_global_min_severity_ = get_min_log_level(); UNLOCK_LOGS(); } diff --git a/src/common/memarea.c b/src/common/memarea.c index 07bd593cc9..0ae0ccca1d 100644 --- a/src/common/memarea.c +++ b/src/common/memarea.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2012, The Tor Project, Inc. */ +/* Copyright (c) 2008-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** \file memarea.c @@ -77,7 +77,7 @@ typedef struct memarea_chunk_t { * full. */ union { char mem[1]; /**< Memory space in this chunk. */ - void *_void_for_alignment; /**< Dummy; used to make sure mem is aligned. */ + void *void_for_alignment_; /**< Dummy; used to make sure mem is aligned. */ } u; } memarea_chunk_t; @@ -118,7 +118,7 @@ alloc_chunk(size_t sz, int freelist_ok) size_t chunk_size = freelist_ok ? CHUNK_SIZE : sz; memarea_chunk_t *res; chunk_size += SENTINEL_LEN; - res = tor_malloc_roundup(&chunk_size); + res = tor_malloc(chunk_size); res->next_chunk = NULL; res->mem_size = chunk_size - CHUNK_HEADER_SIZE - SENTINEL_LEN; res->next_mem = res->u.mem; diff --git a/src/common/memarea.h b/src/common/memarea.h index b3c76d8d0c..8b88585d35 100644 --- a/src/common/memarea.h +++ b/src/common/memarea.h @@ -1,9 +1,9 @@ -/* Copyright (c) 2008-2012, The Tor Project, Inc. */ +/* Copyright (c) 2008-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Tor dependencies */ -#ifndef _TOR_MEMAREA_H -#define _TOR_MEMAREA_H +#ifndef TOR_MEMAREA_H +#define TOR_MEMAREA_H typedef struct memarea_t memarea_t; diff --git a/src/common/mempool.c b/src/common/mempool.c index 637f081c88..4389888760 100644 --- a/src/common/mempool.c +++ b/src/common/mempool.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2012, The Tor Project, Inc. */ +/* Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #if 1 /* Tor dependencies */ @@ -71,7 +71,6 @@ #define ASSERT(x) tor_assert(x) #undef ALLOC_CAN_RETURN_NULL #define TOR -//#define ALLOC_ROUNDUP(p) tor_malloc_roundup(p) /* End Tor dependencies */ #else /* If you're not building this as part of Tor, you'll want to define the @@ -115,7 +114,7 @@ struct mp_allocated_t { * (Not actual size.) */ char mem[1]; /** An extra element to the union to insure correct alignment. */ - ALIGNMENT_TYPE _dummy; + ALIGNMENT_TYPE dummy_; } u; }; @@ -166,25 +165,16 @@ static mp_chunk_t * mp_chunk_new(mp_pool_t *pool) { size_t sz = pool->new_chunk_capacity * pool->item_alloc_size; -#ifdef ALLOC_ROUNDUP - size_t alloc_size = CHUNK_OVERHEAD + sz; - mp_chunk_t *chunk = ALLOC_ROUNDUP(&alloc_size); -#else mp_chunk_t *chunk = ALLOC(CHUNK_OVERHEAD + sz); -#endif + #ifdef MEMPOOL_STATS ++pool->total_chunks_allocated; #endif CHECK_ALLOC(chunk); memset(chunk, 0, sizeof(mp_chunk_t)); /* Doesn't clear the whole thing. */ chunk->magic = MP_CHUNK_MAGIC; -#ifdef ALLOC_ROUNDUP - chunk->mem_size = alloc_size - CHUNK_OVERHEAD; - chunk->capacity = chunk->mem_size / pool->item_alloc_size; -#else chunk->capacity = pool->new_chunk_capacity; chunk->mem_size = sz; -#endif chunk->next_mem = chunk->mem; chunk->pool = pool; return chunk; diff --git a/src/common/mempool.h b/src/common/mempool.h index bc424acdeb..0fc1e4c676 100644 --- a/src/common/mempool.h +++ b/src/common/mempool.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2012, The Tor Project, Inc. */ +/* Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -6,8 +6,8 @@ * \brief Headers for mempool.c **/ -#ifndef _TOR_MEMPOOL_H -#define _TOR_MEMPOOL_H +#ifndef TOR_MEMPOOL_H +#define TOR_MEMPOOL_H /** A memory pool is a context in which a large number of fixed-sized * objects can be allocated efficiently. See mempool.c for implementation diff --git a/src/common/procmon.c b/src/common/procmon.c index 36b1a48553..0a49689e3a 100644 --- a/src/common/procmon.c +++ b/src/common/procmon.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Tor Project, Inc. */ +/* Copyright (c) 2011-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -25,9 +25,21 @@ #ifdef _WIN32 #include <windows.h> +#endif -/* Windows does not define pid_t, but _getpid() returns an int. */ +#if (0 == SIZEOF_PID_T) && defined(_WIN32) +/* Windows does not define pid_t sometimes, but _getpid() returns an int. + * Everybody else needs to have a pid_t. */ typedef int pid_t; +#define PID_T_FORMAT "%d" +#elif (SIZEOF_PID_T == SIZEOF_INT) || (SIZEOF_PID_T == SIZEOF_SHORT) +#define PID_T_FORMAT "%d" +#elif (SIZEOF_PID_T == SIZEOF_LONG) +#define PID_T_FORMAT "%ld" +#elif (SIZEOF_PID_T == SIZEOF_INT64_T) +#define PID_T_FORMAT I64_FORMAT +#else +#error Unknown: SIZEOF_PID_T #endif /* Define to 1 if process-termination monitors on this OS and Libevent @@ -204,15 +216,17 @@ tor_process_monitor_new(struct event_base *base, if (procmon->hproc != NULL) { procmon->poll_hproc = 1; - log_info(procmon->log_domain, "Successfully opened handle to process %d; " + log_info(procmon->log_domain, "Successfully opened handle to process " + PID_T_FORMAT"; " "monitoring it.", - (int)(procmon->pid)); + procmon->pid); } else { /* If we couldn't get a handle to the process, we'll try again the * first time we poll. */ - log_info(procmon->log_domain, "Failed to open handle to process %d; will " + log_info(procmon->log_domain, "Failed to open handle to process " + PID_T_FORMAT"; will " "try again later.", - (int)(procmon->pid)); + procmon->pid); } #endif @@ -257,7 +271,8 @@ tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2, if (!GetExitCodeProcess(procmon->hproc, &exit_code)) { char *errmsg = format_win32_error(GetLastError()); log_warn(procmon->log_domain, "Error \"%s\" occurred while polling " - "handle for monitored process %d; assuming it's dead.", + "handle for monitored process "PID_T_FORMAT"; assuming " + "it's dead.", errmsg, procmon->pid); tor_free(errmsg); its_dead_jim = 1; @@ -273,7 +288,7 @@ tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2, if (procmon->hproc != NULL) { log_info(procmon->log_domain, "Successfully opened handle to monitored " - "process %d.", + "process "PID_T_FORMAT".", procmon->pid); its_dead_jim = 0; procmon->poll_hproc = 1; @@ -292,8 +307,8 @@ tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2, if (!its_dead_jim) log_info(procmon->log_domain, "Failed to open handle to monitored " - "process %d, and error code %lu (%s) is not 'invalid " - "parameter' -- assuming the process is still alive.", + "process "PID_T_FORMAT", and error code %lu (%s) is not " + "'invalid parameter' -- assuming the process is still alive.", procmon->pid, err_code, errmsg); @@ -306,9 +321,9 @@ tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2, its_dead_jim = its_dead_jim && (errno == ESRCH); #endif - log(its_dead_jim ? LOG_NOTICE : LOG_INFO, - procmon->log_domain, "Monitored process %d is %s.", - (int)procmon->pid, + tor_log(its_dead_jim ? LOG_NOTICE : LOG_INFO, + procmon->log_domain, "Monitored process "PID_T_FORMAT" is %s.", + procmon->pid, its_dead_jim ? "dead" : "still alive"); if (its_dead_jim) { diff --git a/src/common/procmon.h b/src/common/procmon.h index 88d64d6a15..b9388e2e90 100644 --- a/src/common/procmon.h +++ b/src/common/procmon.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Tor Project, Inc. */ +/* Copyright (c) 2011-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/common/sha256.c b/src/common/sha256.c deleted file mode 100644 index 813c68d2a3..0000000000 --- a/src/common/sha256.c +++ /dev/null @@ -1,331 +0,0 @@ -/* Copyright (c) 2009-2012, 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/torgzip.c b/src/common/torgzip.c index da4136228e..4328c63c8b 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -1,6 +1,6 @@ /* Copyright (c) 2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/common/torgzip.h b/src/common/torgzip.h index d3ded81f9c..be1016445b 100644 --- a/src/common/torgzip.h +++ b/src/common/torgzip.h @@ -1,6 +1,6 @@ /* Copyright (c) 2003, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,8 +8,8 @@ * \brief Headers for torgzip.h **/ -#ifndef _TOR_TORGZIP_H -#define _TOR_TORGZIP_H +#ifndef TOR_TORGZIP_H +#define TOR_TORGZIP_H /** Enumeration of what kind of compression to use. Only ZLIB_METHOD is * guaranteed to be supported by the compress/uncompress functions here; diff --git a/src/common/torint.h b/src/common/torint.h index 8771802d70..a993d7649a 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -1,6 +1,6 @@ /* Copyright (c) 2003, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,8 +8,8 @@ * \brief Header file to define uint32_t and friends **/ -#ifndef _TOR_TORINT_H -#define _TOR_TORINT_H +#ifndef TOR_TORINT_H +#define TOR_TORINT_H #include "orconfig.h" @@ -214,16 +214,20 @@ typedef int32_t ssize_t; #if (SIZEOF_VOID_P > 4 && SIZEOF_VOID_P <= 8) #ifndef HAVE_INTPTR_T typedef int64_t intptr_t; +#define SIZEOF_INTPTR_T 8 #endif #ifndef HAVE_UINTPTR_T typedef uint64_t uintptr_t; +#define SIZEOF_UINTPTR_T 8 #endif #elif (SIZEOF_VOID_P > 2 && SIZEOF_VOID_P <= 4) #ifndef HAVE_INTPTR_T typedef int32_t intptr_t; +#define SIZEOF_INTPTR_T 4 #endif #ifndef HAVE_UINTPTR_T typedef uint32_t uintptr_t; +#define SIZEOF_UINTPTR_T 4 #endif #else #error "void * is either >8 bytes or <= 2. In either case, I am confused." diff --git a/src/common/torlog.h b/src/common/torlog.h index 28890a44af..8675d7b6e7 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001, Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,7 +10,7 @@ * \brief Headers for log.c **/ -#ifndef _TOR_LOG_H +#ifndef TOR_TORLOG_H #include "compat.h" @@ -94,8 +94,10 @@ #define LD_HANDSHAKE (1u<<19) /** Heartbeat messages */ #define LD_HEARTBEAT (1u<<20) +/** Abstract channel_t code */ +#define LD_CHANNEL (1u<<21) /** Number of logging domains in the code. */ -#define N_LOGGING_DOMAINS 21 +#define N_LOGGING_DOMAINS 22 /** This log message is not safe to send to a callback-based logger * immediately. Used as a flag, not a log domain. */ @@ -151,66 +153,80 @@ void set_log_time_granularity(int granularity_msec); void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) CHECK_PRINTF(3,4); -#define log tor_log /* hack it so we don't conflict with log() as much */ #if defined(__GNUC__) || defined(RUNNING_DOXYGEN) -extern int _log_global_min_severity; +extern int log_global_min_severity_; -void _log_fn(int severity, log_domain_mask_t domain, +void log_fn_(int severity, log_domain_mask_t domain, const char *funcname, const char *format, ...) CHECK_PRINTF(4,5); +struct ratelim_t; +void log_fn_ratelim_(struct ratelim_t *ratelim, int severity, + log_domain_mask_t domain, const char *funcname, + const char *format, ...) + CHECK_PRINTF(5,6); /** Log a message at level <b>severity</b>, using a pretty-printed version * of the current function name. */ #define log_fn(severity, domain, args...) \ - _log_fn(severity, domain, __PRETTY_FUNCTION__, args) + log_fn_(severity, domain, __PRETTY_FUNCTION__, args) +/** As log_fn, but use <b>ratelim</b> (an instance of ratelim_t) to control + * the frequency at which messages can appear. + */ +#define log_fn_ratelim(ratelim, severity, domain, args...) \ + log_fn_ratelim_(ratelim, severity, domain, __PRETTY_FUNCTION__, args) #define log_debug(domain, args...) \ STMT_BEGIN \ - if (PREDICT_UNLIKELY(_log_global_min_severity == LOG_DEBUG)) \ - _log_fn(LOG_DEBUG, domain, __PRETTY_FUNCTION__, args); \ + if (PREDICT_UNLIKELY(log_global_min_severity_ == LOG_DEBUG)) \ + log_fn_(LOG_DEBUG, domain, __PRETTY_FUNCTION__, args); \ STMT_END #define log_info(domain, args...) \ - _log_fn(LOG_INFO, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_INFO, domain, __PRETTY_FUNCTION__, args) #define log_notice(domain, args...) \ - _log_fn(LOG_NOTICE, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_NOTICE, domain, __PRETTY_FUNCTION__, args) #define log_warn(domain, args...) \ - _log_fn(LOG_WARN, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_WARN, domain, __PRETTY_FUNCTION__, args) #define log_err(domain, args...) \ - _log_fn(LOG_ERR, domain, __PRETTY_FUNCTION__, args) + log_fn_(LOG_ERR, domain, __PRETTY_FUNCTION__, args) #else /* ! defined(__GNUC__) */ -void _log_fn(int severity, log_domain_mask_t domain, const char *format, ...); -void _log_debug(log_domain_mask_t domain, const char *format, ...); -void _log_info(log_domain_mask_t domain, const char *format, ...); -void _log_notice(log_domain_mask_t domain, const char *format, ...); -void _log_warn(log_domain_mask_t domain, const char *format, ...); -void _log_err(log_domain_mask_t domain, const char *format, ...); +void log_fn_(int severity, log_domain_mask_t domain, const char *format, ...); +struct ratelim_t; +void log_fn_ratelim_(struct ratelim_t *ratelim, int severity, + log_domain_mask_t domain, const char *format, ...); +void log_debug_(log_domain_mask_t domain, const char *format, ...); +void log_info_(log_domain_mask_t domain, const char *format, ...); +void log_notice_(log_domain_mask_t domain, const char *format, ...); +void log_warn_(log_domain_mask_t domain, const char *format, ...); +void log_err_(log_domain_mask_t domain, const char *format, ...); #if defined(_MSC_VER) && _MSC_VER < 1300 /* MSVC 6 and earlier don't have __func__, or even __LINE__. */ -#define log_fn _log_fn -#define log_debug _log_debug -#define log_info _log_info -#define log_notice _log_notice -#define log_warn _log_warn -#define log_err _log_err +#define log_fn log_fn_ +#define log_fn_ratelim log_fn_ratelim_ +#define log_debug log_debug_ +#define log_info log_info_ +#define log_notice log_notice_ +#define log_warn log_warn_ +#define log_err log_err_ #else /* We don't have GCC's varargs macros, so use a global variable to pass the * function name to log_fn */ -extern const char *_log_fn_function_name; +extern const char *log_fn_function_name_; /* We abuse the comma operator here, since we can't use the standard * do {...} while (0) trick to wrap this macro, since the macro can't take * arguments. */ -#define log_fn (_log_fn_function_name=__func__),_log_fn -#define log_debug (_log_fn_function_name=__func__),_log_debug -#define log_info (_log_fn_function_name=__func__),_log_info -#define log_notice (_log_fn_function_name=__func__),_log_notice -#define log_warn (_log_fn_function_name=__func__),_log_warn -#define log_err (_log_fn_function_name=__func__),_log_err +#define log_fn (log_fn_function_name_=__func__),log_fn_ +#define log_fn_ratelim (log_fn_function_name_=__func__),log_fn_ratelim_ +#define log_debug (log_fn_function_name_=__func__),log_debug_ +#define log_info (log_fn_function_name_=__func__),log_info_ +#define log_notice (log_fn_function_name_=__func__),log_notice_ +#define log_warn (log_fn_function_name_=__func__),log_warn_ +#define log_err (log_fn_function_name_=__func__),log_err_ #endif #endif /* !GNUC */ -# define _TOR_LOG_H +# define TOR_TORLOG_H #endif diff --git a/src/common/tortls.c b/src/common/tortls.c index 60aac64929..8f3f6a7130 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -58,8 +58,8 @@ #include "container.h" #include <string.h> -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,7) -#error "We require OpenSSL >= 0.9.7" +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) +#error "We require OpenSSL >= 0.9.8" #endif /* Enable the "v2" TLS handshake. @@ -127,8 +127,32 @@ typedef struct tor_tls_context_t { crypto_pk_t *auth_key; } tor_tls_context_t; +/** Return values for tor_tls_classify_client_ciphers. + * + * @{ + */ +/** An error occurred when examining the client ciphers */ +#define CIPHERS_ERR -1 +/** The client cipher list indicates that a v1 handshake was in use. */ +#define CIPHERS_V1 1 +/** The client cipher list indicates that the client is using the v2 or the + * v3 handshake, but that it is (probably!) lying about what ciphers it + * supports */ +#define CIPHERS_V2 2 +/** The client cipher list indicates that the client is using the v2 or the + * v3 handshake, and that it is telling the truth about what ciphers it + * supports */ +#define CIPHERS_UNRESTRICTED 3 +/** @} */ + #define TOR_TLS_MAGIC 0x71571571 +typedef enum { + TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE, + TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE, + TOR_TLS_ST_BUFFEREVENT +} tor_tls_state_t; + /** Holds a SSL object and its associated data. Members are only * accessed from within tortls.c. */ @@ -138,12 +162,9 @@ struct tor_tls_t { SSL *ssl; /**< An OpenSSL SSL object. */ int socket; /**< The underlying file descriptor for this TLS connection. */ char *address; /**< An address to log when describing this connection. */ - enum { - TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE, - TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE, - TOR_TLS_ST_BUFFEREVENT - } state : 3; /**< The current SSL state, depending on which operations have - * completed successfully. */ + ENUM_BF(tor_tls_state_t) state : 3; /**< The current SSL state, + * depending on which operations + * have completed successfully. */ unsigned int isServer:1; /**< True iff this is a server-side connection */ unsigned int wasV2Handshake:1; /**< True iff the original handshake for * this connection used the updated version @@ -152,6 +173,9 @@ struct tor_tls_t { * one certificate). */ /** True iff we should call negotiated_callback when we're done reading. */ unsigned int got_renegotiate:1; + /** Return value from tor_tls_classify_client_ciphers, or 0 if we haven't + * called that function yet. */ + int8_t client_cipher_list_type; /** Incremented every time we start the server side of a handshake. */ uint8_t server_handshake_count; size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last @@ -210,14 +234,16 @@ static X509* tor_tls_create_certificate(crypto_pk_t *rsa, crypto_pk_t *rsa_sign, const char *cname, const char *cname_sign, - unsigned int lifetime); + unsigned int cert_lifetime); static int tor_tls_context_init_one(tor_tls_context_t **ppcontext, crypto_pk_t *identity, unsigned int key_lifetime, + unsigned int flags, int is_client); static tor_tls_context_t *tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, + unsigned int flags, int is_client); static int check_cert_lifetime_internal(int severity, const X509 *cert, int past_tolerance, int future_tolerance); @@ -234,8 +260,8 @@ static tor_tls_context_t *client_tls_context = NULL; static int tls_library_is_initialized = 0; /* Module-internal error codes. */ -#define _TOR_TLS_SYSCALL (_MIN_TOR_TLS_ERROR_VAL - 2) -#define _TOR_TLS_ZERORETURN (_MIN_TOR_TLS_ERROR_VAL - 1) +#define TOR_TLS_SYSCALL_ (MIN_TOR_TLS_ERROR_VAL_ - 2) +#define TOR_TLS_ZERORETURN_ (MIN_TOR_TLS_ERROR_VAL_ - 1) /** Write a description of the current state of <b>tls</b> into the * <b>sz</b>-byte buffer at <b>buf</b>. */ @@ -308,11 +334,11 @@ tor_tls_log_one_error(tor_tls_t *tls, unsigned long err, if (!lib) lib = "(null)"; if (!func) func = "(null)"; if (doing) { - log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)", + tor_log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)", doing, addr?" with ":"", addr?addr:"", msg, lib, func, state); } else { - log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)", + tor_log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)", addr?" with ":"", addr?addr:"", msg, lib, func, state); } @@ -336,35 +362,19 @@ tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing) static int tor_errno_to_tls_error(int e) { -#if defined(_WIN32) - switch (e) { - case WSAECONNRESET: // most common - return TOR_TLS_ERROR_CONNRESET; - case WSAETIMEDOUT: - return TOR_TLS_ERROR_TIMEOUT; - case WSAENETUNREACH: - case WSAEHOSTUNREACH: - return TOR_TLS_ERROR_NO_ROUTE; - case WSAECONNREFUSED: - return TOR_TLS_ERROR_CONNREFUSED; // least common - default: - return TOR_TLS_ERROR_MISC; - } -#else switch (e) { - case ECONNRESET: // most common + case SOCK_ERRNO(ECONNRESET): // most common return TOR_TLS_ERROR_CONNRESET; - case ETIMEDOUT: + case SOCK_ERRNO(ETIMEDOUT): return TOR_TLS_ERROR_TIMEOUT; - case EHOSTUNREACH: - case ENETUNREACH: + case SOCK_ERRNO(EHOSTUNREACH): + case SOCK_ERRNO(ENETUNREACH): return TOR_TLS_ERROR_NO_ROUTE; - case ECONNREFUSED: + case SOCK_ERRNO(ECONNREFUSED): return TOR_TLS_ERROR_CONNREFUSED; // least common default: return TOR_TLS_ERROR_MISC; } -#endif } /** Given a TOR_TLS_* error code, return a string equivalent. */ @@ -393,9 +403,9 @@ tor_tls_err_to_string(int err) /** Given a TLS object and the result of an SSL_* call, use * SSL_get_error to determine whether an error has occurred, and if so * which one. Return one of TOR_TLS_{DONE|WANTREAD|WANTWRITE|ERROR}. - * If extra&CATCH_SYSCALL is true, return _TOR_TLS_SYSCALL instead of + * If extra&CATCH_SYSCALL is true, return TOR_TLS_SYSCALL_ instead of * reporting syscall errors. If extra&CATCH_ZERO is true, return - * _TOR_TLS_ZERORETURN instead of reporting zero-return errors. + * TOR_TLS_ZERORETURN_ instead of reporting zero-return errors. * * If an error has occurred, log it at level <b>severity</b> and describe the * current action as <b>doing</b>. @@ -415,14 +425,14 @@ tor_tls_get_error(tor_tls_t *tls, int r, int extra, return TOR_TLS_WANTWRITE; case SSL_ERROR_SYSCALL: if (extra&CATCH_SYSCALL) - return _TOR_TLS_SYSCALL; + return TOR_TLS_SYSCALL_; if (r == 0) { - log(severity, LD_NET, "TLS error: unexpected close while %s (%s)", + tor_log(severity, LD_NET, "TLS error: unexpected close while %s (%s)", doing, SSL_state_string_long(tls->ssl)); tor_error = TOR_TLS_ERROR_IO; } else { int e = tor_socket_errno(tls->socket); - log(severity, LD_NET, + tor_log(severity, LD_NET, "TLS error: <syscall error while %s> (errno=%d: %s; state=%s)", doing, e, tor_socket_strerror(e), SSL_state_string_long(tls->ssl)); @@ -432,8 +442,8 @@ tor_tls_get_error(tor_tls_t *tls, int r, int extra, 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 in state %s", + return TOR_TLS_ZERORETURN_; + tor_log(severity, LD_NET, "TLS connection closed while %s in state %s", doing, SSL_state_string_long(tls->ssl)); tls_log_errors(tls, severity, domain, doing); return TOR_TLS_CLOSE; @@ -478,7 +488,7 @@ tor_tls_init(void) * a test of intelligence and determination. */ if (version > OPENSSL_V(0,9,8,'k') && version <= OPENSSL_V(0,9,8,'l')) { - log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l, but " + log_info(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l, but " "some vendors have backported renegotiation code from " "0.9.8m without updating the version number. " "I will try SSL3_FLAGS and SSL_OP to enable renegotation.", @@ -486,12 +496,12 @@ tor_tls_init(void) use_unsafe_renegotiation_flag = 1; use_unsafe_renegotiation_op = 1; } else if (version > OPENSSL_V(0,9,8,'l')) { - log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8m or later; " + log_info(LD_GENERAL, "OpenSSL %s looks like version 0.9.8m or later; " "I will try SSL_OP to enable renegotiation", SSLeay_version(SSLEAY_VERSION)); use_unsafe_renegotiation_op = 1; } else if (version <= OPENSSL_V(0,9,8,'k')) { - log_notice(LD_GENERAL, "OpenSSL %s [%lx] looks like it's older than " + log_info(LD_GENERAL, "OpenSSL %s [%lx] looks like it's older than " "0.9.8l, but some vendors have backported 0.9.8l's " "renegotiation code to earlier versions, and some have " "backported the code from 0.9.8m or 0.9.8n. I'll set both " @@ -505,6 +515,37 @@ tor_tls_init(void) SSLeay_version(SSLEAY_VERSION), version); } +#if (SIZEOF_VOID_P >= 8 && \ + !defined(OPENSSL_NO_EC) && \ + OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1)) + if (version >= OPENSSL_V_SERIES(1,0,1)) { + /* Warn if we could *almost* be running with much faster ECDH. + If we're built for a 64-bit target, using OpenSSL 1.0.1, but we + don't have one of the built-in __uint128-based speedups, we are + just one build operation away from an accelerated handshake. + + (We could be looking at OPENSSL_NO_EC_NISTP_64_GCC_128 instead of + doing this test, but that gives compile-time options, not runtime + behavior.) + */ + EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + const EC_GROUP *g = key ? EC_KEY_get0_group(key) : NULL; + const EC_METHOD *m = g ? EC_GROUP_method_of(g) : NULL; + const int warn = (m == EC_GFp_simple_method() || + m == EC_GFp_mont_method() || + m == EC_GFp_nist_method()); + EC_KEY_free(key); + + if (warn) + log_notice(LD_GENERAL, "We were built to run on a 64-bit CPU, with " + "OpenSSL 1.0.1 or later, but with a version of OpenSSL " + "that apparently lacks accelerated support for the NIST " + "P-224 and P-256 groups. Building openssl with such " + "support (using the enable-ec_nistp_64_gcc_128 option " + "when configuring it) would make ECDH much faster."); + } +#endif + tor_tls_allocate_tor_tls_object_ex_data_index(); tls_library_is_initialized = 1; @@ -567,9 +608,10 @@ tor_x509_name_new(const char *cname) /** Generate and sign an X509 certificate with the public key <b>rsa</b>, * signed by the private key <b>rsa_sign</b>. The commonName of the * certificate will be <b>cname</b>; the commonName of the issuer will be - * <b>cname_sign</b>. The cert will be valid for <b>cert_lifetime</b> seconds - * starting from now. Return a certificate on success, NULL on - * failure. + * <b>cname_sign</b>. The cert will be valid for <b>cert_lifetime</b> + * seconds, starting from some time in the past. + * + * Return a certificate on success, NULL on failure. */ static X509 * tor_tls_create_certificate(crypto_pk_t *rsa, @@ -591,15 +633,20 @@ tor_tls_create_certificate(crypto_pk_t *rsa, tor_tls_init(); - start_time = time(NULL); + /* Make sure we're part-way through the certificate lifetime, rather + * than having it start right now. Don't choose quite uniformly, since + * then we might pick a time where we're about to expire. Lastly, be + * sure to start on a day boundary. */ + start_time = time(NULL) - crypto_rand_int(cert_lifetime) + 2*24*3600; + start_time -= start_time % (24*3600); tor_assert(rsa); tor_assert(cname); tor_assert(rsa_sign); tor_assert(cname_sign); - if (!(sign_pkey = _crypto_pk_get_evp_pkey(rsa_sign,1))) + if (!(sign_pkey = crypto_pk_get_evp_pkey_(rsa_sign,1))) goto error; - if (!(pkey = _crypto_pk_get_evp_pkey(rsa,0))) + if (!(pkey = crypto_pk_get_evp_pkey_(rsa,0))) goto error; if (!(x509 = X509_new())) goto error; @@ -647,7 +694,7 @@ tor_tls_create_certificate(crypto_pk_t *rsa, if (pkey) EVP_PKEY_free(pkey); if (serial_number) - BN_free(serial_number); + BN_clear_free(serial_number); if (name) X509_NAME_free(name); if (name_issuer) @@ -657,11 +704,58 @@ tor_tls_create_certificate(crypto_pk_t *rsa, #undef SERIAL_NUMBER_SIZE } -/** List of ciphers that servers should select from.*/ +/** List of ciphers that servers should select from when the client might be + * claiming extra unsupported ciphers in order to avoid fingerprinting. */ #define SERVER_CIPHER_LIST \ (TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":" \ TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" \ SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) + +/** List of ciphers that servers should select from when we actually have + * our choice of what cipher to use. */ +const char UNRESTRICTED_SERVER_CIPHER_LIST[] = + /* This list is autogenerated with the gen_server_ciphers.py script; + * don't hand-edit it. */ +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ":" +#endif +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ":" +#endif +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 + TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 ":" +#endif +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 + TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 ":" +#endif +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA + TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA ":" +#endif +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA + TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA ":" +#endif +#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 + TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 ":" +#endif +#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 + TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 ":" +#endif +#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 ":" +#endif +#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 ":" +#endif + /* Required */ + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":" + /* Required */ + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" +#ifdef TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA + TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA ":" +#endif + /* Required */ + SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA; + /* 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 @@ -754,7 +848,7 @@ tor_cert_new(X509 *x509_cert) if ((pkey = X509_get_pubkey(x509_cert)) && (rsa = EVP_PKEY_get1_RSA(pkey))) { - crypto_pk_t *pk = _crypto_new_pk_from_rsa(rsa); + crypto_pk_t *pk = crypto_new_pk_from_rsa_(rsa); crypto_pk_get_all_digests(pk, &cert->pkey_digests); cert->pkey_digests_set = 1; crypto_pk_free(pk); @@ -778,13 +872,8 @@ tor_cert_decode(const uint8_t *certificate, size_t certificate_len) if (certificate_len > INT_MAX) return NULL; -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) - /* This ifdef suppresses a type warning. Take out this case once everybody - * is using OpenSSL 0.9.8 or later. */ - x509 = d2i_X509(NULL, (unsigned char**)&cp, (int)certificate_len); -#else x509 = d2i_X509(NULL, &cp, (int)certificate_len); -#endif + if (!x509) return NULL; /* Couldn't decode */ if (cp - certificate != (int)certificate_len) { @@ -901,7 +990,7 @@ tor_tls_cert_get_key(tor_cert_t *cert) EVP_PKEY_free(pkey); return NULL; } - result = _crypto_new_pk_from_rsa(rsa); + result = crypto_new_pk_from_rsa_(rsa); EVP_PKEY_free(pkey); return result; } @@ -1019,17 +1108,20 @@ tor_tls_context_incref(tor_tls_context_t *ctx) /** 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 + * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in <b>flags</b>, use * the same TLS context for incoming and outgoing connections, and - * ignore <b>client_identity</b>. */ + * ignore <b>client_identity</b>. If one of TOR_TLS_CTX_USE_ECDHE_P{224,256} + * is set in <b>flags</b>, use that ECDHE group if possible; otherwise use + * the default ECDHE group. */ int -tor_tls_context_init(int is_public_server, +tor_tls_context_init(unsigned flags, crypto_pk_t *client_identity, crypto_pk_t *server_identity, unsigned int key_lifetime) { int rv1 = 0; int rv2 = 0; + const int is_public_server = flags & TOR_TLS_CTX_IS_PUBLIC_SERVER; if (is_public_server) { tor_tls_context_t *new_ctx; @@ -1039,7 +1131,7 @@ tor_tls_context_init(int is_public_server, rv1 = tor_tls_context_init_one(&server_tls_context, server_identity, - key_lifetime, 0); + key_lifetime, flags, 0); if (rv1 >= 0) { new_ctx = server_tls_context; @@ -1056,6 +1148,7 @@ tor_tls_context_init(int is_public_server, rv1 = tor_tls_context_init_one(&server_tls_context, server_identity, key_lifetime, + flags, 0); } else { tor_tls_context_t *old_ctx = server_tls_context; @@ -1069,6 +1162,7 @@ tor_tls_context_init(int is_public_server, rv2 = tor_tls_context_init_one(&client_tls_context, client_identity, key_lifetime, + flags, 1); } @@ -1085,10 +1179,12 @@ static int tor_tls_context_init_one(tor_tls_context_t **ppcontext, crypto_pk_t *identity, unsigned int key_lifetime, + unsigned int flags, int is_client) { tor_tls_context_t *new_ctx = tor_tls_context_new(identity, key_lifetime, + flags, is_client); tor_tls_context_t *old_ctx = *ppcontext; @@ -1112,7 +1208,7 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext, */ static tor_tls_context_t * tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, - int is_client) + unsigned flags, int is_client) { crypto_pk_t *rsa = NULL, *rsa_auth = NULL; EVP_PKEY *pkey = NULL; @@ -1150,7 +1246,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, authcert = tor_tls_create_certificate(rsa_auth, identity, nickname, nn2, key_lifetime); if (!cert || !idcert || !authcert) { - log(LOG_WARN, LD_CRYPTO, "Error creating certificate"); + log_warn(LD_CRYPTO, "Error creating certificate"); goto error; } } @@ -1181,6 +1277,10 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, goto error; SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2); + /* Prefer the server's ordering of ciphers: the client's ordering has + * historically been chosen for fingerprinting resistance. */ + SSL_CTX_set_options(result->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + /* Disable TLS1.1 and TLS1.2 if they exist. We need to do this to * workaround a bug present in all OpenSSL 1.0.1 versions (as of 1 * June 2012), wherein renegotiating while using one of these TLS @@ -1189,19 +1289,29 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, * version. Once some version of OpenSSL does TLS1.1 and TLS1.2 * renegotiation properly, we can turn them back on when built with * that version. */ +#if OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,1,'e') #ifdef SSL_OP_NO_TLSv1_2 SSL_CTX_set_options(result->ctx, SSL_OP_NO_TLSv1_2); #endif #ifdef SSL_OP_NO_TLSv1_1 SSL_CTX_set_options(result->ctx, SSL_OP_NO_TLSv1_1); #endif +#endif + /* Disable TLS tickets if they're supported. We never want to use them; * using them can make our perfect forward secrecy a little worse, *and* * create an opportunity to fingerprint us (since it's unusual to use them * with TLS sessions turned off). + * + * In 0.2.4, clients advertise support for them though, to avoid a TLS + * distinguishability vector. This can give us worse PFS, though, if we + * get a server that doesn't set SSL_OP_NO_TICKET. With luck, there will + * be few such servers by the time 0.2.4 is more stable. */ #ifdef SSL_OP_NO_TICKET - SSL_CTX_set_options(result->ctx, SSL_OP_NO_TICKET); + if (! is_client) { + SSL_CTX_set_options(result->ctx, SSL_OP_NO_TICKET); + } #endif if ( @@ -1222,6 +1332,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, } SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_DH_USE); + SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_ECDH_USE); #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(result->ctx, @@ -1257,7 +1368,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); if (!is_client) { tor_assert(rsa); - if (!(pkey = _crypto_pk_get_evp_pkey(rsa,1))) + if (!(pkey = crypto_pk_get_evp_pkey_(rsa,1))) goto error; if (!SSL_CTX_use_PrivateKey(result->ctx, pkey)) goto error; @@ -1269,9 +1380,29 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, { crypto_dh_t *dh = crypto_dh_new(DH_TYPE_TLS); tor_assert(dh); - SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_get_dh(dh)); + SSL_CTX_set_tmp_dh(result->ctx, crypto_dh_get_dh_(dh)); crypto_dh_free(dh); } +#if (!defined(OPENSSL_NO_EC) && \ + OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0)) + if (! is_client) { + int nid; + EC_KEY *ec_key; + if (flags & TOR_TLS_CTX_USE_ECDHE_P224) + nid = NID_secp224r1; + else if (flags & TOR_TLS_CTX_USE_ECDHE_P256) + nid = NID_X9_62_prime256v1; + else + nid = NID_X9_62_prime256v1; + /* Use P-256 for ECDHE. */ + ec_key = EC_KEY_new_by_curve_name(nid); + if (ec_key != NULL) /*XXXX Handle errors? */ + SSL_CTX_set_tmp_ecdh(result->ctx, ec_key); + EC_KEY_free(ec_key); + } +#else + (void)flags; +#endif SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, always_accept_verify_cb); /* let us realloc bufs that we're writing from */ @@ -1308,28 +1439,108 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, } #ifdef V2_HANDSHAKE_SERVER -/** Return true iff the cipher list suggested by the client for <b>ssl</b> is - * a list that indicates that the client knows how to do the v2 TLS connection - * handshake. */ + +/* Here's the old V2 cipher list we sent from 0.2.1.1-alpha up to + * 0.2.3.17-beta. If a client is using this list, we can't believe the ciphers + * that it claims to support. We'll prune this list to remove the ciphers + * *we* don't recognize. */ +static uint16_t v2_cipher_list[] = { + 0xc00a, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */ + 0xc014, /* TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA */ + 0x0039, /* TLS1_TXT_DHE_RSA_WITH_AES_256_SHA */ + 0x0038, /* TLS1_TXT_DHE_DSS_WITH_AES_256_SHA */ + 0xc00f, /* TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA */ + 0xc005, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA */ + 0x0035, /* TLS1_TXT_RSA_WITH_AES_256_SHA */ + 0xc007, /* TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA */ + 0xc009, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */ + 0xc011, /* TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA */ + 0xc013, /* TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA */ + 0x0033, /* TLS1_TXT_DHE_RSA_WITH_AES_128_SHA */ + 0x0032, /* TLS1_TXT_DHE_DSS_WITH_AES_128_SHA */ + 0xc00c, /* TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA */ + 0xc00e, /* TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA */ + 0xc002, /* TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA */ + 0xc004, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA */ + 0x0004, /* SSL3_TXT_RSA_RC4_128_MD5 */ + 0x0005, /* SSL3_TXT_RSA_RC4_128_SHA */ + 0x002f, /* TLS1_TXT_RSA_WITH_AES_128_SHA */ + 0xc008, /* TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA */ + 0xc012, /* TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA */ + 0x0016, /* SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA */ + 0x0013, /* SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA */ + 0xc00d, /* TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA */ + 0xc003, /* TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA */ + 0xfeff, /* SSL3_TXT_RSA_FIPS_WITH_3DES_EDE_CBC_SHA */ + 0x000a, /* SSL3_TXT_RSA_DES_192_CBC3_SHA */ + 0 +}; +/** Have we removed the unrecognized ciphers from v2_cipher_list yet? */ +static int v2_cipher_list_pruned = 0; + +/** Remove from v2_cipher_list every cipher that we don't support, so that + * comparing v2_cipher_list to a client's cipher list will give a sensible + * result. */ +static void +prune_v2_cipher_list(void) +{ + uint16_t *inp, *outp; + const SSL_METHOD *m = SSLv23_method(); + + inp = outp = v2_cipher_list; + while (*inp) { + unsigned char cipherid[2]; + const SSL_CIPHER *cipher; + /* Is there no better way to do this? */ + set_uint16(cipherid, htons(*inp)); + cipher = m->get_cipher_by_char(cipherid); + if (cipher) { + tor_assert((cipher->id & 0xffff) == *inp); + *outp++ = *inp++; + } else { + inp++; + } + } + *outp = 0; + + v2_cipher_list_pruned = 1; +} + +/* Return the name of the negotiated ciphersuite in use on <b>tls</b> */ +const char * +tor_tls_get_ciphersuite_name(tor_tls_t *tls) +{ + return SSL_get_cipher(tls->ssl); +} + +/** Examine the client cipher list in <b>ssl</b>, and determine what kind of + * client it is. Return one of CIPHERS_ERR, CIPHERS_V1, CIPHERS_V2, + * CIPHERS_UNRESTRICTED. + **/ static int -tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) +tor_tls_classify_client_ciphers(const SSL *ssl, + STACK_OF(SSL_CIPHER) *peer_ciphers) { - int i; - SSL_SESSION *session; + int i, res; + tor_tls_t *tor_tls; + if (PREDICT_UNLIKELY(!v2_cipher_list_pruned)) + prune_v2_cipher_list(); + + tor_tls = tor_tls_get_by_ssl(ssl); + if (tor_tls && tor_tls->client_cipher_list_type) + return tor_tls->client_cipher_list_type; + /* 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_info(LD_NET, "No session on TLS?"); - return 0; - } - if (!session->ciphers) { + if (!peer_ciphers) { log_info(LD_NET, "No ciphers on session"); - return 0; + res = CIPHERS_ERR; + goto done; } /* Now we need to see if there are any ciphers whose presence means we're * dealing with an updated Tor. */ - for (i = 0; i < sk_SSL_CIPHER_num(session->ciphers); ++i) { - SSL_CIPHER *cipher = sk_SSL_CIPHER_value(session->ciphers, i); + for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) { + SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i); const char *ciphername = SSL_CIPHER_get_name(cipher); if (strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) && strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) && @@ -1337,28 +1548,111 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) strcmp(ciphername, "(NONE)")) { log_debug(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername); // return 1; - goto dump_list; + goto v2_or_higher; } } - return 0; - dump_list: + res = CIPHERS_V1; + goto done; + v2_or_higher: + { + const uint16_t *v2_cipher = v2_cipher_list; + for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) { + SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i); + uint16_t id = cipher->id & 0xffff; + if (id == 0x00ff) /* extended renegotiation indicator. */ + continue; + if (!id || id != *v2_cipher) { + res = CIPHERS_UNRESTRICTED; + goto dump_ciphers; + } + ++v2_cipher; + } + if (*v2_cipher != 0) { + res = CIPHERS_UNRESTRICTED; + goto dump_ciphers; + } + res = CIPHERS_V2; + } + + dump_ciphers: { smartlist_t *elts = smartlist_new(); char *s; - for (i = 0; i < sk_SSL_CIPHER_num(session->ciphers); ++i) { - SSL_CIPHER *cipher = sk_SSL_CIPHER_value(session->ciphers, i); + for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) { + SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i); const char *ciphername = SSL_CIPHER_get_name(cipher); smartlist_add(elts, (char*)ciphername); } s = smartlist_join_strings(elts, ":", 0, NULL); - log_debug(LD_NET, "Got a non-version-1 cipher list from %s. It is: '%s'", - address, s); + log_debug(LD_NET, "Got a %s V2/V3 cipher list from %s. It is: '%s'", + (res == CIPHERS_V2) ? "fictitious" : "real", ADDR(tor_tls), s); tor_free(s); smartlist_free(elts); } - return 1; + done: + if (tor_tls) + return tor_tls->client_cipher_list_type = res; + + return res; } +/** Return true iff the cipher list suggested by the client for <b>ssl</b> is + * a list that indicates that the client knows how to do the v2 TLS connection + * handshake. */ +static int +tor_tls_client_is_using_v2_ciphers(const SSL *ssl) +{ + SSL_SESSION *session; + if (!(session = SSL_get_session((SSL *)ssl))) { + log_info(LD_NET, "No session on TLS?"); + return CIPHERS_ERR; + } + + return tor_tls_classify_client_ciphers(ssl, session->ciphers) >= CIPHERS_V2; +} + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0) +/** Callback to get invoked on a server after we've read the list of ciphers + * the client supports, but before we pick our own ciphersuite. + * + * We can't abuse an info_cb for this, since by the time one of the + * client_hello info_cbs is called, we've already picked which ciphersuite to + * use. + * + * Technically, this function is an abuse of this callback, since the point of + * a session_secret_cb is to try to set up and/or verify a shared-secret for + * authentication on the fly. But as long as we return 0, we won't actually be + * setting up a shared secret, and all will be fine. + */ +static int +tor_tls_session_secret_cb(SSL *ssl, void *secret, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + SSL_CIPHER **cipher, void *arg) +{ + (void) secret; + (void) secret_len; + (void) peer_ciphers; + (void) cipher; + (void) arg; + + if (tor_tls_classify_client_ciphers(ssl, peer_ciphers) == + CIPHERS_UNRESTRICTED) { + SSL_set_cipher_list(ssl, UNRESTRICTED_SERVER_CIPHER_LIST); + } + + SSL_set_session_secret_cb(ssl, NULL, NULL); + + return 0; +} +static void +tor_tls_setup_session_secret_cb(tor_tls_t *tls) +{ + SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL); +} +#else +#define tor_tls_setup_session_secret_cb(tls) STMT_NIL +#endif + /** Invoked when a TLS state changes: log the change at severity 'debug' */ static void tor_tls_debug_state_callback(const SSL *ssl, int type, int val) @@ -1400,7 +1694,7 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val) } /* Now check the cipher list. */ - if (tor_tls_client_is_using_v2_ciphers(ssl, ADDR(tls))) { + if (tor_tls_client_is_using_v2_ciphers(ssl)) { if (tls->wasV2Handshake) return; /* We already turned this stuff off for the first handshake; * This is a renegotiation. */ @@ -1625,6 +1919,9 @@ tor_tls_new(int sock, int isServer) SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback); } + if (isServer) + tor_tls_setup_session_secret_cb(result); + /* Not expected to get called. */ tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object"); return result; @@ -1721,6 +2018,10 @@ tor_tls_free(tor_tls_t *tls) if (!tls) return; tor_assert(tls->ssl); + { + size_t r,w; + tor_tls_get_n_raw_bytes(tls,&r,&w); /* ensure written_by_tls is updated */ + } #ifdef SSL_set_tlsext_host_name SSL_set_tlsext_host_name(tls->ssl, NULL); #endif @@ -1761,7 +2062,7 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len) return r; } err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET); - if (err == _TOR_TLS_ZERORETURN || err == TOR_TLS_CLOSE) { + 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; return TOR_TLS_CLOSE; @@ -1772,6 +2073,13 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len) } } +/** Total number of bytes that we've used TLS to send. Used to track TLS + * overhead. */ +static uint64_t total_bytes_written_over_tls = 0; +/** Total number of bytes that TLS has put on the network for us. Used to + * track TLS overhead. */ +static uint64_t total_bytes_written_by_tls = 0; + /** Underlying function for TLS writing. Write up to <b>n</b> * characters from <b>cp</b> onto <b>tls</b>. On success, returns the * number of characters written. On failure, returns TOR_TLS_ERROR, @@ -1798,6 +2106,7 @@ tor_tls_write(tor_tls_t *tls, const char *cp, size_t n) r = SSL_write(tls->ssl, cp, (int)n); err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO, LD_NET); if (err == TOR_TLS_DONE) { + total_bytes_written_over_tls += r; return r; } if (err == TOR_TLS_WANTWRITE || err == TOR_TLS_WANTREAD) { @@ -1866,7 +2175,7 @@ tor_tls_finish_handshake(tor_tls_t *tls) /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */ tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN; #ifdef V2_HANDSHAKE_SERVER - if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) { + if (tor_tls_client_is_using_v2_ciphers(tls->ssl)) { /* This check is redundant, but back when we did it in the callback, * we might have not been able to look up the tor_tls_t if the code * was buggy. Fixing that. */ @@ -1974,7 +2283,7 @@ tor_tls_shutdown(tor_tls_t *tls) } while (r>0); err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading to shut down", LOG_INFO, LD_NET); - if (err == _TOR_TLS_ZERORETURN) { + if (err == TOR_TLS_ZERORETURN_) { tls->state = TOR_TLS_ST_GOTCLOSE; /* fall through... */ } else { @@ -1990,11 +2299,11 @@ tor_tls_shutdown(tor_tls_t *tls) } err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down", LOG_INFO, LD_NET); - if (err == _TOR_TLS_SYSCALL) { + if (err == TOR_TLS_SYSCALL_) { /* The underlying TCP connection closed while we were shutting down. */ tls->state = TOR_TLS_ST_CLOSED; return TOR_TLS_DONE; - } else if (err == _TOR_TLS_ZERORETURN) { + } else if (err == TOR_TLS_ZERORETURN_) { /* The TLS connection says that it sent a shutdown record, but * isn't done shutting down yet. Make sure that this hasn't * happened before, then go back to the start of the function @@ -2002,7 +2311,7 @@ tor_tls_shutdown(tor_tls_t *tls) */ if (tls->state == TOR_TLS_ST_GOTCLOSE || tls->state == TOR_TLS_ST_SENTCLOSE) { - log(LOG_WARN, LD_NET, + log_warn(LD_NET, "TLS returned \"half-closed\" value while already half-closed"); return TOR_TLS_ERROR_MISC; } @@ -2052,7 +2361,7 @@ log_cert_lifetime(int severity, const X509 *cert, const char *problem) struct tm tm; if (problem) - log(severity, LD_GENERAL, + tor_log(severity, LD_GENERAL, "Certificate %s. Either their clock is set wrong, or your clock " "is wrong.", problem); @@ -2075,9 +2384,9 @@ log_cert_lifetime(int severity, const X509 *cert, const char *problem) BIO_get_mem_ptr(bio, &buf); s2 = tor_strndup(buf->data, buf->length); - strftime(mytime, 32, "%b %d %H:%M:%S %Y GMT", tor_gmtime_r(&now, &tm)); + strftime(mytime, 32, "%b %d %H:%M:%S %Y UTC", tor_gmtime_r(&now, &tm)); - log(severity, LD_GENERAL, + tor_log(severity, LD_GENERAL, "(certificate lifetime runs from %s through %s. Your time is %s.)", s1,s2,mytime); @@ -2164,7 +2473,7 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity_key) rsa = EVP_PKEY_get1_RSA(id_pkey); if (!rsa) goto done; - *identity_key = _crypto_new_pk_from_rsa(rsa); + *identity_key = crypto_new_pk_from_rsa_(rsa); r = 0; @@ -2287,18 +2596,31 @@ tor_tls_get_n_raw_bytes(tor_tls_t *tls, size_t *n_read, size_t *n_written) "r=%lu, last_read=%lu, w=%lu, last_written=%lu", r, tls->last_read_count, w, tls->last_write_count); } + total_bytes_written_by_tls += *n_written; tls->last_read_count = r; tls->last_write_count = w; } +/** Return a ratio of the bytes that TLS has sent to the bytes that we've told + * it to send. Used to track whether our TLS records are getting too tiny. */ +double +tls_get_write_overhead_ratio(void) +{ + if (total_bytes_written_over_tls == 0) + return 1.0; + + return U64_TO_DBL(total_bytes_written_by_tls) / + U64_TO_DBL(total_bytes_written_over_tls); +} + /** Implement check_no_tls_errors: If there are any pending OpenSSL * errors, log an error message. */ void -_check_no_tls_errors(const char *fname, int line) +check_no_tls_errors_(const char *fname, int line) { if (ERR_peek_error() == 0) return; - log(LOG_WARN, LD_CRYPTO, "Unhandled OpenSSL errors found at %s:%d: ", + log_warn(LD_CRYPTO, "Unhandled OpenSSL errors found at %s:%d: ", tor_fix_source_file(fname), line); tls_log_errors(NULL, LOG_WARN, LD_NET, NULL); } diff --git a/src/common/tortls.h b/src/common/tortls.h index 491a5419df..49c488b365 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -1,10 +1,10 @@ /* Copyright (c) 2003, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_TORTLS_H -#define _TOR_TORTLS_H +#ifndef TOR_TORTLS_H +#define TOR_TORTLS_H /** * \file tortls.h @@ -21,7 +21,7 @@ typedef struct tor_tls_t tor_tls_t; typedef struct tor_cert_t tor_cert_t; /* Possible return values for most tor_tls_* functions. */ -#define _MIN_TOR_TLS_ERROR_VAL -9 +#define MIN_TOR_TLS_ERROR_VAL_ -9 #define TOR_TLS_ERROR_MISC -9 /* Rename to unexpected close or something. XXXX */ #define TOR_TLS_ERROR_IO -8 @@ -54,7 +54,12 @@ const char *tor_tls_err_to_string(int err); void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz); void tor_tls_free_all(void); -int tor_tls_context_init(int is_public_server, + +#define TOR_TLS_CTX_IS_PUBLIC_SERVER (1u<<0) +#define TOR_TLS_CTX_USE_ECDHE_P256 (1u<<1) +#define TOR_TLS_CTX_USE_ECDHE_P224 (1u<<2) + +int tor_tls_context_init(unsigned flags, crypto_pk_t *client_identity, crypto_pk_t *server_identity, unsigned int key_lifetime); @@ -90,6 +95,8 @@ void tor_tls_get_buffer_sizes(tor_tls_t *tls, size_t *rbuf_capacity, size_t *rbuf_bytes, size_t *wbuf_capacity, size_t *wbuf_bytes); +double tls_get_write_overhead_ratio(void); + int tor_tls_used_v1_handshake(tor_tls_t *tls); int tor_tls_received_v3_certificate(tor_tls_t *tls); int tor_tls_get_num_server_handshakes(tor_tls_t *tls); @@ -98,9 +105,9 @@ int tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out); /* Log and abort if there are unhandled TLS errors in OpenSSL's error stack. */ -#define check_no_tls_errors() _check_no_tls_errors(__FILE__,__LINE__) +#define check_no_tls_errors() check_no_tls_errors_(__FILE__,__LINE__) -void _check_no_tls_errors(const char *fname, int line); +void check_no_tls_errors_(const char *fname, int line); void tor_tls_log_one_error(tor_tls_t *tls, unsigned long err, int severity, int domain, const char *doing); @@ -129,6 +136,7 @@ int tor_tls_cert_is_valid(int severity, const tor_cert_t *cert, const tor_cert_t *signing_cert, int check_rsa_1024); +const char *tor_tls_get_ciphersuite_name(tor_tls_t *tls); #endif diff --git a/src/common/util.c b/src/common/util.c index b16afa13e9..5eb0f9a69b 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -20,7 +20,6 @@ #define UTIL_PRIVATE #include "util.h" #include "torlog.h" -#undef log #include "crypto.h" #include "torint.h" #include "container.h" @@ -39,8 +38,8 @@ #endif /* math.h needs this on Linux */ -#ifndef __USE_ISOC99 -#define __USE_ISOC99 1 +#ifndef _USE_ISOC99_ +#define _USE_ISOC99_ 1 #endif #include <math.h> #include <stdlib.h> @@ -125,7 +124,7 @@ * ignored otherwise. */ void * -_tor_malloc(size_t size DMALLOC_PARAMS) +tor_malloc_(size_t size DMALLOC_PARAMS) { void *result; @@ -159,7 +158,7 @@ _tor_malloc(size_t size DMALLOC_PARAMS) * the process on error. (Same as calloc(size,1), but never returns NULL.) */ void * -_tor_malloc_zero(size_t size DMALLOC_PARAMS) +tor_malloc_zero_(size_t size DMALLOC_PARAMS) { /* You may ask yourself, "wouldn't it be smart to use calloc instead of * malloc+memset? Perhaps libc's calloc knows some nifty optimization trick @@ -167,7 +166,7 @@ _tor_malloc_zero(size_t size DMALLOC_PARAMS) * we're allocating something very big (it knows if it just got the memory * from the OS in a pre-zeroed state). We don't want to use tor_malloc_zero * for big stuff, so we don't bother with calloc. */ - void *result = _tor_malloc(size DMALLOC_FN_ARGS); + void *result = tor_malloc_(size DMALLOC_FN_ARGS); memset(result, 0, size); return result; } @@ -184,7 +183,7 @@ _tor_malloc_zero(size_t size DMALLOC_PARAMS) * smaller than size). Don't do that then. */ void * -_tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) +tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) { /* You may ask yourself, "wouldn't it be smart to use calloc instead of * malloc+memset? Perhaps libc's calloc knows some nifty optimization trick @@ -197,7 +196,7 @@ _tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) tor_assert(nmemb < max_nmemb); - result = _tor_malloc_zero((nmemb * size) DMALLOC_FN_ARGS); + result = tor_malloc_zero_((nmemb * size) DMALLOC_FN_ARGS); return result; } @@ -206,7 +205,7 @@ _tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) * terminate. (Like realloc(ptr,size), but never returns NULL.) */ void * -_tor_realloc(void *ptr, size_t size DMALLOC_PARAMS) +tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS) { void *result; @@ -230,7 +229,7 @@ _tor_realloc(void *ptr, size_t size DMALLOC_PARAMS) * NULL.) */ char * -_tor_strdup(const char *s DMALLOC_PARAMS) +tor_strdup_(const char *s DMALLOC_PARAMS) { char *dup; tor_assert(s); @@ -254,12 +253,12 @@ _tor_strdup(const char *s DMALLOC_PARAMS) * NULL.) */ char * -_tor_strndup(const char *s, size_t n DMALLOC_PARAMS) +tor_strndup_(const char *s, size_t n DMALLOC_PARAMS) { char *dup; tor_assert(s); tor_assert(n < SIZE_T_CEILING); - dup = _tor_malloc((n+1) DMALLOC_FN_ARGS); + dup = tor_malloc_((n+1) DMALLOC_FN_ARGS); /* Performance note: Ordinarily we prefer strlcpy to strncpy. But * this function gets called a whole lot, and platform strncpy is * much faster than strlcpy when strlen(s) is much longer than n. @@ -272,55 +271,38 @@ _tor_strndup(const char *s, size_t n DMALLOC_PARAMS) /** Allocate a chunk of <b>len</b> bytes, with the same contents as the * <b>len</b> bytes starting at <b>mem</b>. */ void * -_tor_memdup(const void *mem, size_t len DMALLOC_PARAMS) +tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS) { char *dup; tor_assert(len < SIZE_T_CEILING); tor_assert(mem); - dup = _tor_malloc(len DMALLOC_FN_ARGS); + dup = tor_malloc_(len DMALLOC_FN_ARGS); memcpy(dup, mem, len); return dup; } +/** As tor_memdup(), but add an extra 0 byte at the end of the resulting + * memory. */ +void * +tor_memdup_nulterm(const void *mem, size_t len DMALLOC_PARAMS) +{ + char *dup; + tor_assert(len < SIZE_T_CEILING+1); + tor_assert(mem); + dup = tor_malloc_(len+1 DMALLOC_FN_ARGS); + memcpy(dup, mem, len); + dup[len] = '\0'; + return dup; +} + /** Helper for places that need to take a function pointer to the right * spelling of "free()". */ void -_tor_free(void *mem) +tor_free_(void *mem) { tor_free(mem); } -#if defined(HAVE_MALLOC_GOOD_SIZE) && !defined(HAVE_MALLOC_GOOD_SIZE_PROTOTYPE) -/* Some version of Mac OSX have malloc_good_size in their libc, but not - * actually defined in malloc/malloc.h. We detect this and work around it by - * prototyping. - */ -extern size_t malloc_good_size(size_t size); -#endif - -/** Allocate and return a chunk of memory of size at least *<b>size</b>, using - * the same resources we would use to malloc *<b>sizep</b>. Set *<b>sizep</b> - * to the number of usable bytes in the chunk of memory. */ -void * -_tor_malloc_roundup(size_t *sizep DMALLOC_PARAMS) -{ -#ifdef HAVE_MALLOC_GOOD_SIZE - tor_assert(*sizep < SIZE_T_CEILING); - *sizep = malloc_good_size(*sizep); - return _tor_malloc(*sizep DMALLOC_FN_ARGS); -#elif 0 && defined(HAVE_MALLOC_USABLE_SIZE) && !defined(USE_DMALLOC) - /* Never use malloc_usable_size(); it makes valgrind really unhappy, - * and doesn't win much in terms of usable space where it exists. */ - void *result; - tor_assert(*sizep < SIZE_T_CEILING); - result = _tor_malloc(*sizep DMALLOC_FN_ARGS); - *sizep = malloc_usable_size(result); - return result; -#else - return _tor_malloc(*sizep DMALLOC_FN_ARGS); -#endif -} - /** Call the platform malloc info function, and dump the results to the log at * level <b>severity</b>. If no such function exists, do nothing. */ void @@ -354,8 +336,8 @@ tor_log_mallinfo(int severity) * ===== */ /** - * 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. + * Returns the natural logarithm of d base e. We defined this wrapper here so + * to avoid conflicts with old versions of tor_log(), which were named log(). */ double tor_mathlog(double d) @@ -363,9 +345,9 @@ 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. */ +/** Return the long integer closest to <b>d</b>. We define this wrapper + * here so that not all users of math.h need to use the right incantations + * to get the c99 functions. */ long tor_lround(double d) { @@ -378,6 +360,21 @@ tor_lround(double d) #endif } +/** Return the 64-bit integer closest to d. We define this wrapper here so + * that not all users of math.h need to use the right incantations to get the + * c99 functions. */ +int64_t +tor_llround(double d) +{ +#if defined(HAVE_LLROUND) + return (int64_t)llround(d); +#elif defined(HAVE_RINT) + return (int64_t)rint(d); +#else + return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5)); +#endif +} + /** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */ int tor_log2(uint64_t u64) @@ -410,12 +407,24 @@ tor_log2(uint64_t u64) return r; } -/** Return the power of 2 closest to <b>u64</b>. */ +/** Return the power of 2 in range [1,UINT64_MAX] closest to <b>u64</b>. If + * there are two powers of 2 equally close, round down. */ uint64_t round_to_power_of_2(uint64_t u64) { - int lg2 = tor_log2(u64); - uint64_t low = U64_LITERAL(1) << lg2, high = U64_LITERAL(1) << (lg2+1); + int lg2; + uint64_t low; + uint64_t high; + if (u64 == 0) + return 1; + + lg2 = tor_log2(u64); + low = U64_LITERAL(1) << lg2; + + if (lg2 == 63) + return low; + + high = U64_LITERAL(1) << (lg2+1); if (high - u64 < u64 - low) return high; else @@ -655,6 +664,16 @@ fast_memcmpstart(const void *mem, size_t memlen, return fast_memcmp(mem, prefix, plen); } +/** Given a nul-terminated string s, set every character before the nul + * to zero. */ +void +tor_strclear(char *s) +{ + while (*s) { + *s++ = '\0'; + } +} + /** Return a pointer to the first char of s that is not whitespace and * not a comment, or to the terminating NUL if no such character exists. */ @@ -1013,7 +1032,7 @@ base16_encode(char *dest, size_t destlen, const char *src, size_t srclen) /** Helper: given a hex digit, return its value, or -1 if it isn't hex. */ static INLINE int -_hex_decode_digit(char c) +hex_decode_digit_(char c) { switch (c) { case '0': return 0; @@ -1041,7 +1060,7 @@ _hex_decode_digit(char c) int hex_decode_digit(char c) { - return _hex_decode_digit(c); + return hex_decode_digit_(c); } /** Given a hexadecimal string of <b>srclen</b> bytes in <b>src</b>, decode it @@ -1059,8 +1078,8 @@ base16_decode(char *dest, size_t destlen, const char *src, size_t srclen) return -1; end = src+srclen; while (src<end) { - v1 = _hex_decode_digit(*src); - v2 = _hex_decode_digit(*(src+1)); + v1 = hex_decode_digit_(*src); + v2 = hex_decode_digit_(*(src+1)); if (v1<0||v2<0) return -1; *(uint8_t*)dest = (v1<<4)|v2; @@ -1160,130 +1179,21 @@ esc_for_log(const char *s) const char * escaped(const char *s) { - static char *_escaped_val = NULL; - tor_free(_escaped_val); + static char *escaped_val_ = NULL; + tor_free(escaped_val_); if (s) - _escaped_val = esc_for_log(s); + escaped_val_ = esc_for_log(s); else - _escaped_val = NULL; + escaped_val_ = NULL; - return _escaped_val; -} - -/** Rudimentary string wrapping code: given a un-wrapped <b>string</b> (no - * newlines!), break the string into newline-terminated lines of no more than - * <b>width</b> characters long (not counting newline) and insert them into - * <b>out</b> in order. Precede the first line with prefix0, and subsequent - * lines with prefixRest. - */ -/* This uses a stupid greedy wrapping algorithm right now: - * - For each line: - * - Try to fit as much stuff as possible, but break on a space. - * - If the first "word" of the line will extend beyond the allowable - * width, break the word at the end of the width. - */ -void -wrap_string(smartlist_t *out, const char *string, size_t width, - const char *prefix0, const char *prefixRest) -{ - size_t p0Len, pRestLen, pCurLen; - const char *eos, *prefixCur; - tor_assert(out); - tor_assert(string); - tor_assert(width); - if (!prefix0) - prefix0 = ""; - if (!prefixRest) - prefixRest = ""; - - p0Len = strlen(prefix0); - pRestLen = strlen(prefixRest); - tor_assert(width > p0Len && width > pRestLen); - eos = strchr(string, '\0'); - tor_assert(eos); - pCurLen = p0Len; - prefixCur = prefix0; - - while ((eos-string)+pCurLen > width) { - const char *eol = string + width - pCurLen; - while (eol > string && *eol != ' ') - --eol; - /* eol is now the last space that can fit, or the start of the string. */ - if (eol > string) { - size_t line_len = (eol-string) + pCurLen + 2; - char *line = tor_malloc(line_len); - memcpy(line, prefixCur, pCurLen); - memcpy(line+pCurLen, string, eol-string); - line[line_len-2] = '\n'; - line[line_len-1] = '\0'; - smartlist_add(out, line); - string = eol + 1; - } else { - size_t line_len = width + 2; - char *line = tor_malloc(line_len); - memcpy(line, prefixCur, pCurLen); - memcpy(line+pCurLen, string, width - pCurLen); - line[line_len-2] = '\n'; - line[line_len-1] = '\0'; - smartlist_add(out, line); - string += width-pCurLen; - } - prefixCur = prefixRest; - pCurLen = pRestLen; - } - - if (string < eos) { - size_t line_len = (eos-string) + pCurLen + 2; - char *line = tor_malloc(line_len); - memcpy(line, prefixCur, pCurLen); - memcpy(line+pCurLen, string, eos-string); - line[line_len-2] = '\n'; - line[line_len-1] = '\0'; - smartlist_add(out, line); - } + return escaped_val_; } /* ===== * 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 @@ -1322,6 +1232,18 @@ tv_mdiff(const struct timeval *start, const struct timeval *end) return mdiff; } +/** + * 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; +} + /** 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. */ @@ -1336,7 +1258,7 @@ n_leapdays(int y1, int y2) static const int days_per_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -/** Compute a time_t given a struct tm. The result is given in GMT, and +/** Compute a time_t given a struct tm. The result is given in UTC, and * does not account for leap seconds. Return 0 on success, -1 on failure. */ int @@ -1377,10 +1299,11 @@ static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -/** Set <b>buf</b> to the RFC1123 encoding of the GMT value of <b>t</b>. +/** Set <b>buf</b> to the RFC1123 encoding of the UTC value of <b>t</b>. * The buffer must be at least RFC1123_TIME_LEN+1 bytes long. * - * (RFC1123 format is Fri, 29 Sep 2006 15:54:20 GMT) + * (RFC1123 format is "Fri, 29 Sep 2006 15:54:20 GMT". Note the "GMT" + * rather than "UTC".) */ void format_rfc1123_time(char *buf, time_t t) @@ -1398,8 +1321,11 @@ format_rfc1123_time(char *buf, time_t t) memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3); } -/** Parse the RFC1123 encoding of some time (in GMT) from <b>buf</b>, - * and store the result in *<b>t</b>. +/** Parse the (a subset of) the RFC1123 encoding of some time (in UTC) from + * <b>buf</b>, and store the result in *<b>t</b>. + * + * Note that we only accept the subset generated by format_rfc1123_time above, + * not the full range of formats suggested by RFC 1123. * * Return 0 on success, -1 on failure. */ @@ -1827,6 +1753,10 @@ file_status(const char *fname) return FN_DIR; else if (st.st_mode & S_IFREG) return FN_FILE; +#ifndef _WIN32 + else if (st.st_mode & S_IFIFO) + return FN_FILE; +#endif else return FN_ERROR; } @@ -2257,6 +2187,46 @@ write_bytes_to_new_file(const char *fname, const char *str, size_t len, (bin?O_BINARY:O_TEXT)); } +/** + * Read the contents of the open file <b>fd</b> presuming it is a FIFO + * (or similar) file descriptor for which the size of the file isn't + * known ahead of time. Return NULL on failure, and a NUL-terminated + * string on success. On success, set <b>sz_out</b> to the number of + * bytes read. + */ +char * +read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) +{ + ssize_t r; + size_t pos = 0; + char *string = NULL; + size_t string_max = 0; + + if (max_bytes_to_read+1 >= SIZE_T_CEILING) + return NULL; + + do { + /* XXXX This "add 1K" approach is a little goofy; if we care about + * performance here, we should be doubling. But in practice we shouldn't + * be using this function on big files anyway. */ + string_max = pos + 1024; + if (string_max > max_bytes_to_read) + string_max = max_bytes_to_read + 1; + string = tor_realloc(string, string_max); + r = read(fd, string + pos, string_max - pos - 1); + if (r < 0) { + tor_free(string); + return NULL; + } + + pos += r; + } while (r > 0 && pos < max_bytes_to_read); + + *sz_out = pos; + string[pos] = '\0'; + return string; +} + /** Read the contents of <b>filename</b> into a newly allocated * string; return the string on success or NULL on failure. * @@ -2305,8 +2275,26 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out) return NULL; } - if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) +#ifndef _WIN32 +/** When we detect that we're reading from a FIFO, don't read more than + * this many bytes. It's insane overkill for most uses. */ +#define FIFO_READ_MAX (1024*1024) + if (S_ISFIFO(statbuf.st_mode)) { + size_t sz = 0; + string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz); + if (string && stat_out) { + statbuf.st_size = sz; + memcpy(stat_out, &statbuf, sizeof(struct stat)); + } + close(fd); + return string; + } +#endif + + if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) { + close(fd); return NULL; + } string = tor_malloc((size_t)(statbuf.st_size+1)); @@ -2466,10 +2454,13 @@ unescape_string(const char *s, char **result, size_t *size_out) * key portion and *<b>value_out</b> to a new string holding the value portion * of the line, and return a pointer to the start of the next line. If we run * out of data, return a pointer to the end of the string. If we encounter an - * error, return NULL. + * error, return NULL and set *<b>err_out</b> (if provided) to an error + * message. */ const char * -parse_config_line_from_str(const char *line, char **key_out, char **value_out) +parse_config_line_from_str_verbose(const char *line, char **key_out, + char **value_out, + const char **err_out) { /* I believe the file format here is supposed to be: FILE = (EMPTYLINE | LINE)* (EMPTYLASTLINE | LASTLINE)? @@ -2543,12 +2534,18 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out) /* Find the end of the line. */ if (*line == '\"') { // XXX No continuation handling is done here - if (!(line = unescape_string(line, value_out, NULL))) - return NULL; + if (!(line = unescape_string(line, value_out, NULL))) { + if (err_out) + *err_out = "Invalid escape sequence in quoted string"; + return NULL; + } while (*line == ' ' || *line == '\t') ++line; - if (*line && *line != '#' && *line != '\n') + if (*line && *line != '#' && *line != '\n') { + if (err_out) + *err_out = "Excess data after quoted string"; return NULL; + } } else { /* Look for the end of the line. */ while (*line && *line != '\n' && (*line != '#' || continuation)) { @@ -2683,9 +2680,9 @@ digit_to_num(char d) * success, store the result in <b>out</b>, advance bufp to the next * character, and return 0. On failure, return -1. */ static int -scan_unsigned(const char **bufp, unsigned *out, int width, int base) +scan_unsigned(const char **bufp, unsigned long *out, int width, int base) { - unsigned result = 0; + unsigned long result = 0; int scanned_so_far = 0; const int hex = base==16; tor_assert(base == 10 || base == 16); @@ -2697,8 +2694,8 @@ scan_unsigned(const char **bufp, unsigned *out, int width, int base) while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp)) && scanned_so_far < width) { int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++); - unsigned new_result = result * base + digit; - if (new_result > UINT32_MAX || new_result < result) + unsigned long new_result = result * base + digit; + if (new_result < result) return -1; /* over/underflow. */ result = new_result; ++scanned_so_far; @@ -2711,6 +2708,89 @@ scan_unsigned(const char **bufp, unsigned *out, int width, int base) return 0; } +/** Helper: Read an signed 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_signed(const char **bufp, long *out, int width) +{ + int neg = 0; + unsigned long result = 0; + + if (!bufp || !*bufp || !out) + return -1; + if (width<0) + width=MAX_SCANF_WIDTH; + + if (**bufp == '-') { + neg = 1; + ++*bufp; + --width; + } + + if (scan_unsigned(bufp, &result, width, 10) < 0) + return -1; + + if (neg) { + if (result > ((unsigned long)LONG_MAX) + 1) + return -1; /* Underflow */ + *out = -(long)result; + } else { + if (result > LONG_MAX) + return -1; /* Overflow */ + *out = (long)result; + } + + return 0; +} + +/** Helper: Read a decimal-formatted double 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_double(const char **bufp, double *out, int width) +{ + int neg = 0; + double result = 0; + int scanned_so_far = 0; + + if (!bufp || !*bufp || !out) + return -1; + if (width<0) + width=MAX_SCANF_WIDTH; + + if (**bufp == '-') { + neg = 1; + ++*bufp; + } + + while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) { + const int digit = digit_to_num(*(*bufp)++); + result = result * 10 + digit; + ++scanned_so_far; + } + if (**bufp == '.') { + double fracval = 0, denominator = 1; + ++*bufp; + ++scanned_so_far; + while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) { + const int digit = digit_to_num(*(*bufp)++); + fracval = fracval * 10 + digit; + denominator *= 10; + ++scanned_so_far; + } + result += fracval / denominator; + } + + if (!scanned_so_far) /* No actual digits scanned */ + return -1; + + *out = neg ? -result : result; + return 0; +} + /** 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. */ @@ -2747,6 +2827,7 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) } } else { int width = -1; + int longmod = 0; ++pattern; if (TOR_ISDIGIT(*pattern)) { width = digit_to_num(*pattern++); @@ -2759,17 +2840,57 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) if (!width) /* No zero-width things. */ return -1; } + if (*pattern == 'l') { + longmod = 1; + ++pattern; + } if (*pattern == 'u' || *pattern == 'x') { - unsigned *u = va_arg(ap, unsigned *); + unsigned long u; const int base = (*pattern == 'u') ? 10 : 16; if (!*buf) return n_matched; - if (scan_unsigned(&buf, u, width, base)<0) + if (scan_unsigned(&buf, &u, width, base)<0) + return n_matched; + if (longmod) { + unsigned long *out = va_arg(ap, unsigned long *); + *out = u; + } else { + unsigned *out = va_arg(ap, unsigned *); + if (u > UINT_MAX) + return n_matched; + *out = (unsigned) u; + } + ++pattern; + ++n_matched; + } else if (*pattern == 'f') { + double *d = va_arg(ap, double *); + if (!longmod) + return -1; /* float not supported */ + if (!*buf) + return n_matched; + if (scan_double(&buf, d, width)<0) return n_matched; ++pattern; ++n_matched; + } else if (*pattern == 'd') { + long lng=0; + if (scan_signed(&buf, &lng, width)<0) + return n_matched; + if (longmod) { + long *out = va_arg(ap, long *); + *out = lng; + } else { + int *out = va_arg(ap, int *); + if (lng < INT_MIN || lng > INT_MAX) + return n_matched; + *out = (int)lng; + } + ++pattern; + ++n_matched; } else if (*pattern == 's') { char *s = va_arg(ap, char *); + if (longmod) + return -1; if (width < 0) return -1; if (scan_string(&buf, s, width)<0) @@ -2778,6 +2899,8 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) ++n_matched; } else if (*pattern == 'c') { char *ch = va_arg(ap, char *); + if (longmod) + return -1; if (width != -1) return -1; if (!*buf) @@ -2788,6 +2911,8 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) } else if (*pattern == '%') { if (*buf != '%') return n_matched; + if (longmod) + return -1; ++buf; ++pattern; } else { @@ -2801,9 +2926,14 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) /** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b> * and store the results in the corresponding argument fields. Differs from - * sscanf in that it: Only handles %u, %x, %c and %Ns. Does not handle - * arbitrarily long widths. %u and %x do not consume any space. Is - * locale-independent. Returns -1 on malformed patterns. + * sscanf in that: + * <ul><li>It only handles %u, %lu, %x, %lx, %<NUM>s, %d, %ld, %lf, and %c. + * <li>It only handles decimal inputs for %lf. (12.3, not 1.23e1) + * <li>It does not handle arbitrarily long widths. + * <li>Numbers do not consume any space characters. + * <li>It is locale-independent. + * <li>%u and %x do not consume any space. + * <li>It returns -1 on malformed patterns.</ul> * * (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 @@ -3630,12 +3760,13 @@ tor_spawn_background(const char *const filename, const char **argv, child_state = CHILD_STATE_MAXFD; #ifdef _SC_OPEN_MAX - if (-1 != max_fd) { + if (-1 == max_fd) { max_fd = (int) sysconf(_SC_OPEN_MAX); - if (max_fd == -1) + if (max_fd == -1) { max_fd = DEFAULT_MAX_FD; log_warn(LD_GENERAL, "Cannot find maximum file descriptor, assuming %d", max_fd); + } } #else max_fd = DEFAULT_MAX_FD; @@ -3784,10 +3915,17 @@ tor_process_handle_destroy(process_handle_t *process_handle, if (also_terminate_process) { if (tor_terminate_process(process_handle) < 0) { - log_notice(LD_GENERAL, "Failed to terminate process with PID '%d'", - tor_process_get_pid(process_handle)); + const char *errstr = +#ifdef _WIN32 + format_win32_error(GetLastError()); +#else + strerror(errno); +#endif + log_notice(LD_GENERAL, "Failed to terminate process with " + "PID '%d' ('%s').", tor_process_get_pid(process_handle), + errstr); } else { - log_info(LD_GENERAL, "Terminated process with PID '%d'", + log_info(LD_GENERAL, "Terminated process with PID '%d'.", tor_process_get_pid(process_handle)); } } @@ -4255,7 +4393,70 @@ tor_split_lines(smartlist_t *sl, char *buf, int len) return smartlist_len(sl); } +/** Return a string corresponding to <b>stream_status</b>. */ +const char * +stream_status_to_string(enum stream_status stream_status) +{ + switch (stream_status) { + case IO_STREAM_OKAY: + return "okay"; + case IO_STREAM_EAGAIN: + return "temporarily unavailable"; + case IO_STREAM_TERM: + return "terminated"; + case IO_STREAM_CLOSED: + return "closed"; + default: + tor_fragile_assert(); + return "unknown"; + } +} + #ifdef _WIN32 + +/** Return a smartlist containing lines outputted from + * <b>handle</b>. Return NULL on error, and set + * <b>stream_status_out</b> appropriately. */ +smartlist_t * +tor_get_lines_from_handle(HANDLE *handle, + enum stream_status *stream_status_out) +{ + int pos; + char stdout_buf[600] = {0}; + smartlist_t *lines = NULL; + + tor_assert(stream_status_out); + + *stream_status_out = IO_STREAM_TERM; + + pos = tor_read_all_handle(handle, stdout_buf, sizeof(stdout_buf) - 1, NULL); + if (pos < 0) { + *stream_status_out = IO_STREAM_TERM; + return NULL; + } + if (pos == 0) { + *stream_status_out = IO_STREAM_EAGAIN; + return NULL; + } + + /* End with a null even if there isn't a \r\n at the end */ + /* TODO: What if this is a partial line? */ + stdout_buf[pos] = '\0'; + + /* Split up the buffer */ + lines = smartlist_new(); + tor_split_lines(lines, stdout_buf, pos); + + /* Currently 'lines' is populated with strings residing on the + stack. Replace them with their exact copies on the heap: */ + SMARTLIST_FOREACH(lines, char *, line, + SMARTLIST_REPLACE_CURRENT(lines, line, tor_strdup(line))); + + *stream_status_out = IO_STREAM_OKAY; + + return lines; +} + /** Read from stream, and send lines to log at the specified log level. * Returns -1 if there is a error reading, and 0 otherwise. * If the generated stream is flushed more often than on new lines, or @@ -4303,6 +4504,33 @@ log_from_handle(HANDLE *pipe, int severity) #else +/** Return a smartlist containing lines outputted from + * <b>handle</b>. Return NULL on error, and set + * <b>stream_status_out</b> appropriately. */ +smartlist_t * +tor_get_lines_from_handle(FILE *handle, enum stream_status *stream_status_out) +{ + enum stream_status stream_status; + char stdout_buf[400]; + smartlist_t *lines = NULL; + + while (1) { + memset(stdout_buf, 0, sizeof(stdout_buf)); + + stream_status = get_string_from_pipe(handle, + stdout_buf, sizeof(stdout_buf) - 1); + if (stream_status != IO_STREAM_OKAY) + goto done; + + if (!lines) lines = smartlist_new(); + smartlist_add(lines, tor_strdup(stdout_buf)); + } + + done: + *stream_status_out = stream_status; + return lines; +} + /** Read from stream, and send lines to log at the specified log level. * Returns 1 if stream is closed normally, -1 if there is a error reading, and * 0 otherwise. Handles lines from tor-fw-helper and @@ -4421,9 +4649,130 @@ get_string_from_pipe(FILE *stream, char *buf_out, size_t count) return IO_STREAM_TERM; } -/* DOCDOC tor_check_port_forwarding */ +/** Parse a <b>line</b> from tor-fw-helper and issue an appropriate + * log message to our user. */ +static void +handle_fw_helper_line(const char *line) +{ + smartlist_t *tokens = smartlist_new(); + char *message = NULL; + char *message_for_log = NULL; + const char *external_port = NULL; + const char *internal_port = NULL; + const char *result = NULL; + int port = 0; + int success = 0; + + smartlist_split_string(tokens, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(tokens) < 5) + goto err; + + if (strcmp(smartlist_get(tokens, 0), "tor-fw-helper") || + strcmp(smartlist_get(tokens, 1), "tcp-forward")) + goto err; + + external_port = smartlist_get(tokens, 2); + internal_port = smartlist_get(tokens, 3); + result = smartlist_get(tokens, 4); + + if (smartlist_len(tokens) > 5) { + /* If there are more than 5 tokens, they are part of [<message>]. + Let's use a second smartlist to form the whole message; + strncat loops suck. */ + int i; + int message_words_n = smartlist_len(tokens) - 5; + smartlist_t *message_sl = smartlist_new(); + for (i = 0; i < message_words_n; i++) + smartlist_add(message_sl, smartlist_get(tokens, 5+i)); + + tor_assert(smartlist_len(message_sl) > 0); + message = smartlist_join_strings(message_sl, " ", 0, NULL); + + /* wrap the message in log-friendly wrapping */ + tor_asprintf(&message_for_log, " ('%s')", message); + + smartlist_free(message_sl); + } + + port = atoi(external_port); + if (port < 1 || port > 65535) + goto err; + + port = atoi(internal_port); + if (port < 1 || port > 65535) + goto err; + + if (!strcmp(result, "SUCCESS")) + success = 1; + else if (!strcmp(result, "FAIL")) + success = 0; + else + goto err; + + if (!success) { + log_warn(LD_GENERAL, "Tor was unable to forward TCP port '%s' to '%s'%s. " + "Please make sure that your router supports port " + "forwarding protocols (like NAT-PMP). Note that if '%s' is " + "your ORPort, your relay will be unable to receive inbound " + "traffic.", external_port, internal_port, + message_for_log ? message_for_log : "", + internal_port); + } else { + log_info(LD_GENERAL, + "Tor successfully forwarded TCP port '%s' to '%s'%s.", + external_port, internal_port, + message_for_log ? message_for_log : ""); + } + + goto done; + + err: + log_warn(LD_GENERAL, "tor-fw-helper sent us a string we could not " + "parse (%s).", line); + + done: + SMARTLIST_FOREACH(tokens, char *, cp, tor_free(cp)); + smartlist_free(tokens); + tor_free(message); + tor_free(message_for_log); +} + +/** Read what tor-fw-helper has to say in its stdout and handle it + * appropriately */ +static int +handle_fw_helper_output(process_handle_t *process_handle) +{ + smartlist_t *fw_helper_output = NULL; + enum stream_status stream_status = 0; + + fw_helper_output = + tor_get_lines_from_handle(tor_process_get_stdout_pipe(process_handle), + &stream_status); + if (!fw_helper_output) { /* didn't get any output from tor-fw-helper */ + /* if EAGAIN we should retry in the future */ + return (stream_status == IO_STREAM_EAGAIN) ? 0 : -1; + } + + /* Handle the lines we got: */ + SMARTLIST_FOREACH_BEGIN(fw_helper_output, char *, line) { + handle_fw_helper_line(line); + tor_free(line); + } SMARTLIST_FOREACH_END(line); + + smartlist_free(fw_helper_output); + + return 0; +} + +/** Spawn tor-fw-helper and ask it to forward the ports in + * <b>ports_to_forward</b>. <b>ports_to_forward</b> contains strings + * of the form "<external port>:<internal port>", which is the format + * that tor-fw-helper expects. */ void -tor_check_port_forwarding(const char *filename, int dir_port, int or_port, +tor_check_port_forwarding(const char *filename, + smartlist_t *ports_to_forward, time_t now) { /* When fw-helper succeeds, how long do we wait until running it again */ @@ -4437,32 +4786,51 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, static process_handle_t *child_handle=NULL; static time_t time_to_run_helper = 0; - int stdout_status, stderr_status, retval; - const char *argv[10]; - char s_dirport[6], s_orport[6]; + int stderr_status, retval; + int stdout_status = 0; tor_assert(filename); - /* Set up command line for tor-fw-helper */ - snprintf(s_dirport, sizeof s_dirport, "%d", dir_port); - snprintf(s_orport, sizeof s_orport, "%d", or_port); - - /* TODO: Allow different internal and external ports */ - argv[0] = filename; - argv[1] = "--internal-or-port"; - argv[2] = s_orport; - argv[3] = "--external-or-port"; - argv[4] = s_orport; - argv[5] = "--internal-dir-port"; - argv[6] = s_dirport; - argv[7] = "--external-dir-port"; - argv[8] = s_dirport; - argv[9] = NULL; - /* Start the child, if it is not already running */ if ((!child_handle || child_handle->status != PROCESS_STATUS_RUNNING) && time_to_run_helper < now) { - int status; + /*tor-fw-helper cli looks like this: tor_fw_helper -p :5555 -p 4555:1111 */ + const char **argv; /* cli arguments */ + int args_n, status; + int argv_index = 0; /* index inside 'argv' */ + + tor_assert(smartlist_len(ports_to_forward) > 0); + + /* check for overflow during 'argv' allocation: + (len(ports_to_forward)*2 + 2)*sizeof(char*) > SIZE_MAX == + len(ports_to_forward) > (((SIZE_MAX/sizeof(char*)) - 2)/2) */ + if ((size_t) smartlist_len(ports_to_forward) > + (((SIZE_MAX/sizeof(char*)) - 2)/2)) { + log_warn(LD_GENERAL, + "Overflow during argv allocation. This shouldn't happen."); + return; + } + /* check for overflow during 'argv_index' increase: + ((len(ports_to_forward)*2 + 2) > INT_MAX) == + len(ports_to_forward) > (INT_MAX - 2)/2 */ + if (smartlist_len(ports_to_forward) > (INT_MAX - 2)/2) { + log_warn(LD_GENERAL, + "Overflow during argv_index increase. This shouldn't happen."); + return; + } + + /* Calculate number of cli arguments: one for the filename, two + for each smartlist element (one for "-p" and one for the + ports), and one for the final NULL. */ + args_n = 1 + 2*smartlist_len(ports_to_forward) + 1; + argv = tor_malloc_zero(sizeof(char*)*args_n); + + argv[argv_index++] = filename; + SMARTLIST_FOREACH_BEGIN(ports_to_forward, const char *, port) { + argv[argv_index++] = "-p"; + argv[argv_index++] = port; + } SMARTLIST_FOREACH_END(port); + argv[argv_index] = NULL; /* Assume tor-fw-helper will succeed, start it later*/ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS; @@ -4479,6 +4847,9 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, status = tor_spawn_background(filename, argv, NULL, &child_handle); #endif + tor_free_((void*)argv); + argv=NULL; + if (PROCESS_STATUS_ERROR == status) { log_warn(LD_GENERAL, "Failed to start port forwarding helper %s", filename); @@ -4496,16 +4867,17 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, /* Read from stdout/stderr and log result */ retval = 0; #ifdef _WIN32 - stdout_status = log_from_handle(child_handle->stdout_pipe, LOG_INFO); - stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_WARN); - /* If we got this far (on Windows), the process started */ - retval = 0; + stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_INFO); #else - stdout_status = log_from_pipe(child_handle->stdout_handle, - LOG_INFO, filename, &retval); stderr_status = log_from_pipe(child_handle->stderr_handle, - LOG_WARN, filename, &retval); + LOG_INFO, filename, &retval); #endif + if (handle_fw_helper_output(child_handle) < 0) { + log_warn(LD_GENERAL, "Failed to handle fw helper output."); + stdout_status = -1; + retval = -1; + } + if (retval) { /* There was a problem in the child process */ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL; @@ -4551,3 +4923,45 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, } } +/** Initialize the insecure RNG <b>rng</b> from a seed value <b>seed</b>. */ +void +tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed) +{ + rng->state = (uint32_t)(seed & 0x7fffffff); +} + +/** Return a randomly chosen value in the range 0..TOR_WEAK_RANDOM_MAX based + * on the RNG state of <b>rng</b>. This entropy will not be cryptographically + * strong; do not rely on it for anything an adversary should not be able to + * predict. */ +int32_t +tor_weak_random(tor_weak_rng_t *rng) +{ + /* Here's a linear congruential generator. OpenBSD and glibc use these + * parameters; they aren't too bad, and should have maximal period over the + * range 0..INT32_MAX. We don't want to use the platform rand() or random(), + * since some platforms have bad weak RNGs that only return values in the + * range 0..INT16_MAX, which just isn't enough. */ + rng->state = (rng->state * 1103515245 + 12345) & 0x7fffffff; + return (int32_t) rng->state; +} + +/** Return a random number in the range [0 , <b>top</b>). {That is, the range + * of integers i such that 0 <= i < top.} Chooses uniformly. Requires that + * top is greater than 0. This randomness is not cryptographically strong; do + * not rely on it for anything an adversary should not be able to predict. */ +int32_t +tor_weak_random_range(tor_weak_rng_t *rng, int32_t top) +{ + /* We don't want to just do tor_weak_random() % top, since random() is often + * implemented with an LCG whose modulus is a power of 2, and those are + * cyclic in their low-order bits. */ + int divisor, result; + tor_assert(top > 0); + divisor = TOR_WEAK_RANDOM_MAX / top; + do { + result = (int32_t)(tor_weak_random(rng) / divisor); + } while (result >= top); + return result; +} + diff --git a/src/common/util.h b/src/common/util.h index 8977d273c5..73daa6e2a1 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,8 +8,8 @@ * \brief Headers for util.c **/ -#ifndef _TOR_UTIL_H -#define _TOR_UTIL_H +#ifndef TOR_UTIL_H +#define TOR_UTIL_H #include "orconfig.h" #include "torint.h" @@ -49,9 +49,9 @@ #define tor_assert(expr) STMT_BEGIN \ if (PREDICT_UNLIKELY(!(expr))) { \ log_err(LD_BUG, "%s:%d: %s: Assertion %s failed; aborting.", \ - _SHORT_FILE_, __LINE__, __func__, #expr); \ + SHORT_FILE__, __LINE__, __func__, #expr); \ fprintf(stderr,"%s:%d %s: Assertion %s failed; aborting.\n", \ - _SHORT_FILE_, __LINE__, __func__, #expr); \ + SHORT_FILE__, __LINE__, __func__, #expr); \ abort(); \ } STMT_END @@ -62,7 +62,7 @@ * to calls. */ #ifdef USE_DMALLOC #define DMALLOC_PARAMS , const char *file, const int line -#define DMALLOC_ARGS , _SHORT_FILE_, __LINE__ +#define DMALLOC_ARGS , SHORT_FILE__, __LINE__ #else #define DMALLOC_PARAMS #define DMALLOC_ARGS @@ -74,23 +74,24 @@ #define tor_fragile_assert() /* Memory management */ -void *_tor_malloc(size_t size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_malloc_zero(size_t size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_malloc_roundup(size_t *size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_calloc(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC; -void *_tor_realloc(void *ptr, size_t size DMALLOC_PARAMS); -char *_tor_strdup(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); -char *_tor_strndup(const char *s, size_t n DMALLOC_PARAMS) +void *tor_malloc_(size_t size DMALLOC_PARAMS) ATTR_MALLOC; +void *tor_malloc_zero_(size_t size DMALLOC_PARAMS) ATTR_MALLOC; +void *tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS) ATTR_MALLOC; +void *tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS); +char *tor_strdup_(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); +char *tor_strndup_(const char *s, size_t n DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); -void *_tor_memdup(const void *mem, size_t len DMALLOC_PARAMS) +void *tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1)); -void _tor_free(void *mem); +void *tor_memdup_nulterm_(const void *mem, size_t len DMALLOC_PARAMS) + ATTR_MALLOC ATTR_NONNULL((1)); +void tor_free_(void *mem); #ifdef USE_DMALLOC extern int dmalloc_free(const char *file, const int line, void *pnt, const int func_id); #define tor_free(p) STMT_BEGIN \ if (PREDICT_LIKELY((p)!=NULL)) { \ - dmalloc_free(_SHORT_FILE_, __LINE__, (p), 0); \ + dmalloc_free(SHORT_FILE__, __LINE__, (p), 0); \ (p)=NULL; \ } \ STMT_END @@ -100,7 +101,7 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, * and it sets the pointer value to NULL after freeing it. * * This is a macro. If you need a function pointer to release memory from - * tor_malloc(), use _tor_free(). + * tor_malloc(), use tor_free_(). */ #define tor_free(p) STMT_BEGIN \ if (PREDICT_LIKELY((p)!=NULL)) { \ @@ -110,14 +111,14 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, STMT_END #endif -#define tor_malloc(size) _tor_malloc(size DMALLOC_ARGS) -#define tor_malloc_zero(size) _tor_malloc_zero(size DMALLOC_ARGS) -#define tor_calloc(nmemb,size) _tor_calloc(nmemb, size DMALLOC_ARGS) -#define tor_malloc_roundup(szp) _tor_malloc_roundup(szp DMALLOC_ARGS) -#define tor_realloc(ptr, size) _tor_realloc(ptr, size DMALLOC_ARGS) -#define tor_strdup(s) _tor_strdup(s DMALLOC_ARGS) -#define tor_strndup(s, n) _tor_strndup(s, n DMALLOC_ARGS) -#define tor_memdup(s, n) _tor_memdup(s, n DMALLOC_ARGS) +#define tor_malloc(size) tor_malloc_(size DMALLOC_ARGS) +#define tor_malloc_zero(size) tor_malloc_zero_(size DMALLOC_ARGS) +#define tor_calloc(nmemb,size) tor_calloc_(nmemb, size DMALLOC_ARGS) +#define tor_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS) +#define tor_strdup(s) tor_strdup_(s DMALLOC_ARGS) +#define tor_strndup(s, n) tor_strndup_(s, n DMALLOC_ARGS) +#define tor_memdup(s, n) tor_memdup_(s, n DMALLOC_ARGS) +#define tor_memdup_nulterm(s, n) tor_memdup_nulterm_(s, n DMALLOC_ARGS) void tor_log_mallinfo(int severity); @@ -161,6 +162,7 @@ void tor_log_mallinfo(int severity); /* Math functions */ double tor_mathlog(double d) ATTR_CONST; long tor_lround(double d) ATTR_CONST; +int64_t tor_llround(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); @@ -173,6 +175,17 @@ int n_bits_set_u8(uint8_t v); * overflow. */ #define CEIL_DIV(a,b) (((a)+(b)-1)/(b)) +/* Return <b>v</b> if it's between <b>min</b> and <b>max</b>. Otherwise + * return <b>min</b> if <b>v</b> is smaller than <b>min</b>, or <b>max</b> if + * <b>b</b> is larger than <b>max</b>. + * + * Requires that <b>min</b> is no more than <b>max</b>. May evaluate any of + * its arguments more than once! */ +#define CLAMP(min,v,max) \ + ( ((v) < (min)) ? (min) : \ + ((v) > (max)) ? (max) : \ + (v) ) + /* String manipulation */ /** Allowable characters in a hexadecimal string. */ @@ -188,6 +201,7 @@ int strcasecmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2)); int strcmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2)); int strcasecmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2)); int fast_memcmpstart(const void *mem, size_t memlen, const char *prefix); +void tor_strclear(char *s); void tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2)); long tor_parse_long(const char *s, int base, long min, @@ -215,8 +229,6 @@ int tor_digest256_is_zero(const char *digest); char *esc_for_log(const char *string) ATTR_MALLOC; const char *escaped(const char *string); struct smartlist_t; -void wrap_string(struct smartlist_t *out, const char *string, size_t width, - const char *prefix0, const char *prefixRest); int tor_vsscanf(const char *buf, const char *pattern, va_list ap) #ifdef __GNUC__ __attribute__((format(scanf, 2, 0))) @@ -239,11 +251,9 @@ 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); +int64_t tv_to_msec(const struct timeval *tv); int tor_timegm(const struct tm *tm, time_t *time_out); #define RFC1123_TIME_LEN 29 void format_rfc1123_time(char *buf, time_t t); @@ -283,6 +293,15 @@ void update_approx_time(time_t now); } } </pre> + + As a convenience wrapper for logging, you can replace the above with: + <pre> + if (possibly_very_frequent_event()) { + static ratelim_t warning_limit = RATELIM_INIT(300); + log_fn_ratelim(&warning_limit, LOG_WARN, LD_GENERAL, + "The event occurred!"); + } + </pre> */ typedef struct ratelim_t { int rate; @@ -306,6 +325,8 @@ enum stream_status { IO_STREAM_CLOSED }; +const char *stream_status_to_string(enum stream_status stream_status); + enum stream_status get_string_from_pipe(FILE *stream, char *buf, size_t count); /** Return values from file_status(); see that function's documentation @@ -360,8 +381,14 @@ struct stat; #endif char *read_file_to_str(const char *filename, int flags, struct stat *stat_out) ATTR_MALLOC; -const char *parse_config_line_from_str(const char *line, - char **key_out, char **value_out); +char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, + size_t *sz_out) + ATTR_MALLOC; +const char *parse_config_line_from_str_verbose(const char *line, + char **key_out, char **value_out, + const char **err_out); +#define parse_config_line_from_str(line,key_out,value_out) \ + parse_config_line_from_str_verbose((line),(key_out),(value_out),NULL) char *expand_filename(const char *filename); struct smartlist_t *tor_listdir(const char *dirname); int path_is_relative(const char *filename); @@ -373,7 +400,8 @@ void write_pidfile(char *filename); /* Port forwarding */ void tor_check_port_forwarding(const char *filename, - int dir_port, int or_port, time_t now); + struct smartlist_t *ports_to_forward, + time_t now); typedef struct process_handle_t process_handle_t; typedef struct process_environment_t process_environment_t; @@ -464,10 +492,34 @@ HANDLE tor_process_get_stdout_pipe(process_handle_t *process_handle); FILE *tor_process_get_stdout_pipe(process_handle_t *process_handle); #endif +#ifdef _WIN32 +struct smartlist_t * +tor_get_lines_from_handle(HANDLE *handle, + enum stream_status *stream_status); +#else +struct smartlist_t * +tor_get_lines_from_handle(FILE *handle, + enum stream_status *stream_status); +#endif + int tor_terminate_process(process_handle_t *process_handle); void tor_process_handle_destroy(process_handle_t *process_handle, int also_terminate_process); +/* ===== Insecure rng */ +typedef struct tor_weak_rng_t { + uint32_t state; +} tor_weak_rng_t; + +#define TOR_WEAK_RNG_INIT {383745623} +#define TOR_WEAK_RANDOM_MAX (INT_MAX) +void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed); +int32_t tor_weak_random(tor_weak_rng_t *weak_rng); +int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top); +/** Randomly return true according to <b>rng</b> with probability 1 in + * <b>n</b> */ +#define tor_weak_random_one_in_n(rng, n) (0==tor_weak_random_range((rng),(n))) + #ifdef UTIL_PRIVATE /* Prototypes for private functions only used by util.c (and unit tests) */ diff --git a/src/config/Makefile.am b/src/config/Makefile.am deleted file mode 100644 index 90dd218b40..0000000000 --- a/src/config/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -confdir = $(sysconfdir)/tor - -tordatadir = $(datadir)/tor - -EXTRA_DIST = geoip -# fallback-consensus - -conf_DATA = torrc.sample - -tordata_DATA = geoip -# fallback_consensus - -# If we don't have it, fake it. -fallback-consensus: - touch fallback-consensus - diff --git a/src/config/README.geoip b/src/config/README.geoip new file mode 100644 index 0000000000..8520501405 --- /dev/null +++ b/src/config/README.geoip @@ -0,0 +1,90 @@ +README.geoip -- information on the IP-to-country-code file shipped with tor +=========================================================================== + +The IP-to-country-code file in src/config/geoip is based on MaxMind's +GeoLite Country database with the following modifications: + + - Those "A1" ("Anonymous Proxy") entries lying inbetween two entries with + the same country code are automatically changed to that country code. + These changes can be overriden by specifying a different country code + in src/config/geoip-manual. + + - Other "A1" entries are replaced with country codes specified in + src/config/geoip-manual, or are left as is if there is no corresponding + entry in that file. Even non-"A1" entries can be modified by adding a + replacement entry to src/config/geoip-manual. Handle with care. + + +1. Updating the geoip file from a MaxMind database file +------------------------------------------------------- + +Download the most recent MaxMind GeoLite Country database: +http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip + +Run `python deanonymind.py` in the local directory. Review the output to +learn about applied automatic/manual changes and watch out for any +warnings. + +Possibly edit geoip-manual to make more/fewer/different manual changes and +re-run `python deanonymind.py`. + +When done, prepend the new geoip file with a comment like this: + + # Last updated based on $DATE Maxmind GeoLite Country + # See README.geoip for details on the conversion. + + +2. Verifying automatic and manual changes using diff +---------------------------------------------------- + +To unzip the original MaxMind file and look at the automatic changes, run: + + unzip GeoIPCountryCSV.zip + diff -U1 GeoIPCountryWhois.csv AutomaticGeoIPCountryWhois.csv + +To look at subsequent manual changes, run: + + diff -U1 AutomaticGeoIPCountryWhois.csv ManualGeoIPCountryWhois.csv + +To manually generate the geoip file and compare it to the automatically +created one, run: + + cut -d, -f3-5 < ManualGeoIPCountryWhois.csv | sed 's/"//g' > mygeoip + diff -U1 geoip mygeoip + + +3. Verifying automatic and manual changes using blockfinder +----------------------------------------------------------- + +Blockfinder is a powerful tool to handle multiple IP-to-country data +sources. Blockfinder has a function to specify a country code and compare +conflicting country code assignments in different data sources. + +We can use blockfinder to compare A1 entries in the original MaxMind file +with the same or overlapping blocks in the file generated above and in the +RIR delegation files: + + git clone https://github.com/ioerror/blockfinder + cd blockfinder/ + python blockfinder -i + python blockfinder -r ../GeoIPCountryWhois.csv + python blockfinder -r ../ManualGeoIPCountryWhois.csv + python blockfinder -p A1 > A1-comparison.txt + +The output marks conflicts between assignments using either '*' in case of +two different opinions or '#' for three or more different opinions about +the country code for a given block. + +The '*' conflicts are most likely harmless, because there will always be +at least two opinions with the original MaxMind file saying A1 and the +other two sources saying something more meaningful. + +However, watch out for '#' conflicts. In these cases, the original +MaxMind file ("A1"), the updated MaxMind file (hopefully the correct +country code), and the RIR delegation files (some other country code) all +disagree. + +There are perfectly valid cases where the updated MaxMind file and the RIR +delegation files don't agree. But each of those cases must be verified +manually. + diff --git a/src/config/deanonymind.py b/src/config/deanonymind.py new file mode 100755 index 0000000000..c86dadca99 --- /dev/null +++ b/src/config/deanonymind.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +import optparse +import os +import sys +import zipfile + +""" +Take a MaxMind GeoLite Country database as input and replace A1 entries +with the country code and name of the preceding entry iff the preceding +(subsequent) entry ends (starts) directly before (after) the A1 entry and +both preceding and subsequent entries contain the same country code. + +Then apply manual changes, either replacing A1 entries that could not be +replaced automatically or overriding previously made automatic changes. +""" + +def main(): + options = parse_options() + assignments = read_file(options.in_maxmind) + assignments = apply_automatic_changes(assignments) + write_file(options.out_automatic, assignments) + manual_assignments = read_file(options.in_manual, must_exist=False) + assignments = apply_manual_changes(assignments, manual_assignments) + write_file(options.out_manual, assignments) + write_file(options.out_geoip, assignments, long_format=False) + +def parse_options(): + parser = optparse.OptionParser() + parser.add_option('-i', action='store', dest='in_maxmind', + default='GeoIPCountryCSV.zip', metavar='FILE', + help='use the specified MaxMind GeoLite Country .zip or .csv ' + 'file as input [default: %default]') + parser.add_option('-g', action='store', dest='in_manual', + default='geoip-manual', metavar='FILE', + help='use the specified .csv file for manual changes or to ' + 'override automatic changes [default: %default]') + parser.add_option('-a', action='store', dest='out_automatic', + default="AutomaticGeoIPCountryWhois.csv", metavar='FILE', + help='write full input file plus automatic changes to the ' + 'specified .csv file [default: %default]') + parser.add_option('-m', action='store', dest='out_manual', + default='ManualGeoIPCountryWhois.csv', metavar='FILE', + help='write full input file plus automatic and manual ' + 'changes to the specified .csv file [default: %default]') + parser.add_option('-o', action='store', dest='out_geoip', + default='geoip', metavar='FILE', + help='write full input file plus automatic and manual ' + 'changes to the specified .csv file that can be shipped ' + 'with tor [default: %default]') + (options, args) = parser.parse_args() + return options + +def read_file(path, must_exist=True): + if not os.path.exists(path): + if must_exist: + print 'File %s does not exist. Exiting.' % (path, ) + sys.exit(1) + else: + return + if path.endswith('.zip'): + zip_file = zipfile.ZipFile(path) + csv_content = zip_file.read('GeoIPCountryWhois.csv') + zip_file.close() + else: + csv_file = open(path) + csv_content = csv_file.read() + csv_file.close() + assignments = [] + for line in csv_content.split('\n'): + stripped_line = line.strip() + if len(stripped_line) > 0 and not stripped_line.startswith('#'): + assignments.append(stripped_line) + return assignments + +def apply_automatic_changes(assignments): + print '\nApplying automatic changes...' + result_lines = [] + prev_line = None + a1_lines = [] + for line in assignments: + if '"A1"' in line: + a1_lines.append(line) + else: + if len(a1_lines) > 0: + new_a1_lines = process_a1_lines(prev_line, a1_lines, line) + for new_a1_line in new_a1_lines: + result_lines.append(new_a1_line) + a1_lines = [] + result_lines.append(line) + prev_line = line + if len(a1_lines) > 0: + new_a1_lines = process_a1_lines(prev_line, a1_lines, None) + for new_a1_line in new_a1_lines: + result_lines.append(new_a1_line) + return result_lines + +def process_a1_lines(prev_line, a1_lines, next_line): + if not prev_line or not next_line: + return a1_lines # Can't merge first or last line in file. + if len(a1_lines) > 1: + return a1_lines # Can't merge more than 1 line at once. + a1_line = a1_lines[0].strip() + prev_entry = parse_line(prev_line) + a1_entry = parse_line(a1_line) + next_entry = parse_line(next_line) + touches_prev_entry = int(prev_entry['end_num']) + 1 == \ + int(a1_entry['start_num']) + touches_next_entry = int(a1_entry['end_num']) + 1 == \ + int(next_entry['start_num']) + same_country_code = prev_entry['country_code'] == \ + next_entry['country_code'] + if touches_prev_entry and touches_next_entry and same_country_code: + new_line = format_line_with_other_country(a1_entry, prev_entry) + print '-%s\n+%s' % (a1_line, new_line, ) + return [new_line] + else: + return a1_lines + +def parse_line(line): + if not line: + return None + keys = ['start_str', 'end_str', 'start_num', 'end_num', + 'country_code', 'country_name'] + stripped_line = line.replace('"', '').strip() + parts = stripped_line.split(',') + entry = dict((k, v) for k, v in zip(keys, parts)) + return entry + +def format_line_with_other_country(original_entry, other_entry): + return '"%s","%s","%s","%s","%s","%s"' % (original_entry['start_str'], + original_entry['end_str'], original_entry['start_num'], + original_entry['end_num'], other_entry['country_code'], + other_entry['country_name'], ) + +def apply_manual_changes(assignments, manual_assignments): + if not manual_assignments: + return assignments + print '\nApplying manual changes...' + manual_dict = {} + for line in manual_assignments: + start_num = parse_line(line)['start_num'] + if start_num in manual_dict: + print ('Warning: duplicate start number in manual ' + 'assignments:\n %s\n %s\nDiscarding first entry.' % + (manual_dict[start_num], line, )) + manual_dict[start_num] = line + result = [] + for line in assignments: + entry = parse_line(line) + start_num = entry['start_num'] + if start_num in manual_dict: + manual_line = manual_dict[start_num] + manual_entry = parse_line(manual_line) + if entry['start_str'] == manual_entry['start_str'] and \ + entry['end_str'] == manual_entry['end_str'] and \ + entry['end_num'] == manual_entry['end_num']: + if len(manual_entry['country_code']) != 2: + print '-%s' % (line, ) # only remove, don't replace + else: + new_line = format_line_with_other_country(entry, + manual_entry) + print '-%s\n+%s' % (line, new_line, ) + result.append(new_line) + del manual_dict[start_num] + else: + print ('Warning: only partial match between ' + 'original/automatically replaced assignment and ' + 'manual assignment:\n %s\n %s\nNot applying ' + 'manual change.' % (line, manual_line, )) + result.append(line) + else: + result.append(line) + if len(manual_dict) > 0: + print ('Warning: could not apply all manual assignments: %s' % + ('\n '.join(manual_dict.values())), ) + return result + +def write_file(path, assignments, long_format=True): + if long_format: + output_lines = assignments + else: + output_lines = [] + for long_line in assignments: + entry = parse_line(long_line) + short_line = "%s,%s,%s" % (entry['start_num'], + entry['end_num'], entry['country_code'], ) + output_lines.append(short_line) + out_file = open(path, 'w') + out_file.write('\n'.join(output_lines)) + out_file.close() + +if __name__ == '__main__': + main() + diff --git a/src/config/geoip-manual b/src/config/geoip-manual new file mode 100644 index 0000000000..99c897ff42 --- /dev/null +++ b/src/config/geoip-manual @@ -0,0 +1,116 @@ +# This file contains manual overrides of A1 entries (and possibly others) +# in MaxMind's GeoLite Country database. Use deanonymind.py in the same +# directory to process this file when producing a new geoip file. See +# README.geoip in the same directory for details. + +# Remove MaxMind entry 0.116.0.0-0.119.255.255 which MaxMind says is AT, +# but which is part of reserved range 0.0.0.0/8. -KL 2012-06-13 +# Disabled, because MaxMind apparently removed this range from their +# database. -KL 2013-02-08 +#"0.116.0.0","0.119.255.255","7602176","7864319","","" + +# NL, because previous MaxMind entry 31.171.128.0-31.171.133.255 is NL, +# and RIR delegation files say 31.171.128.0-31.171.135.255 is NL. +# -KL 2012-11-27 +"31.171.134.0","31.171.135.255","531334656","531335167","NL","Netherlands" + +# EU, because next MaxMind entry 37.139.64.1-37.139.64.9 is EU, because +# RIR delegation files say 37.139.64.0-37.139.71.255 is EU, and because it +# just makes more sense for the next entry to start at .0 and not .1. +# -KL 2012-11-27 +"37.139.64.0","37.139.64.0","629882880","629882880","EU","Europe" + +# CH, because previous MaxMind entry 46.19.141.0-46.19.142.255 is CH, and +# RIR delegation files say 46.19.136.0-46.19.143.255 is CH. +# -KL 2012-11-27 +"46.19.143.0","46.19.143.255","773033728","773033983","CH","Switzerland" + +# GB, because next MaxMind entry 46.166.129.0-46.166.134.255 is GB, and +# RIR delegation files say 46.166.128.0-46.166.191.255 is GB. +# -KL 2012-11-27 +"46.166.128.0","46.166.128.255","782663680","782663935","GB","United Kingdom" + +# US, though could as well be CA. Previous MaxMind entry +# 64.237.32.52-64.237.34.127 is US, next MaxMind entry +# 64.237.34.144-64.237.34.151 is CA, and RIR delegation files say the +# entire block 64.237.32.0-64.237.63.255 is US. -KL 2012-11-27 +"64.237.34.128","64.237.34.143","1089282688","1089282703","US","United States" + +# US, though could as well be UY. Previous MaxMind entry +# 67.15.170.0-67.15.182.255 is US, next MaxMind entry +# 67.15.183.128-67.15.183.159 is UY, and RIR delegation files say the +# entire block 67.15.0.0-67.15.255.255 is US. -KL 2012-11-27 +"67.15.183.0","67.15.183.127","1125103360","1125103487","US","United States" + +# US, because next MaxMind entry 67.43.145.0-67.43.155.255 is US, and RIR +# delegation files say 67.43.144.0-67.43.159.255 is US. +# -KL 2012-11-27 +"67.43.144.0","67.43.144.255","1126928384","1126928639","US","United States" + +# US, because previous MaxMind entry 70.159.21.51-70.232.244.255 is US, +# because next MaxMind entry 70.232.245.58-70.232.245.59 is A2 ("Satellite +# Provider") which is a country information about as useless as A1, and +# because RIR delegation files say 70.224.0.0-70.239.255.255 is US. +# -KL 2012-11-27 +"70.232.245.0","70.232.245.57","1189672192","1189672249","US","United States" + +# US, because next MaxMind entry 70.232.246.0-70.240.141.255 is US, +# because previous MaxMind entry 70.232.245.58-70.232.245.59 is A2 +# ("Satellite Provider") which is a country information about as useless +# as A1, and because RIR delegation files say 70.224.0.0-70.239.255.255 is +# US. -KL 2012-11-27 +"70.232.245.60","70.232.245.255","1189672252","1189672447","US","United States" + +# GB, despite neither previous (GE) nor next (LV) MaxMind entry being GB, +# but because RIR delegation files agree with both previous and next +# MaxMind entry and say GB for 91.228.0.0-91.228.3.255. -KL 2012-11-27 +"91.228.0.0","91.228.3.255","1541668864","1541669887","GB","United Kingdom" + +# GB, because next MaxMind entry 91.232.125.0-91.232.125.255 is GB, and +# RIR delegation files say 91.232.124.0-91.232.125.255 is GB. +# -KL 2012-11-27 +"91.232.124.0","91.232.124.255","1541962752","1541963007","GB","United Kingdom" + +# GB, despite neither previous (RU) nor next (PL) MaxMind entry being GB, +# but because RIR delegation files agree with both previous and next +# MaxMind entry and say GB for 91.238.214.0-91.238.215.255. +# -KL 2012-11-27 +"91.238.214.0","91.238.215.255","1542379008","1542379519","GB","United Kingdom" + +# US, because next MaxMind entry 173.0.16.0-173.0.65.255 is US, and RIR +# delegation files say 173.0.0.0-173.0.15.255 is US. -KL 2012-11-27 +"173.0.0.0","173.0.15.255","2902458368","2902462463","US","United States" + +# US, because next MaxMind entry 176.67.84.0-176.67.84.79 is US, and RIR +# delegation files say 176.67.80.0-176.67.87.255 is US. -KL 2012-11-27 +"176.67.80.0","176.67.83.255","2957201408","2957202431","US","United States" + +# US, because previous MaxMind entry 176.67.84.192-176.67.85.255 is US, +# and RIR delegation files say 176.67.80.0-176.67.87.255 is US. +# -KL 2012-11-27 +"176.67.86.0","176.67.87.255","2957202944","2957203455","US","United States" + +# EU, despite neither previous (RU) nor next (UA) MaxMind entry being EU, +# but because RIR delegation files agree with both previous and next +# MaxMind entry and say EU for 193.200.150.0-193.200.150.255. +# -KL 2012-11-27 +"193.200.150.0","193.200.150.255","3251148288","3251148543","EU","Europe" + +# US, because previous MaxMind entry 199.96.68.0-199.96.87.127 is US, and +# RIR delegation files say 199.96.80.0-199.96.87.255 is US. +# -KL 2012-11-27 +"199.96.87.128","199.96.87.255","3344979840","3344979967","US","United States" + +# US, because previous MaxMind entry 209.58.176.144-209.59.31.255 is US, +# and RIR delegation files say 209.59.32.0-209.59.63.255 is US. +# -KL 2012-11-27 +"209.59.32.0","209.59.63.255","3510312960","3510321151","US","United States" + +# FR, because previous MaxMind entry 217.15.166.0-217.15.166.255 is FR, +# and RIR delegation files contain a block 217.15.160.0-217.15.175.255 +# which, however, is EU, not FR. But merging with next MaxMind entry +# 217.15.176.0-217.15.191.255 which is KZ and which fully matches what +# the RIR delegation files say seems unlikely to be correct. +# -KL 2012-11-27 +"217.15.167.0","217.15.175.255","3641681664","3641683967","FR","France" + diff --git a/src/config/geoip6 b/src/config/geoip6 new file mode 100644 index 0000000000..0804892d43 --- /dev/null +++ b/src/config/geoip6 @@ -0,0 +1,18119 @@ +# Last updated based on June 4 2014 Maxmind GeoLite2 Country +# wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz +# gunzip GeoLite2-Country.mmdb.gz +# python mmdb-convert.py GeoLite2-Country.mmdb +2001:218::,2001:218:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:220::,2001:220:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:230::,2001:230:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:238::,2001:238:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:240::,2001:240:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:250::,2001:252:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:254::,2001:254:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:256::,2001:256:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:258::,2001:258:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:260::,2001:260:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:268::,2001:268:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:270::,2001:270:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:278::,2001:278:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:280::,2001:280:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:288::,2001:288:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:290::,2001:290:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:298::,2001:298:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:2a0::,2001:2a0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:2a8::,2001:2a8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:2b0::,2001:2b0:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:2b8::,2001:2b8:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:2c0::,2001:2c0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:2c8::,2001:2c8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:2d8::,2001:2d8:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:2e0::,2001:2e0:ffff:ffff:ffff:ffff:ffff:ffff,HK +2001:2e8::,2001:2e8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:2f0::,2001:2f0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:2f8::,2001:2f8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:300::,2001:300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:308::,2001:308:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:310::,2001:310:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:318::,2001:318:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:320::,2001:320:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:328::,2001:328:ffff:ffff:ffff:ffff:ffff:ffff,MY +2001:330::,2001:330:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:338::,2001:338:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:340::,2001:340:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:348::,2001:348:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:350::,2001:350:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:358::,2001:358:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:360::,2001:360:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:368::,2001:368:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:370::,2001:370:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:378::,2001:378:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:380::,2001:380:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:388::,2001:388:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:390::,2001:390:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:398::,2001:398:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:3a0::,2001:3a0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:3a8::,2001:3a8:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:3b0::,2001:3b0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:3b8::,2001:3b8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:3c0::,2001:3c0:1fff:ffff:ffff:ffff:ffff:ffff,JP +2001:3c8::,2001:3c8:ffff:ffff:ffff:ffff:ffff:ffff,TH +2001:3d0::,2001:3d0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:3d8::,2001:3d8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:3e0::,2001:3e0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:3e8::,2001:3e8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:400::,2001:400:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:408::,2001:408:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:410::,2001:410:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:418::,2001:418:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:420::,2001:420:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:428::,2001:428:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:430::,2001:430:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:438::,2001:438:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:440::,2001:440:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:448::,2001:448:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:450::,2001:450:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:458::,2001:458:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:460::,2001:460:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:468::,2001:468:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:470::,2001:470:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:478::,2001:478:ffff:ffff:ffff:ffff:ffff:ffff,KN +2001:480::,2001:480:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:490::,2001:490:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4a0::,2001:4a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4b0::,2001:4b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4b8::,2001:4b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4c0::,2001:4c0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:4c8::,2001:4c8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:4d0::,2001:4d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4e0::,2001:4e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4e8::,2001:4e8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:4f0::,2001:4f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4f8::,2001:4f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:500:1::,2001:500:4:ffff:ffff:ffff:ffff:ffff,US +2001:500:6::,2001:500:f:ffff:ffff:ffff:ffff:ffff,CA +2001:500:10::,2001:500:10:ffff:ffff:ffff:ffff:ffff,PR +2001:500:11::,2001:500:15:ffff:ffff:ffff:ffff:ffff,US +2001:500:16::,2001:500:2c:ffff:ffff:ffff:ffff:ffff,CA +2001:500:2d::,2001:500:31:ffff:ffff:ffff:ffff:ffff,US +2001:500:40::,2001:500:56:ffff:ffff:ffff:ffff:ffff,CA +2001:500:60::,2001:500:7d:ffff:ffff:ffff:ffff:ffff,US +2001:500:80::,2001:500:83:ffff:ffff:ffff:ffff:ffff,CA +2001:500:84::,2001:500:89:ffff:ffff:ffff:ffff:ffff,US +2001:500:8c::,2001:500:9a:ffff:ffff:ffff:ffff:ffff,US +2001:500:9c::,2001:500:9f:ffff:ffff:ffff:ffff:ffff,US +2001:500:a0::,2001:500:a7:ffff:ffff:ffff:ffff:ffff,CA +2001:500:a8::,2001:500:a8:ffff:ffff:ffff:ffff:ffff,US +2001:500:c0::,2001:500:ef:ffff:ffff:ffff:ffff:ffff,CA +2001:500:f0::,2001:500:f0:ffff:ffff:ffff:ffff:ffff,US +2001:500:f1::,2001:500:f1:ffff:ffff:ffff:ffff:ffff,CA +2001:500:100::,2001:500:109:ffff:ffff:ffff:ffff:ffff,CA +2001:500:3e5::,2001:500:3e5:ffff:ffff:ffff:ffff:ffff,US +2001:500:30ff::,2001:500:30ff:ffff:ffff:ffff:ffff:ffff,US +2001:500:3682::,2001:500:3682:ffff:ffff:ffff:ffff:ffff,US +2001:500:4431::,2001:500:4431:ffff:ffff:ffff:ffff:ffff,US +2001:500:7967::,2001:500:7967:ffff:ffff:ffff:ffff:ffff,US +2001:500:856e::,2001:500:856e:ffff:ffff:ffff:ffff:ffff,US +2001:500:d937::,2001:500:d937:ffff:ffff:ffff:ffff:ffff,US +2001:500:ed30::,2001:500:ed30:ffff:ffff:ffff:ffff:ffff,US +2001:501:8a29::,2001:501:8a29:ffff:ffff:ffff:ffff:ffff,US +2001:501:973c::,2001:501:973c:ffff:ffff:ffff:ffff:ffff,US +2001:501:b1f9::,2001:501:b1f9:ffff:ffff:ffff:ffff:ffff,US +2001:502:8cc::,2001:502:8cc:ffff:ffff:ffff:ffff:ffff,US +2001:502:100e::,2001:502:100e:ffff:ffff:ffff:ffff:ffff,US +2001:502:1ca1::,2001:502:1ca1:ffff:ffff:ffff:ffff:ffff,US +2001:502:2eda::,2001:502:2eda:ffff:ffff:ffff:ffff:ffff,US +2001:502:4612::,2001:502:4612:ffff:ffff:ffff:ffff:ffff,US +2001:502:63bd::,2001:502:63bd:ffff:ffff:ffff:ffff:ffff,US +2001:502:7094::,2001:502:7094:ffff:ffff:ffff:ffff:ffff,US +2001:502:7a71::,2001:502:7a71:ffff:ffff:ffff:ffff:ffff,US +2001:502:8c25::,2001:502:8c25:ffff:ffff:ffff:ffff:ffff,US +2001:502:ad09::,2001:502:ad09:ffff:ffff:ffff:ffff:ffff,US +2001:502:be98::,2001:502:be98:ffff:ffff:ffff:ffff:ffff,US +2001:502:cbe4::,2001:502:cbe4:ffff:ffff:ffff:ffff:ffff,US +2001:502:cfb5::,2001:502:cfb5:ffff:ffff:ffff:ffff:ffff,US +2001:502:d399::,2001:502:d399:ffff:ffff:ffff:ffff:ffff,US +2001:502:f3ff::,2001:502:f3ff:ffff:ffff:ffff:ffff:ffff,US +2001:503:c27::,2001:503:c27:ffff:ffff:ffff:ffff:ffff,US +2001:503:d2d::,2001:503:d2d:ffff:ffff:ffff:ffff:ffff,US +2001:503:231d::,2001:503:231d:ffff:ffff:ffff:ffff:ffff,US +2001:503:3227::,2001:503:3227:ffff:ffff:ffff:ffff:ffff,US +2001:503:39c1::,2001:503:39c1:ffff:ffff:ffff:ffff:ffff,US +2001:503:4872::,2001:503:4872:ffff:ffff:ffff:ffff:ffff,US +2001:503:5419::,2001:503:5419:ffff:ffff:ffff:ffff:ffff,US +2001:503:5ae2::,2001:503:5ae2:ffff:ffff:ffff:ffff:ffff,US +2001:503:6810::,2001:503:6810:ffff:ffff:ffff:ffff:ffff,US +2001:503:7bbb::,2001:503:7bbb:ffff:ffff:ffff:ffff:ffff,US +2001:503:7bbf::,2001:503:7bbf:ffff:ffff:ffff:ffff:ffff,US +2001:503:8028::,2001:503:8028:ffff:ffff:ffff:ffff:ffff,US +2001:503:83eb::,2001:503:83eb:ffff:ffff:ffff:ffff:ffff,US +2001:503:91ef::,2001:503:91ef:ffff:ffff:ffff:ffff:ffff,US +2001:503:a124::,2001:503:a124:ffff:ffff:ffff:ffff:ffff,US +2001:503:a83e::,2001:503:a83e:ffff:ffff:ffff:ffff:ffff,US +2001:503:ba3e::,2001:503:ba3e:ffff:ffff:ffff:ffff:ffff,US +2001:503:bfb0::,2001:503:bfb0:ffff:ffff:ffff:ffff:ffff,US +2001:503:c779::,2001:503:c779:ffff:ffff:ffff:ffff:ffff,US +2001:503:cc2c::,2001:503:cc2c:ffff:ffff:ffff:ffff:ffff,US +2001:503:d1ae::,2001:503:d1ae:ffff:ffff:ffff:ffff:ffff,US +2001:503:d414::,2001:503:d414:ffff:ffff:ffff:ffff:ffff,US +2001:503:e239::,2001:503:e239:ffff:ffff:ffff:ffff:ffff,US +2001:503:e8ef::,2001:503:e8ef:ffff:ffff:ffff:ffff:ffff,US +2001:503:eea3::,2001:503:eea3:ffff:ffff:ffff:ffff:ffff,US +2001:503:f189::,2001:503:f189:ffff:ffff:ffff:ffff:ffff,US +2001:503:f261::,2001:503:f261:ffff:ffff:ffff:ffff:ffff,US +2001:503:f3da::,2001:503:f3da:ffff:ffff:ffff:ffff:ffff,US +2001:503:ff39::,2001:503:ff39:ffff:ffff:ffff:ffff:ffff,US +2001:504::,2001:504:13:ffff:ffff:ffff:ffff:ffff,US +2001:504:15::,2001:504:15:ffff:ffff:ffff:ffff:ffff,CA +2001:504:16::,2001:504:19:ffff:ffff:ffff:ffff:ffff,US +2001:504:1a::,2001:504:1a:ffff:ffff:ffff:ffff:ffff,CA +2001:504:1b::,2001:504:1c:ffff:ffff:ffff:ffff:ffff,US +2001:504:1d::,2001:504:1d:ffff:ffff:ffff:ffff:ffff,PR +2001:504:20::,2001:504:23:ffff:ffff:ffff:ffff:ffff,CA +2001:504:24::,2001:504:24:ffff:ffff:ffff:ffff:ffff,US +2001:504:25::,2001:504:26:ffff:ffff:ffff:ffff:ffff,CA +2001:504:27::,2001:504:2a:ffff:ffff:ffff:ffff:ffff,US +2001:504:2b::,2001:504:2d:ffff:ffff:ffff:ffff:ffff,CA +2001:504:2e::,2001:504:2e:ffff:ffff:ffff:ffff:ffff,US +2001:504:2f::,2001:504:2f:ffff:ffff:ffff:ffff:ffff,CA +2001:506::,2001:506:1:ffff:ffff:ffff:ffff:ffff,US +2001:506:8::,2001:506:8:ffff:ffff:ffff:ffff:ffff,US +2001:506:20::,2001:506:20:ffff:ffff:ffff:ffff:ffff,CA +2001:506:28::,2001:506:28:ffff:ffff:ffff:ffff:ffff,US +2001:506:100::,2001:506:100:ffff:ffff:ffff:ffff:ffff,US +2001:506:1000::,2001:506:2fff:ffff:ffff:ffff:ffff:ffff,US +2001:506:4000::,2001:506:7fff:ffff:ffff:ffff:ffff:ffff,US +2001:508::,2001:508:ffff:ffff:ffff:ffff:ffff:ffff,BM +2001:510::,2001:510:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:518::,2001:518:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:520::,2001:520:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:528::,2001:528:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:530::,2001:530:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:538::,2001:538:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:540::,2001:540:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:548::,2001:548:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:550::,2001:550:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:558::,2001:560:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:568::,2001:56f:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:570::,2001:570:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:578::,2001:57b:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:580::,2001:580:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:590::,2001:590:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:598::,2001:598:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:5a0::,2001:5a0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:5a8::,2001:5a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5b0::,2001:5b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5b8::,2001:5b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5c0::,2001:5c0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:5c8::,2001:5c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5d0::,2001:5d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5d8::,2001:5d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5e0::,2001:5e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5e8::,2001:5e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5f0::,2001:5f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:5f8::,2001:5f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:608::,2001:608:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:610::,2001:610:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:618::,2001:618:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:620::,2001:620:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:628::,2001:62f:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:630::,2001:630:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:638::,2001:638:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:640::,2001:640:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:648::,2001:648:ffff:ffff:ffff:ffff:ffff:ffff,GR +2001:650::,2001:658:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:660::,2001:667:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:668::,2001:66f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:670::,2001:673:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:678:1::,2001:678:1:ffff:ffff:ffff:ffff:ffff,CZ +2001:678:2::,2001:678:2:ffff:ffff:ffff:ffff:ffff,DE +2001:678:3::,2001:678:3:ffff:ffff:ffff:ffff:ffff,CH +2001:678:4::,2001:678:5:ffff:ffff:ffff:ffff:ffff,GB +2001:678:6::,2001:678:6:ffff:ffff:ffff:ffff:ffff,LT +2001:678:7::,2001:678:7:ffff:ffff:ffff:ffff:ffff,GR +2001:678:8::,2001:678:8:ffff:ffff:ffff:ffff:ffff,NL +2001:678:9::,2001:678:a:ffff:ffff:ffff:ffff:ffff,BE +2001:678:b::,2001:678:b:ffff:ffff:ffff:ffff:ffff,LV +2001:678:c::,2001:678:c:ffff:ffff:ffff:ffff:ffff,FR +2001:678:d::,2001:678:d:ffff:ffff:ffff:ffff:ffff,AT +2001:678:e::,2001:678:e:ffff:ffff:ffff:ffff:ffff,DE +2001:678:f::,2001:678:11:ffff:ffff:ffff:ffff:ffff,CZ +2001:678:12::,2001:678:12:ffff:ffff:ffff:ffff:ffff,IT +2001:678:13::,2001:678:18:ffff:ffff:ffff:ffff:ffff,RU +2001:678:19::,2001:678:19:ffff:ffff:ffff:ffff:ffff,LT +2001:678:1a::,2001:678:1a:ffff:ffff:ffff:ffff:ffff,DK +2001:678:1b::,2001:678:1b:ffff:ffff:ffff:ffff:ffff,LU +2001:678:1c::,2001:678:1c:ffff:ffff:ffff:ffff:ffff,AT +2001:678:20::,2001:678:20:ffff:ffff:ffff:ffff:ffff,AT +2001:678:24::,2001:678:24:ffff:ffff:ffff:ffff:ffff,AT +2001:678:28::,2001:678:28:ffff:ffff:ffff:ffff:ffff,SM +2001:678:2c::,2001:678:2c:ffff:ffff:ffff:ffff:ffff,NL +2001:678:30::,2001:678:30:ffff:ffff:ffff:ffff:ffff,NL +2001:678:34::,2001:678:34:ffff:ffff:ffff:ffff:ffff,NL +2001:678:38::,2001:678:38:ffff:ffff:ffff:ffff:ffff,NL +2001:678:3c::,2001:678:3c:ffff:ffff:ffff:ffff:ffff,BG +2001:678:40::,2001:678:40:ffff:ffff:ffff:ffff:ffff,ES +2001:678:44::,2001:678:44:ffff:ffff:ffff:ffff:ffff,ES +2001:678:48::,2001:678:48:ffff:ffff:ffff:ffff:ffff,ES +2001:678:4c::,2001:678:4c:ffff:ffff:ffff:ffff:ffff,FR +2001:678:60::,2001:678:60:ffff:ffff:ffff:ffff:ffff,LU +2001:678:64::,2001:678:64:ffff:ffff:ffff:ffff:ffff,BE +2001:678:68::,2001:678:68:ffff:ffff:ffff:ffff:ffff,BE +2001:678:6c::,2001:678:6c:ffff:ffff:ffff:ffff:ffff,BE +2001:678:70::,2001:678:70:ffff:ffff:ffff:ffff:ffff,SK +2001:678:74::,2001:678:74:ffff:ffff:ffff:ffff:ffff,DK +2001:678:78::,2001:678:78:ffff:ffff:ffff:ffff:ffff,DK +2001:678:7c::,2001:678:7c:ffff:ffff:ffff:ffff:ffff,LV +2001:678:80::,2001:678:80:ffff:ffff:ffff:ffff:ffff,LV +2001:678:84::,2001:678:84:ffff:ffff:ffff:ffff:ffff,LV +2001:678:88::,2001:678:88:ffff:ffff:ffff:ffff:ffff,LT +2001:678:8c::,2001:678:8c:ffff:ffff:ffff:ffff:ffff,LT +2001:678:90::,2001:678:90:ffff:ffff:ffff:ffff:ffff,SK +2001:678:94::,2001:678:94:ffff:ffff:ffff:ffff:ffff,EE +2001:678:98::,2001:678:98:ffff:ffff:ffff:ffff:ffff,KZ +2001:67c::,2001:67c::ffff:ffff:ffff:ffff:ffff,IE +2001:67c:4::,2001:67c:4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:8::,2001:67c:8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:c::,2001:67c:c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:10::,2001:67c:10:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:14::,2001:67c:14:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:18::,2001:67c:18:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1c::,2001:67c:1c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:20::,2001:67c:20:ffff:ffff:ffff:ffff:ffff,IE +2001:67c:24::,2001:67c:24:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2c::,2001:67c:2c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:30::,2001:67c:30:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:34::,2001:67c:34:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:38::,2001:67c:38:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:40::,2001:67c:40:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:44::,2001:67c:44:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:4c::,2001:67c:4c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:50::,2001:67c:50:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:54::,2001:67c:54:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:58::,2001:67c:58:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:5c::,2001:67c:5c:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:60::,2001:67c:60:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:64::,2001:67c:64:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:68::,2001:67c:68:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:6c::,2001:67c:6c:ffff:ffff:ffff:ffff:ffff,IS +2001:67c:70::,2001:67c:70:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:74::,2001:67c:74:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:78::,2001:67c:78:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:84::,2001:67c:84:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:88::,2001:67c:88:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:8c::,2001:67c:8c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:90::,2001:67c:90:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:94::,2001:67c:94:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:98::,2001:67c:98:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:9c::,2001:67c:9c:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:a0::,2001:67c:a0:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:a4::,2001:67c:a4:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:a8::,2001:67c:a8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:ac::,2001:67c:ac:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:b0::,2001:67c:b0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:b4::,2001:67c:b4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:b8::,2001:67c:b8:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:bc::,2001:67c:bc:ffff:ffff:ffff:ffff:ffff,EE +2001:67c:c4::,2001:67c:c4:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:c8::,2001:67c:c8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:cc::,2001:67c:cc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:d0::,2001:67c:d0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:d4::,2001:67c:d4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:d8::,2001:67c:d8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:dc::,2001:67c:dc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:e0::,2001:67c:e0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:e4::,2001:67c:e4:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:e8::,2001:67c:e8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:ec::,2001:67c:ec:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:f0::,2001:67c:f0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:f4::,2001:67c:f4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:f8::,2001:67c:f8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:fc::,2001:67c:fc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:100::,2001:67c:100:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:108::,2001:67c:108:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:10c::,2001:67c:10c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:110::,2001:67c:110:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:114::,2001:67c:114:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:118::,2001:67c:118:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:11c::,2001:67c:11c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:120::,2001:67c:120:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:124::,2001:67c:124:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:128::,2001:67c:128:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:12c::,2001:67c:12c:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:130::,2001:67c:130:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:134::,2001:67c:134:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:138::,2001:67c:138:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:13c::,2001:67c:13c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:140::,2001:67c:140:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:148::,2001:67c:148:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:14c::,2001:67c:14d:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:154::,2001:67c:154:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:158::,2001:67c:158:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:15c::,2001:67c:15c:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:160::,2001:67c:160:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:164::,2001:67c:164:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:168::,2001:67c:168:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:170::,2001:67c:170:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:174::,2001:67c:174:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:178::,2001:67c:178:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:17c::,2001:67c:17c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:180::,2001:67c:180:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:184::,2001:67c:184:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:188::,2001:67c:188:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:18c::,2001:67c:18c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:190::,2001:67c:190:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:194::,2001:67c:194:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:19c::,2001:67c:19c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1a0::,2001:67c:1a0:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:1a4::,2001:67c:1a4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1a8::,2001:67c:1a8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1ac::,2001:67c:1ac:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1b0::,2001:67c:1b0:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1b4::,2001:67c:1b4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1b8::,2001:67c:1b8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1bc::,2001:67c:1bc:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1c0::,2001:67c:1c0:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1c4::,2001:67c:1c4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1c8::,2001:67c:1c8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1cc::,2001:67c:1cc:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:1d0::,2001:67c:1d0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1d4::,2001:67c:1d4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1d8::,2001:67c:1d8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1dc::,2001:67c:1dc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1e0::,2001:67c:1e0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1e4::,2001:67c:1e4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1e8::,2001:67c:1e8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1ec::,2001:67c:1ec:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:1f0::,2001:67c:1f0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1f4::,2001:67c:1f4:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:1f8::,2001:67c:1f8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1fc::,2001:67c:1fc:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:200::,2001:67c:200:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:204::,2001:67c:204:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:208::,2001:67c:208:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:20c::,2001:67c:20c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:210::,2001:67c:210:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:214::,2001:67c:214:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:218::,2001:67c:218:ffff:ffff:ffff:ffff:ffff,LT +2001:67c:21c::,2001:67c:21c:ffff:ffff:ffff:ffff:ffff,AM +2001:67c:220::,2001:67c:220:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:224::,2001:67c:224:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:228::,2001:67c:228:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:22c::,2001:67c:22c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:230::,2001:67c:230:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:234::,2001:67c:234:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:238::,2001:67c:238:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:23c::,2001:67c:23c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:240::,2001:67c:240:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:244::,2001:67c:244:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:248::,2001:67c:248:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:24c::,2001:67c:24c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:250::,2001:67c:250:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:254::,2001:67c:254:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:258::,2001:67c:258:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:25c::,2001:67c:25c:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:260::,2001:67c:260:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:264::,2001:67c:264:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:268::,2001:67c:268:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:26c::,2001:67c:26c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:270::,2001:67c:270:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:274::,2001:67c:274:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:278::,2001:67c:278:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:27c::,2001:67c:27c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:280::,2001:67c:280:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:284::,2001:67c:284:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:288::,2001:67c:288:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:28c::,2001:67c:28c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:294::,2001:67c:294:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:298::,2001:67c:298:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:29c::,2001:67c:29c:ffff:ffff:ffff:ffff:ffff,IT +2001:67c:2a0::,2001:67c:2a0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2a4::,2001:67c:2a4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2a8::,2001:67c:2a8:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2ac::,2001:67c:2ac:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2b0::,2001:67c:2b0:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:2b8::,2001:67c:2b8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2bc::,2001:67c:2bc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2c0::,2001:67c:2c0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2c4::,2001:67c:2c4:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2c8::,2001:67c:2c8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2cc::,2001:67c:2cc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2d0::,2001:67c:2d0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2d4::,2001:67c:2d4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2d8::,2001:67c:2d8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2dc::,2001:67c:2dc:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2e0::,2001:67c:2e0:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2e4::,2001:67c:2e4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2e8::,2001:67c:2e8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2ec::,2001:67c:2ec:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2f4::,2001:67c:2f4:ffff:ffff:ffff:ffff:ffff,LU +2001:67c:2f8::,2001:67c:2f8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2fc::,2001:67c:2fc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:300::,2001:67c:300:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:304::,2001:67c:304:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:308::,2001:67c:308:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:30c::,2001:67c:30c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:310::,2001:67c:310:ffff:ffff:ffff:ffff:ffff,CY +2001:67c:314::,2001:67c:314:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:318::,2001:67c:318:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:31c::,2001:67c:31c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:324::,2001:67c:324:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:328::,2001:67c:328:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:32c::,2001:67c:32c:ffff:ffff:ffff:ffff:ffff,EE +2001:67c:330::,2001:67c:330:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:334::,2001:67c:334:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:338::,2001:67c:338:ffff:ffff:ffff:ffff:ffff,IE +2001:67c:33c::,2001:67c:33c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:340::,2001:67c:340:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:344::,2001:67c:344:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:348::,2001:67c:348:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:34c::,2001:67c:34c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:350::,2001:67c:350:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:354::,2001:67c:354:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:358::,2001:67c:358:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:35c::,2001:67c:35c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:360::,2001:67c:360:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:364::,2001:67c:364:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:368::,2001:67c:368:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:36c::,2001:67c:36c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:370::,2001:67c:370:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:374::,2001:67c:374:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:37c::,2001:67c:37c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:380::,2001:67c:380:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:384::,2001:67c:384:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:388::,2001:67c:388:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:38c::,2001:67c:38c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:390::,2001:67c:390:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:394::,2001:67c:394:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:398::,2001:67c:398:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:39c::,2001:67c:39c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:3a0::,2001:67c:3a0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:3a4::,2001:67c:3a4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:3a8::,2001:67c:3a8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:3ac::,2001:67c:3ac:ffff:ffff:ffff:ffff:ffff,RS +2001:67c:3b0::,2001:67c:3b0:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:3b4::,2001:67c:3b4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:3b8::,2001:67c:3b8:ffff:ffff:ffff:ffff:ffff,IE +2001:67c:3bc::,2001:67c:3bc:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:3c0::,2001:67c:3c0:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:3c4::,2001:67c:3c4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:3c8::,2001:67c:3c8:ffff:ffff:ffff:ffff:ffff,EE +2001:67c:3cc::,2001:67c:3cc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:3d0::,2001:67c:3d0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:3d4::,2001:67c:3d4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:3d8::,2001:67c:3d8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:3dc::,2001:67c:3dc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:3e0::,2001:67c:3e0:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:3e4::,2001:67c:3e4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:3e8::,2001:67c:3e9:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:3f0::,2001:67c:3f0:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:3f4::,2001:67c:3f4:ffff:ffff:ffff:ffff:ffff,HR +2001:67c:3f8::,2001:67c:3f8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:3fc::,2001:67c:3fc:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:400::,2001:67c:400:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:404::,2001:67c:404:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:408::,2001:67c:408:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:40c::,2001:67c:40c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:410::,2001:67c:410:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:414::,2001:67c:414:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:418::,2001:67c:418:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:41c::,2001:67c:41c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:420::,2001:67c:420:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:424::,2001:67c:424:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:428::,2001:67c:428:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:42c::,2001:67c:42c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:430::,2001:67c:430:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:434::,2001:67c:434:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:438::,2001:67c:438:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:43c::,2001:67c:43c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:440::,2001:67c:440:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:444::,2001:67c:444:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:448::,2001:67c:448:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:44c::,2001:67c:44c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:450::,2001:67c:450:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:454::,2001:67c:454:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:458::,2001:67c:458:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:45c::,2001:67c:45c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:460::,2001:67c:460:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:464::,2001:67c:464:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:468::,2001:67c:468:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:46c::,2001:67c:46c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:470::,2001:67c:470:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:474::,2001:67c:474:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:478::,2001:67c:478:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:47c::,2001:67c:47c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:480::,2001:67c:480:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:484::,2001:67c:484:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:488::,2001:67c:488:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:48c::,2001:67c:48c:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:490::,2001:67c:490:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:494::,2001:67c:494:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:498::,2001:67c:498:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:49c::,2001:67c:49c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:4a0::,2001:67c:4a0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:4a4::,2001:67c:4a4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:4a8::,2001:67c:4a8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:4ac::,2001:67c:4ac:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:4b0::,2001:67c:4b0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:4b4::,2001:67c:4b4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:4b8::,2001:67c:4b8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:4bc::,2001:67c:4bc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:4c0::,2001:67c:4c0:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:4c4::,2001:67c:4c4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:4c8::,2001:67c:4c8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:4cc::,2001:67c:4cc:ffff:ffff:ffff:ffff:ffff,IL +2001:67c:4d0::,2001:67c:4d0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:4d4::,2001:67c:4d4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:4d8::,2001:67c:4d8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:4dc::,2001:67c:4dc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:4e0::,2001:67c:4e0:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:4e4::,2001:67c:4e4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:4e8::,2001:67c:4e8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:4ec::,2001:67c:4ec:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:4f0::,2001:67c:4f0:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:4f4::,2001:67c:4f4:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:4f8::,2001:67c:4f8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:4fc::,2001:67c:4fc:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:500::,2001:67c:500:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:504::,2001:67c:504:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:508::,2001:67c:508:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:50c::,2001:67c:50c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:510::,2001:67c:510:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:514::,2001:67c:514:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:518::,2001:67c:518:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:51c::,2001:67c:51c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:520::,2001:67c:520:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:524::,2001:67c:524:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:528::,2001:67c:528:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:530::,2001:67c:530:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:534::,2001:67c:534:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:538::,2001:67c:538:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:53c::,2001:67c:53c:ffff:ffff:ffff:ffff:ffff,HR +2001:67c:540::,2001:67c:540:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:544::,2001:67c:544:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:548::,2001:67c:548:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:54c::,2001:67c:54c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:550::,2001:67c:550:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:554::,2001:67c:554:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:558::,2001:67c:558:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:55c::,2001:67c:55c:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:560::,2001:67c:560:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:564::,2001:67c:564:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:568::,2001:67c:568:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:56c::,2001:67c:56c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:570::,2001:67c:570:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:574::,2001:67c:574:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:578::,2001:67c:578:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:57c::,2001:67c:57c:ffff:ffff:ffff:ffff:ffff,BY +2001:67c:580::,2001:67c:580:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:584::,2001:67c:584:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:588::,2001:67c:588:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:58c::,2001:67c:58c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:590::,2001:67c:590:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:594::,2001:67c:594:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:598::,2001:67c:598:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:59c::,2001:67c:59c:ffff:ffff:ffff:ffff:ffff,HU +2001:67c:5a0::,2001:67c:5a1:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:5a8::,2001:67c:5a8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:5ac::,2001:67c:5ac:ffff:ffff:ffff:ffff:ffff,BY +2001:67c:5b0::,2001:67c:5b0:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:5b4::,2001:67c:5b4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:5b8::,2001:67c:5b8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:5bc::,2001:67c:5bc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:5c0::,2001:67c:5c0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:5c4::,2001:67c:5c4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:5c8::,2001:67c:5c8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:5cc::,2001:67c:5cc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:5d0::,2001:67c:5d0:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:5d4::,2001:67c:5d4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:5d8::,2001:67c:5d8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:5dc::,2001:67c:5dc:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:5e0::,2001:67c:5e0:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:5e4::,2001:67c:5e4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:5e8::,2001:67c:5e8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:5ec::,2001:67c:5ec:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:5f0::,2001:67c:5f0:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:5f4::,2001:67c:5f4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:5f8::,2001:67c:5f8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:5fc::,2001:67c:5fc:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:600::,2001:67c:600:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1000::,2001:67c:1001:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1008::,2001:67c:1009:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1010::,2001:67c:1011:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1018::,2001:67c:1019:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1020::,2001:67c:1021:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1028::,2001:67c:1029:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1030::,2001:67c:1030:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1034::,2001:67c:1034:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1038::,2001:67c:1038:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:103c::,2001:67c:103c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1040::,2001:67c:1040:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1044::,2001:67c:1044:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1048::,2001:67c:1048:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:104c::,2001:67c:104c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1050::,2001:67c:1050:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1054::,2001:67c:1054:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1058::,2001:67c:1058:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:105c::,2001:67c:105c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1060::,2001:67c:1060:ffff:ffff:ffff:ffff:ffff,LU +2001:67c:1064::,2001:67c:1064:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1068::,2001:67c:1068:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:106c::,2001:67c:106c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1070::,2001:67c:1071:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:1078::,2001:67c:1078:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:107c::,2001:67c:107c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1080::,2001:67c:1080:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1084::,2001:67c:1084:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1090::,2001:67c:1090:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1098::,2001:67c:1098:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:109c::,2001:67c:109c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:10a0::,2001:67c:10a0:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:10a4::,2001:67c:10a4:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:10a8::,2001:67c:10a9:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:10b0::,2001:67c:10b0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:10b4::,2001:67c:10b4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:10b8::,2001:67c:10b8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:10bc::,2001:67c:10bc:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:10c0::,2001:67c:10c0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:10c4::,2001:67c:10c4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:10c8::,2001:67c:10c8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:10cc::,2001:67c:10cc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:10d0::,2001:67c:10d0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:10d4::,2001:67c:10d4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:10d8::,2001:67c:10d8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:10dc::,2001:67c:10dc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:10e0::,2001:67c:10e0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:10e4::,2001:67c:10e4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:10e8::,2001:67c:10e8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:10ec::,2001:67c:10ec:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:10f0::,2001:67c:10f0:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:10f4::,2001:67c:10f4:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:10f8::,2001:67c:10f8:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:10fc::,2001:67c:10fc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1100::,2001:67c:1100:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1104::,2001:67c:1104:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1108::,2001:67c:1109:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1110::,2001:67c:1111:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1118::,2001:67c:1118:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:111c::,2001:67c:111c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1120::,2001:67c:1120:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1124::,2001:67c:1124:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:1128::,2001:67c:1128:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:112c::,2001:67c:112c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1130::,2001:67c:1130:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1134::,2001:67c:1134:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1138::,2001:67c:1138:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:113c::,2001:67c:113c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1140::,2001:67c:1140:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1144::,2001:67c:1144:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1148::,2001:67c:1148:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:114c::,2001:67c:114c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1150::,2001:67c:1150:ffff:ffff:ffff:ffff:ffff,IL +2001:67c:1154::,2001:67c:1154:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:1158::,2001:67c:1158:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:115c::,2001:67c:115c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1160::,2001:67c:1160:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1164::,2001:67c:1164:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:116c::,2001:67c:116c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1170::,2001:67c:1170:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1174::,2001:67c:1174:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1178::,2001:67c:1178:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:117c::,2001:67c:117c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1180::,2001:67c:1180:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1184::,2001:67c:1184:ffff:ffff:ffff:ffff:ffff,HR +2001:67c:1188::,2001:67c:1188:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:118c::,2001:67c:118c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1190::,2001:67c:1190:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1194::,2001:67c:1194:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1198::,2001:67c:1199:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:11a0::,2001:67c:11a0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:11a4::,2001:67c:11a4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:11a8::,2001:67c:11a8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:11ac::,2001:67c:11ac:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:11b0::,2001:67c:11b0:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:11b4::,2001:67c:11b4:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:11b8::,2001:67c:11b8:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:11bc::,2001:67c:11bc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:11c0::,2001:67c:11c0:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:11c4::,2001:67c:11c4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:11c8::,2001:67c:11c8:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:11cc::,2001:67c:11cc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:11d0::,2001:67c:11d0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:11d4::,2001:67c:11d4:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:11d8::,2001:67c:11d8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:11dc::,2001:67c:11dc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:11e0::,2001:67c:11e0:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:11e4::,2001:67c:11e4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:11e8::,2001:67c:11e8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:11ec::,2001:67c:11ec:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:11f4::,2001:67c:11f4:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:11f8::,2001:67c:11f8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:11fc::,2001:67c:11fc:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1200::,2001:67c:1203:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1210::,2001:67c:1213:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1220::,2001:67c:1223:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1230::,2001:67c:1233:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1240::,2001:67c:1240:ffff:ffff:ffff:ffff:ffff,IE +2001:67c:1244::,2001:67c:1244:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1248::,2001:67c:1248:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:124c::,2001:67c:124c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1250::,2001:67c:1250:ffff:ffff:ffff:ffff:ffff,LU +2001:67c:1254::,2001:67c:1254:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:125c::,2001:67c:125c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1260::,2001:67c:1260:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1264::,2001:67c:1264:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1268::,2001:67c:1268:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:126c::,2001:67c:126c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1270::,2001:67c:1270:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1274::,2001:67c:1274:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1278::,2001:67c:1278:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1280::,2001:67c:1280:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1284::,2001:67c:1284:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1288::,2001:67c:1288:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:128c::,2001:67c:128c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1294::,2001:67c:1294:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:129c::,2001:67c:129c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:12a0::,2001:67c:12a0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:12a4::,2001:67c:12a4:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:12a8::,2001:67c:12a8:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:12ac::,2001:67c:12ac:ffff:ffff:ffff:ffff:ffff,LU +2001:67c:12b0::,2001:67c:12b0:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:12b4::,2001:67c:12b4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:12b8::,2001:67c:12b8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:12bc::,2001:67c:12bc:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:12c0::,2001:67c:12c1:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:12c8::,2001:67c:12c8:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:12cc::,2001:67c:12cc:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:12d0::,2001:67c:12d0:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:12d4::,2001:67c:12d4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:12d8::,2001:67c:12d8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:12dc::,2001:67c:12dc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:12e0::,2001:67c:12e0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:12e4::,2001:67c:12e4:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:12e8::,2001:67c:12e9:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:12f0::,2001:67c:12f0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:12f4::,2001:67c:12f4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:12f8::,2001:67c:12f8:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:12fc::,2001:67c:12fc:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1300::,2001:67c:1300:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1304::,2001:67c:1304:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1308::,2001:67c:1308:ffff:ffff:ffff:ffff:ffff,MD +2001:67c:130c::,2001:67c:130c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1310::,2001:67c:1310:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1314::,2001:67c:1314:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1318::,2001:67c:1318:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:131c::,2001:67c:131c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1320::,2001:67c:1320:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1324::,2001:67c:1324:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1328::,2001:67c:1328:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:132c::,2001:67c:132c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1330::,2001:67c:1330:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1334::,2001:67c:1334:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1338::,2001:67c:1338:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:133c::,2001:67c:133c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1340::,2001:67c:1340:ffff:ffff:ffff:ffff:ffff,HR +2001:67c:1344::,2001:67c:1344:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1348::,2001:67c:1348:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:134c::,2001:67c:134c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1350::,2001:67c:1350:ffff:ffff:ffff:ffff:ffff,CY +2001:67c:1354::,2001:67c:1354:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1358::,2001:67c:1358:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:135c::,2001:67c:135c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1360::,2001:67c:1360:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1364::,2001:67c:1364:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1368::,2001:67c:1368:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:136c::,2001:67c:136c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1370::,2001:67c:1370:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1374::,2001:67c:1374:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1378::,2001:67c:1378:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:137c::,2001:67c:137c:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:1380::,2001:67c:1380:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1384::,2001:67c:1384:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1388::,2001:67c:1388:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:138c::,2001:67c:138c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1390::,2001:67c:1390:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1394::,2001:67c:1394:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1398::,2001:67c:1398:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:139c::,2001:67c:139c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:13a0::,2001:67c:13a0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:13a4::,2001:67c:13a4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:13a8::,2001:67c:13a8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:13ac::,2001:67c:13ac:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:13b0::,2001:67c:13b0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:13b4::,2001:67c:13b4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:13b8::,2001:67c:13b8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:13bc::,2001:67c:13bc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:13c0::,2001:67c:13c0:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:13c4::,2001:67c:13c4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:13c8::,2001:67c:13c8:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:13cc::,2001:67c:13cc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:13d0::,2001:67c:13d0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:13d4::,2001:67c:13d4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:13d8::,2001:67c:13d8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:13e0::,2001:67c:13e0:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:13e4::,2001:67c:13e4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:13e8::,2001:67c:13e8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:13ec::,2001:67c:13ec:ffff:ffff:ffff:ffff:ffff,PT +2001:67c:13f0::,2001:67c:13f0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:13f4::,2001:67c:13f4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:13f8::,2001:67c:13f8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:13fc::,2001:67c:13fc:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1400::,2001:67c:1407:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1420::,2001:67c:1427:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1440::,2001:67c:1447:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1460::,2001:67c:1467:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1480::,2001:67c:1480:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1484::,2001:67c:1484:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1488::,2001:67c:1488:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:148c::,2001:67c:148c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1490::,2001:67c:1490:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1494::,2001:67c:1494:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1498::,2001:67c:1498:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:149c::,2001:67c:149c:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:14a0::,2001:67c:14a0:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:14a4::,2001:67c:14a4:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:14a8::,2001:67c:14a8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:14ac::,2001:67c:14ac:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:14b0::,2001:67c:14b0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:14b4::,2001:67c:14b4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:14b8::,2001:67c:14b8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:14bc::,2001:67c:14bc:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:14c4::,2001:67c:14c4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:14d0::,2001:67c:14d0:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:14d4::,2001:67c:14d4:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:14d8::,2001:67c:14d8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:14dc::,2001:67c:14dc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:14e0::,2001:67c:14e7:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1500::,2001:67c:1500:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1504::,2001:67c:1504:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1508::,2001:67c:1508:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:150c::,2001:67c:150c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1510::,2001:67c:1510:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1514::,2001:67c:1514:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1518::,2001:67c:1518:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:151c::,2001:67c:151c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1520::,2001:67c:1520:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1524::,2001:67c:1524:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1528::,2001:67c:1528:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:152c::,2001:67c:152c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1530::,2001:67c:1530:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1534::,2001:67c:1534:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1538::,2001:67c:1538:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:153c::,2001:67c:153c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1540::,2001:67c:1540:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1544::,2001:67c:1544:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:154c::,2001:67c:154c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1554::,2001:67c:1554:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:1558::,2001:67c:1558:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:155c::,2001:67c:155c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1560::,2001:67c:1563:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1570::,2001:67c:1570:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1574::,2001:67c:1574:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1578::,2001:67c:1578:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:157c::,2001:67c:157c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1580::,2001:67c:1580:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1584::,2001:67c:1584:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:158c::,2001:67c:158c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1590::,2001:67c:1591:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1598::,2001:67c:1598:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:159c::,2001:67c:159c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:15a0::,2001:67c:15a3:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:15b0::,2001:67c:15b0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:15b8::,2001:67c:15b8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:15bc::,2001:67c:15bc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:15c0::,2001:67c:15c0:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:15c4::,2001:67c:15c4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:15c8::,2001:67c:15c8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:15cc::,2001:67c:15cc:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:15d0::,2001:67c:15d0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:15d4::,2001:67c:15d4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:15d8::,2001:67c:15d8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:15dc::,2001:67c:15dc:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:15e0::,2001:67c:15e0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:15e4::,2001:67c:15e4:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:15e8::,2001:67c:15e8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:15ec::,2001:67c:15ec:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:15f0::,2001:67c:15f0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:15f4::,2001:67c:15f4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:15f8::,2001:67c:15f8:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:15fc::,2001:67c:15fc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1600::,2001:67c:160f:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1640::,2001:67c:164f:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:1680::,2001:67c:1680:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1684::,2001:67c:1684:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:1688::,2001:67c:1688:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:168c::,2001:67c:168c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1690::,2001:67c:1690:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1694::,2001:67c:1694:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1698::,2001:67c:1698:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:169c::,2001:67c:169c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:16a0::,2001:67c:16a0:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:16a4::,2001:67c:16a4:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:16a8::,2001:67c:16a8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:16ac::,2001:67c:16ac:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:16b0::,2001:67c:16b0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:16b4::,2001:67c:16b4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:16b8::,2001:67c:16b8:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:16bc::,2001:67c:16bc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:16c0::,2001:67c:16c0:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:16c4::,2001:67c:16c4:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:16c8::,2001:67c:16c8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:16d0::,2001:67c:16d1:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:16d8::,2001:67c:16d8:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:16dc::,2001:67c:16dc:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:16e0::,2001:67c:16e0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:16e4::,2001:67c:16e4:ffff:ffff:ffff:ffff:ffff,HR +2001:67c:16e8::,2001:67c:16e8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:16ec::,2001:67c:16ec:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:16f0::,2001:67c:16f0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:16f4::,2001:67c:16f4:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:16f8::,2001:67c:16f8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:16fc::,2001:67c:16fc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1700::,2001:67c:1700:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1704::,2001:67c:1704:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1708::,2001:67c:1708:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:170c::,2001:67c:170c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1710::,2001:67c:1710:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1720::,2001:67c:1720:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1724::,2001:67c:1724:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1728::,2001:67c:1728:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:172c::,2001:67c:172c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1730::,2001:67c:1730:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1734::,2001:67c:1734:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1738::,2001:67c:1738:ffff:ffff:ffff:ffff:ffff,IL +2001:67c:173c::,2001:67c:173c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1740::,2001:67c:1740:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1744::,2001:67c:1744:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:1748::,2001:67c:1748:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:174c::,2001:67c:174c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1750::,2001:67c:1750:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1754::,2001:67c:1754:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1758::,2001:67c:1758:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:175c::,2001:67c:175c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1760::,2001:67c:1760:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:1764::,2001:67c:1764:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1768::,2001:67c:1768:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:176c::,2001:67c:176c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1770::,2001:67c:1770:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1774::,2001:67c:1774:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:177c::,2001:67c:177c:ffff:ffff:ffff:ffff:ffff,LT +2001:67c:1780::,2001:67c:1780:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1784::,2001:67c:1784:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1788::,2001:67c:1788:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:178c::,2001:67c:178c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1790::,2001:67c:1790:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1794::,2001:67c:1794:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1798::,2001:67c:1798:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:179c::,2001:67c:179c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17a0::,2001:67c:17a0:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:17a8::,2001:67c:17a8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17ac::,2001:67c:17ac:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17b0::,2001:67c:17b0:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:17b4::,2001:67c:17b4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:17b8::,2001:67c:17b8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:17bc::,2001:67c:17bc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17c0::,2001:67c:17c0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17c4::,2001:67c:17c4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17c8::,2001:67c:17c8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:17cc::,2001:67c:17cc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17d0::,2001:67c:17d0:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:17d4::,2001:67c:17d4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:17d8::,2001:67c:17d8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:17dc::,2001:67c:17dc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17e0::,2001:67c:17e0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17e4::,2001:67c:17e4:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:17e8::,2001:67c:17e8:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:17ec::,2001:67c:17ec:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:17f0::,2001:67c:17f0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17f4::,2001:67c:17f4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:17f8::,2001:67c:17f8:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:17fc::,2001:67c:17fc:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1800::,2001:67c:1800:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1804::,2001:67c:1804:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1808::,2001:67c:1809:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:1810::,2001:67c:1810:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:1814::,2001:67c:1814:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1818::,2001:67c:1818:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:181c::,2001:67c:181c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1820::,2001:67c:1820:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1828::,2001:67c:1828:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:182c::,2001:67c:182c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1830::,2001:67c:1830:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1834::,2001:67c:1834:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:1838::,2001:67c:1838:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:183c::,2001:67c:183c:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:1840::,2001:67c:1840:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1844::,2001:67c:1844:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1848::,2001:67c:1848:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:184c::,2001:67c:184c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1850::,2001:67c:1850:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1854::,2001:67c:1854:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1858::,2001:67c:1858:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:185c::,2001:67c:185c:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:1860::,2001:67c:1860:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1864::,2001:67c:1864:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1868::,2001:67c:1868:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:186c::,2001:67c:186c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1870::,2001:67c:1870:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1874::,2001:67c:1874:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1878::,2001:67c:1878:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:187c::,2001:67c:187c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1880::,2001:67c:1880:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1884::,2001:67c:1884:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1888::,2001:67c:1888:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:188c::,2001:67c:188c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1890::,2001:67c:1890:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1894::,2001:67c:1894:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1898::,2001:67c:1898:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:189c::,2001:67c:189c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:18a0::,2001:67c:18a0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:18a4::,2001:67c:18a4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:18a8::,2001:67c:18a8:ffff:ffff:ffff:ffff:ffff,BY +2001:67c:18ac::,2001:67c:18ac:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:18b0::,2001:67c:18b0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:18b4::,2001:67c:18b4:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:18b8::,2001:67c:18b8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:18bc::,2001:67c:18bc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:18c0::,2001:67c:18c0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:18c4::,2001:67c:18c4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:18c8::,2001:67c:18c9:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:18d0::,2001:67c:18d0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:18d4::,2001:67c:18d4:ffff:ffff:ffff:ffff:ffff,NZ +2001:67c:18d8::,2001:67c:18d8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:18dc::,2001:67c:18dc:ffff:ffff:ffff:ffff:ffff,LI +2001:67c:18e0::,2001:67c:18e0:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:18e4::,2001:67c:18e4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:18e8::,2001:67c:18e8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:18ec::,2001:67c:18ec:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:18f0::,2001:67c:18f0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:18f4::,2001:67c:18f4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:18f8::,2001:67c:18f8:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:18fc::,2001:67c:18fc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1900::,2001:67c:1903:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:1910::,2001:67c:1910:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1914::,2001:67c:1914:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1918::,2001:67c:1918:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:191c::,2001:67c:191c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1920::,2001:67c:1920:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1924::,2001:67c:1924:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1928::,2001:67c:1928:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:192c::,2001:67c:192c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1930::,2001:67c:1933:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1940::,2001:67c:1940:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1944::,2001:67c:1944:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1948::,2001:67c:1948:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:194c::,2001:67c:194c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1950::,2001:67c:1950:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1954::,2001:67c:1954:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1958::,2001:67c:1958:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:195c::,2001:67c:195c:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:1960::,2001:67c:1960:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1964::,2001:67c:1964:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1968::,2001:67c:1968:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:196c::,2001:67c:196c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1970::,2001:67c:1970:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1974::,2001:67c:1974:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1978::,2001:67c:1978:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:197c::,2001:67c:197c:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:1980::,2001:67c:1980:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1984::,2001:67c:1984:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:1988::,2001:67c:1988:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:198c::,2001:67c:198c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1990::,2001:67c:1990:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1994::,2001:67c:1994:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1998::,2001:67c:1998:ffff:ffff:ffff:ffff:ffff,LU +2001:67c:199c::,2001:67c:199c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:19a0::,2001:67c:19a0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:19a4::,2001:67c:19a4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:19a8::,2001:67c:19a8:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:19ac::,2001:67c:19ac:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:19b0::,2001:67c:19b3:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:19c0::,2001:67c:19c0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:19c4::,2001:67c:19c4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:19c8::,2001:67c:19c8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:19cc::,2001:67c:19cc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:19d0::,2001:67c:19d0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:19d4::,2001:67c:19d4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:19d8::,2001:67c:19d8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:19dc::,2001:67c:19dc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:19e0::,2001:67c:19e0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:19e4::,2001:67c:19e4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:19e8::,2001:67c:19e8:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:19ec::,2001:67c:19ec:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:19f0::,2001:67c:19f0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:19f4::,2001:67c:19f4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:19f8::,2001:67c:19f8:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:19fc::,2001:67c:19fc:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1a00::,2001:67c:1a3f:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1b00::,2001:67c:1b00:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1b04::,2001:67c:1b04:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1b08::,2001:67c:1b08:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1b0c::,2001:67c:1b0c:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:1b10::,2001:67c:1b10:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1b14::,2001:67c:1b14:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1b18::,2001:67c:1b18:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1b1c::,2001:67c:1b1c:ffff:ffff:ffff:ffff:ffff,LU +2001:67c:1b20::,2001:67c:1b20:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1b24::,2001:67c:1b24:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1b2c::,2001:67c:1b2c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1b30::,2001:67c:1b30:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1b34::,2001:67c:1b34:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1b3c::,2001:67c:1b3c:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:1b40::,2001:67c:1b43:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1b50::,2001:67c:1b50:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1b54::,2001:67c:1b54:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1b58::,2001:67c:1b59:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:1b60::,2001:67c:1b60:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1b64::,2001:67c:1b64:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1b6c::,2001:67c:1b6c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1b70::,2001:67c:1b70:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:1b74::,2001:67c:1b74:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1b78::,2001:67c:1b78:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1b7c::,2001:67c:1b7c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1b80::,2001:67c:1b80:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1b84::,2001:67c:1b84:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1b88::,2001:67c:1b88:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1b8c::,2001:67c:1b8c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1b90::,2001:67c:1b90:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:1b94::,2001:67c:1b94:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1b98::,2001:67c:1b98:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1b9c::,2001:67c:1b9c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1ba4::,2001:67c:1ba4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1ba8::,2001:67c:1ba8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1bb0::,2001:67c:1bb0:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1bb4::,2001:67c:1bb4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1bb8::,2001:67c:1bb8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1bbc::,2001:67c:1bbc:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:1bc0::,2001:67c:1bc0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1bc4::,2001:67c:1bc4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:1bc8::,2001:67c:1bc8:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1bcc::,2001:67c:1bcc:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1bd0::,2001:67c:1bd0:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:1bd4::,2001:67c:1bd4:ffff:ffff:ffff:ffff:ffff,SK +2001:67c:1bd8::,2001:67c:1bd8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1bdc::,2001:67c:1bdc:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:1be0::,2001:67c:1be0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:1be4::,2001:67c:1be4:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:1be8::,2001:67c:1be8:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:1bec::,2001:67c:1bec:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:1bf4::,2001:67c:1bf4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:1bf8::,2001:67c:1bf8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:1bfc::,2001:67c:1bfc:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:1c00::,2001:67c:1cff:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2004::,2001:67c:2004:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2008::,2001:67c:2008:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:200c::,2001:67c:200c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2010::,2001:67c:2010:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2014::,2001:67c:2014:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2018::,2001:67c:2018:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2020::,2001:67c:2020:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2024::,2001:67c:2024:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2028::,2001:67c:2028:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:202c::,2001:67c:202c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2030::,2001:67c:2030:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2034::,2001:67c:2034:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2038::,2001:67c:2038:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:203c::,2001:67c:203c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2040::,2001:67c:2040:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:2044::,2001:67c:2044:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2048::,2001:67c:2048:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:204c::,2001:67c:204c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2050::,2001:67c:2050:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:205c::,2001:67c:205c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2060::,2001:67c:2060:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2064::,2001:67c:2064:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2068::,2001:67c:2068:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:206c::,2001:67c:206c:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2070::,2001:67c:2070:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2074::,2001:67c:2074:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2078::,2001:67c:2078:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:207c::,2001:67c:207c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2080::,2001:67c:2080:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2084::,2001:67c:2084:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2088::,2001:67c:2088:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:208c::,2001:67c:208c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:20a0::,2001:67c:20a1:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:20a8::,2001:67c:20a8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:20ac::,2001:67c:20ac:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:20b0::,2001:67c:20b0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:20b4::,2001:67c:20b4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:20b8::,2001:67c:20b9:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:20c0::,2001:67c:20c0:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:20c4::,2001:67c:20c4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:20c8::,2001:67c:20c8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:20cc::,2001:67c:20cc:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:20d0::,2001:67c:20d1:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:20d8::,2001:67c:20d8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:20dc::,2001:67c:20dc:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:20e0::,2001:67c:20e0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:20e4::,2001:67c:20e4:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:20e8::,2001:67c:20e8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:20ec::,2001:67c:20ec:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:20f0::,2001:67c:20f0:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:20f4::,2001:67c:20f4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:20f8::,2001:67c:20f8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:20fc::,2001:67c:20fc:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2100::,2001:67c:2100:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2104::,2001:67c:2104:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2108::,2001:67c:2108:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:210c::,2001:67c:210c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2110::,2001:67c:2110:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2114::,2001:67c:2114:ffff:ffff:ffff:ffff:ffff,IS +2001:67c:2118::,2001:67c:2118:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:211c::,2001:67c:211c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2120::,2001:67c:2120:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2124::,2001:67c:2124:ffff:ffff:ffff:ffff:ffff,HU +2001:67c:2128::,2001:67c:2128:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:212c::,2001:67c:212c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2130::,2001:67c:2130:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2134::,2001:67c:2134:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2138::,2001:67c:2138:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:213c::,2001:67c:213c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2144::,2001:67c:2144:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:2148::,2001:67c:2148:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:214c::,2001:67c:214c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2150::,2001:67c:2150:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2154::,2001:67c:2154:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:2158::,2001:67c:2158:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:215c::,2001:67c:215c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2160::,2001:67c:2160:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2164::,2001:67c:2164:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:2168::,2001:67c:2168:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:216c::,2001:67c:216c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2170::,2001:67c:2170:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2174::,2001:67c:2174:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2178::,2001:67c:2178:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:217c::,2001:67c:217c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2180::,2001:67c:2180:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2188::,2001:67c:2188:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:218c::,2001:67c:218c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2190::,2001:67c:2190:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2194::,2001:67c:2194:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2198::,2001:67c:2198:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:219c::,2001:67c:219c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:21a0::,2001:67c:21a0:ffff:ffff:ffff:ffff:ffff,IT +2001:67c:21a4::,2001:67c:21a4:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:21a8::,2001:67c:21a8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:21ac::,2001:67c:21ac:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:21b0::,2001:67c:21b0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:21b4::,2001:67c:21b4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:21b8::,2001:67c:21b8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:21bc::,2001:67c:21bc:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:21c0::,2001:67c:21c0:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:21c4::,2001:67c:21c4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:21c8::,2001:67c:21c8:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:21cc::,2001:67c:21cc:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:21d0::,2001:67c:21d0:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:21d8::,2001:67c:21d8:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:21dc::,2001:67c:21dc:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:21e0::,2001:67c:21e0:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:21e4::,2001:67c:21e4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:21e8::,2001:67c:21e8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:21ec::,2001:67c:21ec:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:21f0::,2001:67c:21f0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:21f4::,2001:67c:21f4:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:21f8::,2001:67c:21f8:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:21fc::,2001:67c:21fc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2200::,2001:67c:2200:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2204::,2001:67c:2204:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2208::,2001:67c:2208:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:220c::,2001:67c:220c:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:2210::,2001:67c:2210:ffff:ffff:ffff:ffff:ffff,RS +2001:67c:2214::,2001:67c:2214:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2218::,2001:67c:2219:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2220::,2001:67c:2220:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2224::,2001:67c:2224:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2228::,2001:67c:2228:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:222c::,2001:67c:222c:ffff:ffff:ffff:ffff:ffff,SK +2001:67c:2234::,2001:67c:2234:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2238::,2001:67c:2238:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:223c::,2001:67c:223c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2240::,2001:67c:2240:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2244::,2001:67c:2244:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2248::,2001:67c:2248:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2250::,2001:67c:2250:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2254::,2001:67c:2254:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2258::,2001:67c:2258:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:225c::,2001:67c:225c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2260::,2001:67c:2260:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2264::,2001:67c:2264:ffff:ffff:ffff:ffff:ffff,KG +2001:67c:2268::,2001:67c:2268:ffff:ffff:ffff:ffff:ffff,BY +2001:67c:226c::,2001:67c:226c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2270::,2001:67c:2270:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2274::,2001:67c:2274:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2278::,2001:67c:2278:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:227c::,2001:67c:227c:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2280::,2001:67c:2280:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2284::,2001:67c:2284:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2288::,2001:67c:2288:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:228c::,2001:67c:228c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2290::,2001:67c:2290:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2294::,2001:67c:2294:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:2298::,2001:67c:2298:ffff:ffff:ffff:ffff:ffff,US +2001:67c:229c::,2001:67c:229c:ffff:ffff:ffff:ffff:ffff,GR +2001:67c:22a0::,2001:67c:22a0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:22a4::,2001:67c:22a4:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:22a8::,2001:67c:22a8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:22b0::,2001:67c:22b0:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:22b4::,2001:67c:22b4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:22b8::,2001:67c:22b8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:22bc::,2001:67c:22bc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:22c0::,2001:67c:22c0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:22c4::,2001:67c:22c4:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:22c8::,2001:67c:22c8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:22cc::,2001:67c:22cc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:22d0::,2001:67c:22d0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:22d8::,2001:67c:22d8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:22dc::,2001:67c:22dc:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:22e0::,2001:67c:22e0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:22e4::,2001:67c:22e4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:22e8::,2001:67c:22e8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:22ec::,2001:67c:22ec:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:22f0::,2001:67c:22f0:ffff:ffff:ffff:ffff:ffff,RS +2001:67c:22f8::,2001:67c:22f8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:22fc::,2001:67c:22fc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2300::,2001:67c:2300:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2304::,2001:67c:2304:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2308::,2001:67c:2308:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:230c::,2001:67c:230c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2310::,2001:67c:2310:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2314::,2001:67c:2314:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2318::,2001:67c:2318:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:231c::,2001:67c:231c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2320::,2001:67c:2320:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2324::,2001:67c:2324:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2328::,2001:67c:2328:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:232c::,2001:67c:232c:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:2330::,2001:67c:2330:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2334::,2001:67c:2334:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2338::,2001:67c:2338:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:233c::,2001:67c:233c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2340::,2001:67c:2340:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2348::,2001:67c:2348:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:234c::,2001:67c:234c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2354::,2001:67c:2354:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2358::,2001:67c:2358:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:235c::,2001:67c:235c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2360::,2001:67c:2360:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2364::,2001:67c:2364:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2368::,2001:67c:2368:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:236c::,2001:67c:236c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2370::,2001:67c:2370:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2374::,2001:67c:2374:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2378::,2001:67c:2378:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:237c::,2001:67c:237c:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2380::,2001:67c:2380:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2384::,2001:67c:2384:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2388::,2001:67c:2388:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:238c::,2001:67c:238c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2394::,2001:67c:2394:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2398::,2001:67c:2398:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:239c::,2001:67c:239c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:23a0::,2001:67c:23a0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:23a4::,2001:67c:23a4:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:23a8::,2001:67c:23a8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:23b0::,2001:67c:23b0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:23b4::,2001:67c:23b4:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:23b8::,2001:67c:23b8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:23bc::,2001:67c:23bc:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:23c0::,2001:67c:23c0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:23c4::,2001:67c:23c4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:23c8::,2001:67c:23c8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:23cc::,2001:67c:23cc:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:23d4::,2001:67c:23d4:ffff:ffff:ffff:ffff:ffff,EE +2001:67c:23d8::,2001:67c:23d9:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:23e4::,2001:67c:23e4:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:23e8::,2001:67c:23e8:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:23ec::,2001:67c:23ec:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:23f0::,2001:67c:23f0:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:23f4::,2001:67c:23f4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:23f8::,2001:67c:23f8:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:23fc::,2001:67c:23fc:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:2400::,2001:67c:2400:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2404::,2001:67c:2404:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2408::,2001:67c:2408:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:240c::,2001:67c:240c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2410::,2001:67c:2410:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:2414::,2001:67c:2414:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2418::,2001:67c:2418:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2420::,2001:67c:2420:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2424::,2001:67c:2424:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2428::,2001:67c:2428:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:242c::,2001:67c:242c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2430::,2001:67c:2433:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2440::,2001:67c:2440:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2444::,2001:67c:2444:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2448::,2001:67c:2448:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:244c::,2001:67c:244c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2454::,2001:67c:2454:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:245c::,2001:67c:245c:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:2460::,2001:67c:2460:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2464::,2001:67c:2464:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2468::,2001:67c:2468:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:246c::,2001:67c:246c:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2470::,2001:67c:2470:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2474::,2001:67c:2474:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2478::,2001:67c:2478:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:247c::,2001:67c:247c:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2480::,2001:67c:2480:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2484::,2001:67c:2484:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2488::,2001:67c:2488:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:248c::,2001:67c:248c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2490::,2001:67c:2490:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2494::,2001:67c:2494:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2498::,2001:67c:2498:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:249c::,2001:67c:249c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:24a0::,2001:67c:24a0:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:24a4::,2001:67c:24a4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:24a8::,2001:67c:24a8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:24ac::,2001:67c:24ac:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:24b4::,2001:67c:24b4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:24b8::,2001:67c:24b8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:24bc::,2001:67c:24bc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:24c4::,2001:67c:24c4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:24c8::,2001:67c:24c8:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:24cc::,2001:67c:24cc:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:24d0::,2001:67c:24d0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:24d4::,2001:67c:24d4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:24d8::,2001:67c:24d8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:24dc::,2001:67c:24dc:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:24e0::,2001:67c:24e0:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:24e4::,2001:67c:24e4:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:24e8::,2001:67c:24e9:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:24f0::,2001:67c:24f0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:24f4::,2001:67c:24f4:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:24f8::,2001:67c:24f8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:24fc::,2001:67c:24fc:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2500::,2001:67c:2507:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2520::,2001:67c:2520:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2524::,2001:67c:2524:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2528::,2001:67c:2528:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:252c::,2001:67c:252c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2534::,2001:67c:2534:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2538::,2001:67c:2538:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:253c::,2001:67c:253c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2540::,2001:67c:2540:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2544::,2001:67c:2544:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2548::,2001:67c:2548:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:254c::,2001:67c:254c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2550::,2001:67c:2550:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2554::,2001:67c:2554:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2558::,2001:67c:2558:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:255c::,2001:67c:255c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2560::,2001:67c:2560:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2564::,2001:67c:2564:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:256c::,2001:67c:256c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2574::,2001:67c:2574:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2578::,2001:67c:2578:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:257c::,2001:67c:257c:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2580::,2001:67c:2580:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2584::,2001:67c:2584:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2588::,2001:67c:2588:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:258c::,2001:67c:258c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2590::,2001:67c:2590:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2594::,2001:67c:2594:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2598::,2001:67c:2598:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:259c::,2001:67c:259c:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:25a0::,2001:67c:25a0:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:25a4::,2001:67c:25a4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:25a8::,2001:67c:25a8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:25ac::,2001:67c:25ac:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:25b0::,2001:67c:25b0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:25b4::,2001:67c:25b4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:25b8::,2001:67c:25b8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:25bc::,2001:67c:25bc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:25c0::,2001:67c:25c0:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:25c4::,2001:67c:25c4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:25cc::,2001:67c:25cc:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:25d0::,2001:67c:25d0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:25d4::,2001:67c:25d4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:25d8::,2001:67c:25d8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:25dc::,2001:67c:25dc:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:25e4::,2001:67c:25e4:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:25f4::,2001:67c:25f4:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:25fc::,2001:67c:25fc:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2600::,2001:67c:2600:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2604::,2001:67c:2604:ffff:ffff:ffff:ffff:ffff,SK +2001:67c:260c::,2001:67c:260c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2610::,2001:67c:2610:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2614::,2001:67c:2614:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2618::,2001:67c:2618:ffff:ffff:ffff:ffff:ffff,EE +2001:67c:261c::,2001:67c:261c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2620::,2001:67c:2620:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2624::,2001:67c:2624:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:262c::,2001:67c:262c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2630::,2001:67c:2630:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2634::,2001:67c:2634:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2638::,2001:67c:2638:ffff:ffff:ffff:ffff:ffff,SK +2001:67c:263c::,2001:67c:263c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2640::,2001:67c:2640:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:2644::,2001:67c:2644:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:264c::,2001:67c:264c:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2650::,2001:67c:2650:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2654::,2001:67c:2654:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:265c::,2001:67c:265c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2660::,2001:67c:2660:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2664::,2001:67c:2664:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2668::,2001:67c:2668:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:266c::,2001:67c:266c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2670::,2001:67c:2670:ffff:ffff:ffff:ffff:ffff,SK +2001:67c:2674::,2001:67c:2674:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2678::,2001:67c:2678:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:267c::,2001:67c:267c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2684::,2001:67c:2684:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2688::,2001:67c:2688:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:268c::,2001:67c:268c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2690::,2001:67c:2690:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:2694::,2001:67c:2694:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2698::,2001:67c:2698:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:269c::,2001:67c:269c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:26a0::,2001:67c:26a0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:26a4::,2001:67c:26a4:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:26ac::,2001:67c:26ac:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:26b0::,2001:67c:26b0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:26b4::,2001:67c:26b4:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:26b8::,2001:67c:26b8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:26bc::,2001:67c:26bc:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:26c0::,2001:67c:26c3:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:26d0::,2001:67c:26d0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:26d4::,2001:67c:26d4:ffff:ffff:ffff:ffff:ffff,SK +2001:67c:26d8::,2001:67c:26d8:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:26dc::,2001:67c:26dc:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:26e0::,2001:67c:26e0:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:26e4::,2001:67c:26e4:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:26e8::,2001:67c:26e8:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:26ec::,2001:67c:26ec:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:26f0::,2001:67c:26f0:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:26f4::,2001:67c:26f4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:26f8::,2001:67c:26f8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:26fc::,2001:67c:26fc:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2700::,2001:67c:2700:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:2704::,2001:67c:2704:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2708::,2001:67c:2708:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:270c::,2001:67c:270c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2710::,2001:67c:2710:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2714::,2001:67c:2714:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2718::,2001:67c:2718:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:271c::,2001:67c:271c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2720::,2001:67c:2720:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2724::,2001:67c:2724:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2728::,2001:67c:2728:ffff:ffff:ffff:ffff:ffff,IR +2001:67c:272c::,2001:67c:272c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2730::,2001:67c:2730:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2734::,2001:67c:2734:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2738::,2001:67c:2738:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:273c::,2001:67c:273c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2740::,2001:67c:2740:ffff:ffff:ffff:ffff:ffff,SK +2001:67c:2744::,2001:67c:2744:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2748::,2001:67c:2748:ffff:ffff:ffff:ffff:ffff,GR +2001:67c:274c::,2001:67c:274c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2750::,2001:67c:2750:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2758::,2001:67c:2758:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:275c::,2001:67c:275c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2760::,2001:67c:2760:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2764::,2001:67c:2764:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2768::,2001:67c:2768:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:276c::,2001:67c:276c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2770::,2001:67c:2770:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2774::,2001:67c:2774:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:2778::,2001:67c:2778:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:277c::,2001:67c:277c:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2780::,2001:67c:2780:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2784::,2001:67c:2784:ffff:ffff:ffff:ffff:ffff,FI +2001:67c:2788::,2001:67c:2788:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:278c::,2001:67c:278c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2790::,2001:67c:2790:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2794::,2001:67c:2794:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2798::,2001:67c:2798:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:27c0::,2001:67c:27c0:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:27c4::,2001:67c:27c4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:27c8::,2001:67c:27c8:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:27cc::,2001:67c:27cc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:27d0::,2001:67c:27d0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:27d4::,2001:67c:27d4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:27d8::,2001:67c:27d8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:27dc::,2001:67c:27dc:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:27e0::,2001:67c:27e0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:27e4::,2001:67c:27e4:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:27e8::,2001:67c:27e8:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:27ec::,2001:67c:27ec:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:27f0::,2001:67c:27f0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:27f4::,2001:67c:27f4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:27f8::,2001:67c:27f8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:27fc::,2001:67c:27fc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2800::,2001:67c:2800:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2804::,2001:67c:2804:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2808::,2001:67c:2808:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:280c::,2001:67c:280c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2810::,2001:67c:2810:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2814::,2001:67c:2814:ffff:ffff:ffff:ffff:ffff,LI +2001:67c:2818::,2001:67c:2818:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:281c::,2001:67c:281c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2820::,2001:67c:2820:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2824::,2001:67c:2824:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2828::,2001:67c:2828:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:282c::,2001:67c:282c:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:2830::,2001:67c:2830:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2834::,2001:67c:2834:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2838::,2001:67c:2838:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:283c::,2001:67c:283c:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:2840::,2001:67c:2840:ffff:ffff:ffff:ffff:ffff,IL +2001:67c:2844::,2001:67c:2844:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2848::,2001:67c:2848:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:284c::,2001:67c:284c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2850::,2001:67c:2850:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2854::,2001:67c:2854:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:285c::,2001:67c:285c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2860::,2001:67c:2860:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2864::,2001:67c:2864:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2868::,2001:67c:2868:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:286c::,2001:67c:286c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2870::,2001:67c:2870:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2874::,2001:67c:2874:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2878::,2001:67c:2878:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:287c::,2001:67c:287c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2880::,2001:67c:2880:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2884::,2001:67c:2884:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2888::,2001:67c:2889:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2890::,2001:67c:2890:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2894::,2001:67c:2894:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2898::,2001:67c:2898:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:289c::,2001:67c:289c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:28a0::,2001:67c:28a0:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:28a4::,2001:67c:28a4:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:28a8::,2001:67c:28a8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:28ac::,2001:67c:28ac:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:28b0::,2001:67c:28b0:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:28b4::,2001:67c:28b4:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:28b8::,2001:67c:28b8:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:28bc::,2001:67c:28bc:ffff:ffff:ffff:ffff:ffff,HU +2001:67c:28c0::,2001:67c:28c0:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:28c4::,2001:67c:28c4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:28cc::,2001:67c:28cc:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:28d0::,2001:67c:28d0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:28d4::,2001:67c:28d4:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:28d8::,2001:67c:28d8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:28e0::,2001:67c:28e0:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:28e4::,2001:67c:28e4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:28e8::,2001:67c:28e8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:28f0::,2001:67c:28f0:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:28f4::,2001:67c:28f4:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:28f8::,2001:67c:28f8:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:28fc::,2001:67c:28fc:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2900::,2001:67c:291f:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2980::,2001:67c:2980:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2984::,2001:67c:2984:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2988::,2001:67c:2989:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:2994::,2001:67c:2994:ffff:ffff:ffff:ffff:ffff,SA +2001:67c:2998::,2001:67c:2998:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:299c::,2001:67c:299c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:29a0::,2001:67c:29a0:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:29a8::,2001:67c:29a8:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:29ac::,2001:67c:29ac:ffff:ffff:ffff:ffff:ffff,CY +2001:67c:29b0::,2001:67c:29b1:ffff:ffff:ffff:ffff:ffff,CY +2001:67c:29bc::,2001:67c:29bc:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:29c0::,2001:67c:29c1:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:29c8::,2001:67c:29c8:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:29cc::,2001:67c:29cc:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:29d0::,2001:67c:29d0:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:29d4::,2001:67c:29d4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:29d8::,2001:67c:29d8:ffff:ffff:ffff:ffff:ffff,AE +2001:67c:29dc::,2001:67c:29dc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:29e0::,2001:67c:29e0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:29e4::,2001:67c:29e4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:29e8::,2001:67c:29e8:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:29ec::,2001:67c:29ec:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:29f0::,2001:67c:29f0:ffff:ffff:ffff:ffff:ffff,BG +2001:67c:29f4::,2001:67c:29f4:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:29f8::,2001:67c:29f8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:29fc::,2001:67c:29fc:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2a00::,2001:67c:2a00:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2a04::,2001:67c:2a04:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2a08::,2001:67c:2a08:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2a0c::,2001:67c:2a0c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2a14::,2001:67c:2a14:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2a18::,2001:67c:2a18:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2a1c::,2001:67c:2a1c:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2a20::,2001:67c:2a20:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2a24::,2001:67c:2a24:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2a28::,2001:67c:2a28:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2a2c::,2001:67c:2a2c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2a30::,2001:67c:2a30:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2a34::,2001:67c:2a34:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2a38::,2001:67c:2a38:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2a3c::,2001:67c:2a3c:ffff:ffff:ffff:ffff:ffff,ES +2001:67c:2a40::,2001:67c:2a40:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2a44::,2001:67c:2a44:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2a48::,2001:67c:2a48:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2a4c::,2001:67c:2a4c:ffff:ffff:ffff:ffff:ffff,GB +2001:67c:2a50::,2001:67c:2a50:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2a54::,2001:67c:2a54:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2a58::,2001:67c:2a58:ffff:ffff:ffff:ffff:ffff,BE +2001:67c:2a5c::,2001:67c:2a5c:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2a64::,2001:67c:2a64:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2a68::,2001:67c:2a68:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2a6c::,2001:67c:2a6c:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:2a70::,2001:67c:2a70:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2a74::,2001:67c:2a74:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2a78::,2001:67c:2a78:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2a7c::,2001:67c:2a7c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2a80::,2001:67c:2a80:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2a84::,2001:67c:2a84:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2a88::,2001:67c:2a88:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:2a8c::,2001:67c:2a8c:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2a90::,2001:67c:2a90:ffff:ffff:ffff:ffff:ffff,NO +2001:67c:2a94::,2001:67c:2a94:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2a98::,2001:67c:2a98:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2a9c::,2001:67c:2a9c:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2aa0::,2001:67c:2aa0:ffff:ffff:ffff:ffff:ffff,LU +2001:67c:2aa4::,2001:67c:2aa4:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2aa8::,2001:67c:2aa8:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2aac::,2001:67c:2aac:ffff:ffff:ffff:ffff:ffff,IS +2001:67c:2ab0::,2001:67c:2ab0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2ab4::,2001:67c:2ab4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2ab8::,2001:67c:2ab8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2abc::,2001:67c:2abc:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2ac0::,2001:67c:2ac0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2ac4::,2001:67c:2ac4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2ac8::,2001:67c:2ac8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2acc::,2001:67c:2acc:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2ad0::,2001:67c:2ad0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2ad4::,2001:67c:2ad4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2ad8::,2001:67c:2ad8:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2adc::,2001:67c:2adc:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2ae0::,2001:67c:2ae0:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2ae4::,2001:67c:2ae4:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2ae8::,2001:67c:2ae8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2aec::,2001:67c:2aec:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2af0::,2001:67c:2af0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2af4::,2001:67c:2af4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2afc::,2001:67c:2afc:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2b04::,2001:67c:2b04:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2b08::,2001:67c:2b08:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2b0c::,2001:67c:2b0c:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2b10::,2001:67c:2b10:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2b14::,2001:67c:2b14:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2b18::,2001:67c:2b18:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2b1c::,2001:67c:2b1c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2b20::,2001:67c:2b20:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2b24::,2001:67c:2b24:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2b28::,2001:67c:2b28:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2b2c::,2001:67c:2b2c:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2b30::,2001:67c:2b30:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2b34::,2001:67c:2b34:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2b38::,2001:67c:2b38:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2b3c::,2001:67c:2b3c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2b40::,2001:67c:2b40:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2b44::,2001:67c:2b44:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2b48::,2001:67c:2b48:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2b4c::,2001:67c:2b4c:ffff:ffff:ffff:ffff:ffff,CZ +2001:67c:2b50::,2001:67c:2b50:ffff:ffff:ffff:ffff:ffff,AT +2001:67c:2b54::,2001:67c:2b54:ffff:ffff:ffff:ffff:ffff,CH +2001:67c:2b58::,2001:67c:2b58:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2b5c::,2001:67c:2b5c:ffff:ffff:ffff:ffff:ffff,FR +2001:67c:2b60::,2001:67c:2b60:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2b64::,2001:67c:2b64:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2b68::,2001:67c:2b68:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2b6c::,2001:67c:2b6c:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2b70::,2001:67c:2b70:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2b74::,2001:67c:2b74:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2b78::,2001:67c:2b79:ffff:ffff:ffff:ffff:ffff,GR +2001:67c:2b80::,2001:67c:2b80:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2b84::,2001:67c:2b84:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2b88::,2001:67c:2b88:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2b8c::,2001:67c:2b8c:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2b90::,2001:67c:2b90:ffff:ffff:ffff:ffff:ffff,SI +2001:67c:2b94::,2001:67c:2b94:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2b98::,2001:67c:2b98:ffff:ffff:ffff:ffff:ffff,DK +2001:67c:2b9c::,2001:67c:2b9c:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2ba0::,2001:67c:2ba0:ffff:ffff:ffff:ffff:ffff,TR +2001:67c:2ba4::,2001:67c:2ba4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2ba8::,2001:67c:2ba8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2bac::,2001:67c:2bac:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2bb4::,2001:67c:2bb4:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2bb8::,2001:67c:2bb8:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2bbc::,2001:67c:2bbc:ffff:ffff:ffff:ffff:ffff,RO +2001:67c:2bc0::,2001:67c:2bc0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2bc4::,2001:67c:2bc4:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2bc8::,2001:67c:2bc8:ffff:ffff:ffff:ffff:ffff,DE +2001:67c:2bcc::,2001:67c:2bcc:ffff:ffff:ffff:ffff:ffff,LV +2001:67c:2bd0::,2001:67c:2bd0:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2bd4::,2001:67c:2bd4:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2bd8::,2001:67c:2bd8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2bdc::,2001:67c:2bdc:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2be0::,2001:67c:2be0:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2be4::,2001:67c:2be4:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2be8::,2001:67c:2be8:ffff:ffff:ffff:ffff:ffff,NL +2001:67c:2bec::,2001:67c:2bec:ffff:ffff:ffff:ffff:ffff,PL +2001:67c:2bf0::,2001:67c:2bf0:ffff:ffff:ffff:ffff:ffff,UA +2001:67c:2bf4::,2001:67c:2bf4:ffff:ffff:ffff:ffff:ffff,RU +2001:67c:2bf8::,2001:67c:2bf8:ffff:ffff:ffff:ffff:ffff,SE +2001:67c:2bfc::,2001:67c:2bfc:ffff:ffff:ffff:ffff:ffff,SE +2001:680::,2001:680:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:688::,2001:688:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:690::,2001:697:ffff:ffff:ffff:ffff:ffff:ffff,PT +2001:6a0::,2001:6a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:6a8::,2001:6a8:ffff:ffff:ffff:ffff:ffff:ffff,BE +2001:6b0::,2001:6b0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:6b8::,2001:6b8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:6c8::,2001:6cf:ffff:ffff:ffff:ffff:ffff:ffff,DK +2001:6d0::,2001:6d0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:6d8::,2001:6df:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:6e0::,2001:6e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:6e8::,2001:6ef:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:6f0::,2001:6f7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:6f8::,2001:6f8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:700::,2001:7ff:ffff:ffff:ffff:ffff:ffff:ffff,LV +2001:800::,2001:8ff:ffff:ffff:ffff:ffff:ffff:ffff,GD +2001:900::,2001:9ff:ffff:ffff:ffff:ffff:ffff:ffff,NO +2001:a00::,2001:aff:ffff:ffff:ffff:ffff:ffff:ffff,DJ +2001:b00::,2001:b07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:b08::,2001:b08:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:b10::,2001:b10:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:b18::,2001:b18:ffff:ffff:ffff:ffff:ffff:ffff,PT +2001:b20::,2001:b20:ffff:ffff:ffff:ffff:ffff:ffff,LU +2001:b28::,2001:b28:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:b30::,2001:b30:ffff:ffff:ffff:ffff:ffff:ffff,RO +2001:b38::,2001:b38:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:b40::,2001:b40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:b48::,2001:b4f:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:b50::,2001:b50:ffff:ffff:ffff:ffff:ffff:ffff,DK +2001:b58::,2001:b58:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:b60::,2001:b67:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:b68::,2001:b68:ffff:ffff:ffff:ffff:ffff:ffff,HR +2001:b70::,2001:b70:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:b80::,2001:b87:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:b88::,2001:b88:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:b90::,2001:b90:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:b98::,2001:b98:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:ba0::,2001:ba0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:ba8::,2001:ba8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:bb0::,2001:bb0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2001:bb8::,2001:bb8:ffff:ffff:ffff:ffff:ffff:ffff,EE +2001:bc0::,2001:bc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:bc8::,2001:bc8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:bd0::,2001:bd0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:be0::,2001:be7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:be8::,2001:be8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:bf0::,2001:bf7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:bf8::,2001:bf8:ffff:ffff:ffff:ffff:ffff:ffff,IL +2001:c00::,2001:cff:ffff:ffff:ffff:ffff:ffff:ffff,CO +2001:d00::,2001:d00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d08::,2001:d08:ffff:ffff:ffff:ffff:ffff:ffff,MY +2001:d10::,2001:d10:ffff:ffff:ffff:ffff:ffff:ffff,ID +2001:d18::,2001:d18:ffff:ffff:ffff:ffff:ffff:ffff,PH +2001:d28::,2001:d28:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d30::,2001:d30:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d38::,2001:d38:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:d40::,2001:d40:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:d48::,2001:d48:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:d50::,2001:d50:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d58::,2001:d58:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:d68::,2001:d68:ffff:ffff:ffff:ffff:ffff:ffff,ID +2001:d70::,2001:d73:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d80::,2001:d80:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d88::,2001:d88:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d90::,2001:d90:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:d98::,2001:d98:ffff:ffff:ffff:ffff:ffff:ffff,SG +2001:da0::,2001:da0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:da8::,2001:daa:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:db0::,2001:db0:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:dc0::,2001:dc0:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:dc1::,2001:dc1:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:dc2::,2001:dc4:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:dc5::,2001:dc5:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:dc6::,2001:dc6:ffff:ffff:ffff:ffff:ffff:ffff,ID +2001:dc7::,2001:dc7:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:dc8::,2001:dc8:ffff:ffff:ffff:ffff:ffff:ffff,VN +2001:dc9::,2001:dc9:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:dca::,2001:dca:ffff:ffff:ffff:ffff:ffff:ffff,HK +2001:dcc::,2001:dcc:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:dcd::,2001:dcd:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:dce::,2001:dce:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2001:dd8::,2001:dd8::ffff:ffff:ffff:ffff:ffff,FJ +2001:dd8:1::,2001:dd8:1:ffff:ffff:ffff:ffff:ffff,CN +2001:dd8:2::,2001:dd8:2:ffff:ffff:ffff:ffff:ffff,MY +2001:dd8:3::,2001:dd8:3:ffff:ffff:ffff:ffff:ffff,NZ +2001:dd8:4::,2001:dd8:4:ffff:ffff:ffff:ffff:ffff,SG +2001:dd8:5::,2001:dd8:5:ffff:ffff:ffff:ffff:ffff,CN +2001:dd8:6::,2001:dd8:6:ffff:ffff:ffff:ffff:ffff,AU +2001:dd8:7::,2001:dd8:7:ffff:ffff:ffff:ffff:ffff,NP +2001:dd8:8::,2001:dd8:f:ffff:ffff:ffff:ffff:ffff,AU +2001:dd8:10::,2001:dd8:11:ffff:ffff:ffff:ffff:ffff,NP +2001:dd8:12::,2001:dd8:12:ffff:ffff:ffff:ffff:ffff,AU +2001:dd8:13::,2001:dd8:13:ffff:ffff:ffff:ffff:ffff,NZ +2001:dd8:14::,2001:dd8:14:ffff:ffff:ffff:ffff:ffff,AU +2001:dd8:15::,2001:dd8:15:ffff:ffff:ffff:ffff:ffff,HK +2001:dd8:16::,2001:dd8:16:ffff:ffff:ffff:ffff:ffff,SG +2001:dd8:17::,2001:dd8:17:ffff:ffff:ffff:ffff:ffff,KR +2001:dd8:18::,2001:dd8:18:ffff:ffff:ffff:ffff:ffff,TW +2001:dd8:19::,2001:dd8:19:ffff:ffff:ffff:ffff:ffff,IN +2001:dd8:1a::,2001:dd8:1a:ffff:ffff:ffff:ffff:ffff,CN +2001:dd8:1b::,2001:dd8:1b:ffff:ffff:ffff:ffff:ffff,IN +2001:dd8:1c::,2001:dd8:1c:ffff:ffff:ffff:ffff:ffff,PK +2001:dd8:1d::,2001:dd8:1d:ffff:ffff:ffff:ffff:ffff,BD +2001:dd8:1e::,2001:dd8:1e:ffff:ffff:ffff:ffff:ffff,KH +2001:dd8:1f::,2001:dd8:1f:ffff:ffff:ffff:ffff:ffff,ID +2001:dd8:20::,2001:dd8:21:ffff:ffff:ffff:ffff:ffff,IN +2001:dd8:22::,2001:dd8:22:ffff:ffff:ffff:ffff:ffff,JP +2001:dd8:24::,2001:dd8:25:ffff:ffff:ffff:ffff:ffff,NP +2001:de1::,2001:de1:3f:ffff:ffff:ffff:ffff:ffff,JP +2001:de8::,2001:de8::ffff:ffff:ffff:ffff:ffff,TH +2001:de8:1::,2001:de8:1:ffff:ffff:ffff:ffff:ffff,IN +2001:de8:2::,2001:de8:2:ffff:ffff:ffff:ffff:ffff,ID +2001:de8:3::,2001:de8:3:ffff:ffff:ffff:ffff:ffff,VN +2001:de8:4::,2001:de8:7:ffff:ffff:ffff:ffff:ffff,SG +2001:de8:8::,2001:de8:8:ffff:ffff:ffff:ffff:ffff,JP +2001:de8:9::,2001:de8:9:ffff:ffff:ffff:ffff:ffff,AU +2001:de8:a::,2001:de8:a:ffff:ffff:ffff:ffff:ffff,VN +2001:de8:b::,2001:de8:b:ffff:ffff:ffff:ffff:ffff,BD +2001:de8:c::,2001:de8:c:ffff:ffff:ffff:ffff:ffff,JP +2001:de8:d::,2001:de8:d:ffff:ffff:ffff:ffff:ffff,SG +2001:de8:e::,2001:de8:e:ffff:ffff:ffff:ffff:ffff,TH +2001:de8:f::,2001:de8:10:ffff:ffff:ffff:ffff:ffff,MY +2001:de8:11::,2001:de8:11:ffff:ffff:ffff:ffff:ffff,ID +2001:de8:12::,2001:de8:12:ffff:ffff:ffff:ffff:ffff,SG +2001:de8:13::,2001:de8:13:ffff:ffff:ffff:ffff:ffff,MY +2001:de8:14::,2001:de8:14:ffff:ffff:ffff:ffff:ffff,AU +2001:de8:15::,2001:de8:15:ffff:ffff:ffff:ffff:ffff,ID +2001:de8:16::,2001:de8:16:ffff:ffff:ffff:ffff:ffff,PF +2001:de8:17::,2001:de8:17:ffff:ffff:ffff:ffff:ffff,AU +2001:de8:19::,2001:de8:19:ffff:ffff:ffff:ffff:ffff,NZ +2001:de8:1a::,2001:de8:1a:ffff:ffff:ffff:ffff:ffff,ID +2001:de8:1b::,2001:de8:1b:ffff:ffff:ffff:ffff:ffff,MY +2001:de8:1d::,2001:de8:1d:ffff:ffff:ffff:ffff:ffff,KH +2001:de8:1e::,2001:de8:1e:ffff:ffff:ffff:ffff:ffff,JP +2001:de9::,2001:de9::ffff:ffff:ffff:ffff:ffff,LK +2001:dea::,2001:dea::ffff:ffff:ffff:ffff:ffff,AU +2001:dec::,2001:dec::ffff:ffff:ffff:ffff:ffff,VU +2001:dee::,2001:dee::ffff:ffff:ffff:ffff:ffff,HK +2001:df0::,2001:df0:1:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:2::,2001:df0:2:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:4::,2001:df0:4:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:7::,2001:df0:7:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:8::,2001:df0:8:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:9::,2001:df0:a:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:c::,2001:df0:13:ffff:ffff:ffff:ffff:ffff,VN +2001:df0:14::,2001:df0:14:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:15::,2001:df0:15:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:17::,2001:df0:17:ffff:ffff:ffff:ffff:ffff,LK +2001:df0:18::,2001:df0:18:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:19::,2001:df0:1d:ffff:ffff:ffff:ffff:ffff,VN +2001:df0:1e::,2001:df0:1e:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:1f::,2001:df0:1f:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:20::,2001:df0:3f:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:40::,2001:df0:40:ffff:ffff:ffff:ffff:ffff,VN +2001:df0:41::,2001:df0:41:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:42::,2001:df0:42:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:43::,2001:df0:43:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:44::,2001:df0:44:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:45::,2001:df0:46:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:48::,2001:df0:48:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:49::,2001:df0:49:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:4a::,2001:df0:4a:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:4b::,2001:df0:4d:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:4f::,2001:df0:60:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:62::,2001:df0:62:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:63::,2001:df0:63:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:65::,2001:df0:65:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:66::,2001:df0:66:ffff:ffff:ffff:ffff:ffff,VN +2001:df0:68::,2001:df0:68:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:69::,2001:df0:69:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:6a::,2001:df0:6a:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:6b::,2001:df0:6b:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:6c::,2001:df0:6c:ffff:ffff:ffff:ffff:ffff,WS +2001:df0:6f::,2001:df0:6f:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:70::,2001:df0:70:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:71::,2001:df0:71:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:73::,2001:df0:74:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:75::,2001:df0:75:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:76::,2001:df0:76:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:77::,2001:df0:77:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:78::,2001:df0:78:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:7b::,2001:df0:7c:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:7d::,2001:df0:7d:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:7e::,2001:df0:81:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:82::,2001:df0:82:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:83::,2001:df0:83:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:84::,2001:df0:84:ffff:ffff:ffff:ffff:ffff,PK +2001:df0:85::,2001:df0:85:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:86::,2001:df0:87:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:89::,2001:df0:89:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:8b::,2001:df0:8b:ffff:ffff:ffff:ffff:ffff,NP +2001:df0:8c::,2001:df0:8c:ffff:ffff:ffff:ffff:ffff,NU +2001:df0:8e::,2001:df0:90:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:91::,2001:df0:91:ffff:ffff:ffff:ffff:ffff,FJ +2001:df0:92::,2001:df0:92:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:93::,2001:df0:93:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:94::,2001:df0:94:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:95::,2001:df0:95:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:96::,2001:df0:96:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:97::,2001:df0:97:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:98::,2001:df0:9a:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:9c::,2001:df0:9c:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:9d::,2001:df0:9d:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:9e::,2001:df0:9e:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:9f::,2001:df0:9f:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:a0::,2001:df0:a1:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:a2::,2001:df0:a2:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:a3::,2001:df0:a3:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:a4::,2001:df0:a4:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:a5::,2001:df0:a6:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:a7::,2001:df0:ab:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:ad::,2001:df0:ad:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:ae::,2001:df0:ae:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:b0::,2001:df0:b0:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:b1::,2001:df0:b8:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:b9::,2001:df0:b9:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:ba::,2001:df0:bd:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:be::,2001:df0:be:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:bf::,2001:df0:bf:ffff:ffff:ffff:ffff:ffff,LA +2001:df0:c0::,2001:df0:c0:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:c1::,2001:df0:c2:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:c4::,2001:df0:c4:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:c5::,2001:df0:c5:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:c6::,2001:df0:c6:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:c7::,2001:df0:c8:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:c9::,2001:df0:cc:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:cd::,2001:df0:cd:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:ce::,2001:df0:ce:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:cf::,2001:df0:cf:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:d1::,2001:df0:d1:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:d2::,2001:df0:d2:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:d4::,2001:df0:d6:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:d7::,2001:df0:d7:ffff:ffff:ffff:ffff:ffff,KR +2001:df0:d8::,2001:df0:d8:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:d9::,2001:df0:d9:ffff:ffff:ffff:ffff:ffff,TW +2001:df0:da::,2001:df0:da:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:db::,2001:df0:db:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:dc::,2001:df0:dc:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:dd::,2001:df0:dd:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:de::,2001:df0:df:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:e1::,2001:df0:e1:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:e2::,2001:df0:e2:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:e3::,2001:df0:e3:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:e4::,2001:df0:e5:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:e6::,2001:df0:e6:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:e7::,2001:df0:e8:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:e9::,2001:df0:e9:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:ea::,2001:df0:ea:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:eb::,2001:df0:eb:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:ed::,2001:df0:ed:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:ee::,2001:df0:ee:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:ef::,2001:df0:f0:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:f1::,2001:df0:f1:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:f2::,2001:df0:f2:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:f3::,2001:df0:f3:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:f4::,2001:df0:f4:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:f5::,2001:df0:f5:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:f6::,2001:df0:f6:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:f7::,2001:df0:f7:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:f8::,2001:df0:fa:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:fb::,2001:df0:fb:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:fc::,2001:df0:fc:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:fd::,2001:df0:fe:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:100::,2001:df0:1ff:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:201::,2001:df0:201:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:202::,2001:df0:202:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:203::,2001:df0:203:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:204::,2001:df0:204:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:205::,2001:df0:205:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:206::,2001:df0:206:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:207::,2001:df0:207:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:208::,2001:df0:208:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:209::,2001:df0:209:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:20a::,2001:df0:20a:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:20b::,2001:df0:20b:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:20c::,2001:df0:20c:ffff:ffff:ffff:ffff:ffff,NF +2001:df0:20d::,2001:df0:20d:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:20e::,2001:df0:20e:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:210::,2001:df0:210:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:211::,2001:df0:211:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:212::,2001:df0:212:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:213::,2001:df0:213:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:214::,2001:df0:214:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:215::,2001:df0:215:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:216::,2001:df0:217:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:218::,2001:df0:219:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:21a::,2001:df0:21a:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:21b::,2001:df0:21b:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:21c::,2001:df0:21c:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:21d::,2001:df0:21d:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:21e::,2001:df0:21e:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:21f::,2001:df0:220:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:221::,2001:df0:221:ffff:ffff:ffff:ffff:ffff,VN +2001:df0:222::,2001:df0:222:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:224::,2001:df0:224:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:225::,2001:df0:225:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:226::,2001:df0:228:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:229::,2001:df0:229:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:22b::,2001:df0:22b:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:22c::,2001:df0:22d:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:22e::,2001:df0:22f:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:230::,2001:df0:230:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:231::,2001:df0:231:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:232::,2001:df0:232:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:233::,2001:df0:234:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:235::,2001:df0:235:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:237::,2001:df0:237:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:238::,2001:df0:238:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:239::,2001:df0:239:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:23a::,2001:df0:23a:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:23b::,2001:df0:23b:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:23c::,2001:df0:23d:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:23e::,2001:df0:23e:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:23f::,2001:df0:23f:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:240::,2001:df0:241:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:242::,2001:df0:242:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:243::,2001:df0:243:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:245::,2001:df0:246:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:247::,2001:df0:247:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:248::,2001:df0:248:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:249::,2001:df0:24a:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:24b::,2001:df0:24b:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:24c::,2001:df0:24c:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:24e::,2001:df0:24e:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:24f::,2001:df0:24f:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:250::,2001:df0:250:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:251::,2001:df0:252:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:253::,2001:df0:253:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:254::,2001:df0:254:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:255::,2001:df0:255:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:256::,2001:df0:256:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:257::,2001:df0:257:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:258::,2001:df0:258:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:259::,2001:df0:259:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:25a::,2001:df0:25a:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:25b::,2001:df0:25b:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:25c::,2001:df0:25d:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:25e::,2001:df0:25e:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:260::,2001:df0:260:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:261::,2001:df0:261:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:262::,2001:df0:262:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:263::,2001:df0:263:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:264::,2001:df0:264:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:265::,2001:df0:265:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:266::,2001:df0:266:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:267::,2001:df0:267:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:268::,2001:df0:269:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:26a::,2001:df0:26b:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:26c::,2001:df0:26c:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:26d::,2001:df0:26f:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:270::,2001:df0:270:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:271::,2001:df0:271:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:272::,2001:df0:272:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:273::,2001:df0:273:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:274::,2001:df0:277:ffff:ffff:ffff:ffff:ffff,NP +2001:df0:278::,2001:df0:278:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:279::,2001:df0:279:ffff:ffff:ffff:ffff:ffff,PK +2001:df0:27a::,2001:df0:27a:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:27b::,2001:df0:27b:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:27c::,2001:df0:27c:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:27d::,2001:df0:27d:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:27e::,2001:df0:27e:ffff:ffff:ffff:ffff:ffff,CN +2001:df0:27f::,2001:df0:27f:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:280::,2001:df0:28f:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:290::,2001:df0:290:ffff:ffff:ffff:ffff:ffff,KR +2001:df0:291::,2001:df0:291:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:292::,2001:df0:292:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:293::,2001:df0:293:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:294::,2001:df0:294:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:295::,2001:df0:296:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:298::,2001:df0:298:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:299::,2001:df0:299:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:29a::,2001:df0:29a:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:29b::,2001:df0:29b:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:29c::,2001:df0:29c:ffff:ffff:ffff:ffff:ffff,VN +2001:df0:29d::,2001:df0:29d:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:29f::,2001:df0:29f:ffff:ffff:ffff:ffff:ffff,BD +2001:df0:2a0::,2001:df0:2a0:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:2a1::,2001:df0:2a1:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2a2::,2001:df0:2a2:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:2a3::,2001:df0:2a3:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2a4::,2001:df0:2a4:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2a5::,2001:df0:2a5:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:2a6::,2001:df0:2a6:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2a7::,2001:df0:2a7:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2a8::,2001:df0:2a8:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:2a9::,2001:df0:2aa:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2ab::,2001:df0:2ab:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2ac::,2001:df0:2ac:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:2ad::,2001:df0:2ad:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2ae::,2001:df0:2ae:ffff:ffff:ffff:ffff:ffff,WS +2001:df0:2af::,2001:df0:2af:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:2b0::,2001:df0:2b1:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2b2::,2001:df0:2b2:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2b3::,2001:df0:2b3:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2b4::,2001:df0:2b4:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2b5::,2001:df0:2b5:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2b6::,2001:df0:2b6:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2b7::,2001:df0:2b7:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2b8::,2001:df0:2b8:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:2b9::,2001:df0:2b9:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:2ba::,2001:df0:2ba:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:2bb::,2001:df0:2bb:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:2bc::,2001:df0:2bc:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2bd::,2001:df0:2bd:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2be::,2001:df0:2be:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2bf::,2001:df0:2bf:ffff:ffff:ffff:ffff:ffff,GB +2001:df0:2c1::,2001:df0:2c1:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:2c2::,2001:df0:2c2:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2c3::,2001:df0:2c3:ffff:ffff:ffff:ffff:ffff,BD +2001:df0:2c4::,2001:df0:2c4:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2c5::,2001:df0:2c5:ffff:ffff:ffff:ffff:ffff,BD +2001:df0:2c6::,2001:df0:2c8:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2c9::,2001:df0:2c9:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2ca::,2001:df0:2ca:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2cb::,2001:df0:2cb:ffff:ffff:ffff:ffff:ffff,PK +2001:df0:2cc::,2001:df0:2cc:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2cd::,2001:df0:2cd:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:2ce::,2001:df0:2e0:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2e1::,2001:df0:2e1:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2e2::,2001:df0:2e2:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2e3::,2001:df0:2e3:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2e4::,2001:df0:2e4:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2e5::,2001:df0:2e5:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2e6::,2001:df0:2e7:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2e8::,2001:df0:2e8:ffff:ffff:ffff:ffff:ffff,VN +2001:df0:2e9::,2001:df0:2e9:ffff:ffff:ffff:ffff:ffff,CN +2001:df0:2ea::,2001:df0:2ea:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:2ec::,2001:df0:2ec:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2ed::,2001:df0:2ee:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2ef::,2001:df0:2ef:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:2f0::,2001:df0:2f3:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2f4::,2001:df0:2f4:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2f5::,2001:df0:2f5:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2f6::,2001:df0:2f6:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2f7::,2001:df0:2f7:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:2f8::,2001:df0:2f8:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2f9::,2001:df0:2f9:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2fa::,2001:df0:2fa:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2fb::,2001:df0:2fb:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:2fc::,2001:df0:2fc:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:2fd::,2001:df0:2fd:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:2fe::,2001:df0:2ff:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:300::,2001:df0:311:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:314::,2001:df0:317:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:400::,2001:df0:400:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:401::,2001:df0:401:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:402::,2001:df0:403:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:404::,2001:df0:404:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:405::,2001:df0:405:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:407::,2001:df0:407:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:408::,2001:df0:408:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:409::,2001:df0:409:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:40a::,2001:df0:40a:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:40c::,2001:df0:40c:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:40d::,2001:df0:40d:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:40e::,2001:df0:40f:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:410::,2001:df0:410:ffff:ffff:ffff:ffff:ffff,VU +2001:df0:411::,2001:df0:411:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:412::,2001:df0:412:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:413::,2001:df0:413:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:415::,2001:df0:415:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:417::,2001:df0:417:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:418::,2001:df0:419:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:41a::,2001:df0:41a:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:41b::,2001:df0:41b:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:41c::,2001:df0:41c:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:41d::,2001:df0:41e:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:41f::,2001:df0:41f:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:420::,2001:df0:420:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:421::,2001:df0:421:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:422::,2001:df0:422:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:423::,2001:df0:423:ffff:ffff:ffff:ffff:ffff,CN +2001:df0:424::,2001:df0:424:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:425::,2001:df0:425:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:426::,2001:df0:426:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:427::,2001:df0:427:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:430::,2001:df0:43f:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:440::,2001:df0:440:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:441::,2001:df0:441:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:442::,2001:df0:443:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:444::,2001:df0:445:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:446::,2001:df0:446:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:447::,2001:df0:447:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:448::,2001:df0:448:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:449::,2001:df0:449:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:44a::,2001:df0:44a:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:44b::,2001:df0:44b:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:44c::,2001:df0:44d:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:44e::,2001:df0:44e:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:44f::,2001:df0:44f:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:450::,2001:df0:450:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:451::,2001:df0:451:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:452::,2001:df0:452:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:453::,2001:df0:453:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:454::,2001:df0:454:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:455::,2001:df0:455:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:456::,2001:df0:456:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:457::,2001:df0:457:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:458::,2001:df0:458:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:459::,2001:df0:459:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:45a::,2001:df0:45a:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:45b::,2001:df0:45b:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:45c::,2001:df0:45d:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:45e::,2001:df0:45e:ffff:ffff:ffff:ffff:ffff,BD +2001:df0:45f::,2001:df0:45f:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:460::,2001:df0:460:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:461::,2001:df0:461:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:462::,2001:df0:462:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:463::,2001:df0:463:ffff:ffff:ffff:ffff:ffff,SG +2001:df0:464::,2001:df0:464:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:465::,2001:df0:465:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:466::,2001:df0:466:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:467::,2001:df0:467:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:468::,2001:df0:469:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:46a::,2001:df0:46a:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:46b::,2001:df0:46b:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:46c::,2001:df0:46c:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:500::,2001:df0:5ff:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:800::,2001:df0:800:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:1000::,2001:df0:1000:ffff:ffff:ffff:ffff:ffff,TH +2001:df0:1800::,2001:df0:1800:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:2000::,2001:df0:2000:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:2800::,2001:df0:2800:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:3000::,2001:df0:3000:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:3800::,2001:df0:3800:ffff:ffff:ffff:ffff:ffff,MY +2001:df0:4000::,2001:df0:4000:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:4800::,2001:df0:4800:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:5000::,2001:df0:5000:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:5800::,2001:df0:5800:ffff:ffff:ffff:ffff:ffff,ID +2001:df0:6000::,2001:df0:6000:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:6800::,2001:df0:6800:ffff:ffff:ffff:ffff:ffff,JP +2001:df0:7000::,2001:df0:7000:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:7800::,2001:df0:7800:ffff:ffff:ffff:ffff:ffff,WS +2001:df0:8000::,2001:df0:8000:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:8800::,2001:df0:8800:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:9800::,2001:df0:9800:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:a000::,2001:df0:a000:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:a800::,2001:df0:a800:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:b000::,2001:df0:b000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df0:b800::,2001:df0:b800:ffff:ffff:ffff:ffff:ffff,PH +2001:df0:c000::,2001:df0:c000:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:c800::,2001:df0:c800:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:d000::,2001:df0:d000:ffff:ffff:ffff:ffff:ffff,IN +2001:df0:d800::,2001:df0:d800:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:e000::,2001:df0:e000:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:e800::,2001:df0:e800:ffff:ffff:ffff:ffff:ffff,AU +2001:df0:f000::,2001:df0:f000:ffff:ffff:ffff:ffff:ffff,HK +2001:df0:f800::,2001:df0:f800:ffff:ffff:ffff:ffff:ffff,ID +2001:df1::,2001:df1::ffff:ffff:ffff:ffff:ffff,TH +2001:df1:800::,2001:df1:800:ffff:ffff:ffff:ffff:ffff,SG +2001:df1:1000::,2001:df1:1000:ffff:ffff:ffff:ffff:ffff,IN +2001:df1:1800::,2001:df1:1800:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:2000::,2001:df1:2000:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:2800::,2001:df1:2800:ffff:ffff:ffff:ffff:ffff,SG +2001:df1:3000::,2001:df1:3000:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:3800::,2001:df1:3800:ffff:ffff:ffff:ffff:ffff,NZ +2001:df1:4000::,2001:df1:4000:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:4800::,2001:df1:4800:ffff:ffff:ffff:ffff:ffff,IN +2001:df1:5000::,2001:df1:5000:ffff:ffff:ffff:ffff:ffff,HK +2001:df1:5800::,2001:df1:5800:ffff:ffff:ffff:ffff:ffff,BD +2001:df1:6000::,2001:df1:6000:ffff:ffff:ffff:ffff:ffff,SG +2001:df1:6800::,2001:df1:6800:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:7000::,2001:df1:7000:ffff:ffff:ffff:ffff:ffff,ID +2001:df1:7800::,2001:df1:7800:ffff:ffff:ffff:ffff:ffff,ID +2001:df1:8000::,2001:df1:8000:ffff:ffff:ffff:ffff:ffff,IN +2001:df1:8800::,2001:df1:8800:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:9000::,2001:df1:9000:ffff:ffff:ffff:ffff:ffff,ID +2001:df1:9800::,2001:df1:9800:ffff:ffff:ffff:ffff:ffff,MY +2001:df1:a000::,2001:df1:a000:ffff:ffff:ffff:ffff:ffff,IN +2001:df1:a800::,2001:df1:a800:ffff:ffff:ffff:ffff:ffff,SG +2001:df1:b000::,2001:df1:b000:ffff:ffff:ffff:ffff:ffff,TH +2001:df1:b800::,2001:df1:b800:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:c000::,2001:df1:c000:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:c800::,2001:df1:c800:ffff:ffff:ffff:ffff:ffff,HK +2001:df1:d000::,2001:df1:d000:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:d800::,2001:df1:d800:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:e000::,2001:df1:e000:ffff:ffff:ffff:ffff:ffff,ID +2001:df1:e800::,2001:df1:e800:ffff:ffff:ffff:ffff:ffff,AU +2001:df1:f000::,2001:df1:f000:ffff:ffff:ffff:ffff:ffff,ID +2001:df1:f800::,2001:df1:f800:ffff:ffff:ffff:ffff:ffff,BN +2001:df2::,2001:df2::ffff:ffff:ffff:ffff:ffff,AU +2001:df2:800::,2001:df2:800:ffff:ffff:ffff:ffff:ffff,AU +2001:df2:1000::,2001:df2:1000:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:1800::,2001:df2:1803:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:2000::,2001:df2:2000:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:2800::,2001:df2:2800:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:3000::,2001:df2:3000:ffff:ffff:ffff:ffff:ffff,SG +2001:df2:3800::,2001:df2:3800:ffff:ffff:ffff:ffff:ffff,TH +2001:df2:4000::,2001:df2:4000:ffff:ffff:ffff:ffff:ffff,HK +2001:df2:4800::,2001:df2:4800:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:5000::,2001:df2:5000:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:5800::,2001:df2:5800:ffff:ffff:ffff:ffff:ffff,HK +2001:df2:6000::,2001:df2:6000:ffff:ffff:ffff:ffff:ffff,ID +2001:df2:6800::,2001:df2:6800:ffff:ffff:ffff:ffff:ffff,PH +2001:df2:7000::,2001:df2:7000:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:7800::,2001:df2:7800:ffff:ffff:ffff:ffff:ffff,AU +2001:df2:8000::,2001:df2:8000:ffff:ffff:ffff:ffff:ffff,BN +2001:df2:8800::,2001:df2:8800:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:9000::,2001:df2:9000:ffff:ffff:ffff:ffff:ffff,AU +2001:df2:9800::,2001:df2:9803:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:a000::,2001:df2:a000:ffff:ffff:ffff:ffff:ffff,ID +2001:df2:a800::,2001:df2:a800:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:b000::,2001:df2:b000:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:c000::,2001:df2:c000:ffff:ffff:ffff:ffff:ffff,ID +2001:df2:c800::,2001:df2:c800:ffff:ffff:ffff:ffff:ffff,AU +2001:df2:d000::,2001:df2:d000:ffff:ffff:ffff:ffff:ffff,HK +2001:df2:d800::,2001:df2:d800:ffff:ffff:ffff:ffff:ffff,JP +2001:df2:e000::,2001:df2:e000:ffff:ffff:ffff:ffff:ffff,AU +2001:df2:e800::,2001:df2:e800:ffff:ffff:ffff:ffff:ffff,IN +2001:df2:f000::,2001:df2:f000:ffff:ffff:ffff:ffff:ffff,VN +2001:df2:f800::,2001:df2:f800:ffff:ffff:ffff:ffff:ffff,IN +2001:df3::,2001:df3::ffff:ffff:ffff:ffff:ffff,MY +2001:df3:800::,2001:df3:80f:ffff:ffff:ffff:ffff:ffff,CN +2001:df3:1000::,2001:df3:1000:ffff:ffff:ffff:ffff:ffff,BD +2001:df3:1800::,2001:df3:1800:ffff:ffff:ffff:ffff:ffff,ID +2001:df3:2000::,2001:df3:2000:ffff:ffff:ffff:ffff:ffff,ID +2001:df3:2800::,2001:df3:2800:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:3000::,2001:df3:3000:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:3800::,2001:df3:3800:ffff:ffff:ffff:ffff:ffff,ID +2001:df3:4000::,2001:df3:4000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df3:4800::,2001:df3:4800:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:5000::,2001:df3:5000:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:5800::,2001:df3:5800:ffff:ffff:ffff:ffff:ffff,AU +2001:df3:6000::,2001:df3:6000:ffff:ffff:ffff:ffff:ffff,SG +2001:df3:6800::,2001:df3:6800:ffff:ffff:ffff:ffff:ffff,AU +2001:df3:7000::,2001:df3:7000:ffff:ffff:ffff:ffff:ffff,ID +2001:df3:7800::,2001:df3:7800:ffff:ffff:ffff:ffff:ffff,SG +2001:df3:8000::,2001:df3:8000:ffff:ffff:ffff:ffff:ffff,ID +2001:df3:8800::,2001:df3:8800:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:9000::,2001:df3:9000:ffff:ffff:ffff:ffff:ffff,HK +2001:df3:9800::,2001:df3:9800:ffff:ffff:ffff:ffff:ffff,MY +2001:df3:a000::,2001:df3:a003:ffff:ffff:ffff:ffff:ffff,PH +2001:df3:a800::,2001:df3:a800:ffff:ffff:ffff:ffff:ffff,MY +2001:df3:b000::,2001:df3:b000:ffff:ffff:ffff:ffff:ffff,TH +2001:df3:b800::,2001:df3:b800:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:c000::,2001:df3:c000:ffff:ffff:ffff:ffff:ffff,ID +2001:df3:c800::,2001:df3:c800:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:d000::,2001:df3:d000:ffff:ffff:ffff:ffff:ffff,AU +2001:df3:d800::,2001:df3:d800:ffff:ffff:ffff:ffff:ffff,SG +2001:df3:e000::,2001:df3:e000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df3:e800::,2001:df3:e800:ffff:ffff:ffff:ffff:ffff,IN +2001:df3:f000::,2001:df3:f000:ffff:ffff:ffff:ffff:ffff,ID +2001:df3:f800::,2001:df3:f800:ffff:ffff:ffff:ffff:ffff,IN +2001:df4::,2001:df4::ffff:ffff:ffff:ffff:ffff,MY +2001:df4:800::,2001:df4:800:ffff:ffff:ffff:ffff:ffff,AU +2001:df4:1000::,2001:df4:1000:ffff:ffff:ffff:ffff:ffff,HK +2001:df4:1800::,2001:df4:1800:ffff:ffff:ffff:ffff:ffff,IN +2001:df4:2000::,2001:df4:2000:ffff:ffff:ffff:ffff:ffff,TH +2001:df4:2800::,2001:df4:2800:ffff:ffff:ffff:ffff:ffff,HK +2001:df4:3000::,2001:df4:3000:ffff:ffff:ffff:ffff:ffff,TH +2001:df4:3800::,2001:df4:3800:ffff:ffff:ffff:ffff:ffff,BD +2001:df4:4000::,2001:df4:400f:ffff:ffff:ffff:ffff:ffff,SG +2001:df4:4800::,2001:df4:4800:ffff:ffff:ffff:ffff:ffff,AU +2001:df4:5000::,2001:df4:5000:ffff:ffff:ffff:ffff:ffff,ID +2001:df4:5800::,2001:df4:5800:ffff:ffff:ffff:ffff:ffff,AU +2001:df4:6000::,2001:df4:6000:ffff:ffff:ffff:ffff:ffff,MY +2001:df4:6800::,2001:df4:6800:ffff:ffff:ffff:ffff:ffff,SG +2001:df4:7000::,2001:df4:7000:ffff:ffff:ffff:ffff:ffff,HK +2001:df4:7800::,2001:df4:7800:ffff:ffff:ffff:ffff:ffff,IN +2001:df4:8000::,2001:df4:8000:ffff:ffff:ffff:ffff:ffff,MY +2001:df4:8800::,2001:df4:8800:ffff:ffff:ffff:ffff:ffff,HK +2001:df4:9000::,2001:df4:9000:ffff:ffff:ffff:ffff:ffff,SG +2001:df4:9800::,2001:df4:9800:ffff:ffff:ffff:ffff:ffff,ID +2001:df4:a000::,2001:df4:a000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df4:a800::,2001:df4:a800:ffff:ffff:ffff:ffff:ffff,ID +2001:df4:b000::,2001:df4:b000:ffff:ffff:ffff:ffff:ffff,IN +2001:df4:b800::,2001:df4:b800:ffff:ffff:ffff:ffff:ffff,AU +2001:df4:c000::,2001:df4:c000:ffff:ffff:ffff:ffff:ffff,ID +2001:df4:c800::,2001:df4:c800:ffff:ffff:ffff:ffff:ffff,SG +2001:df4:d000::,2001:df4:d000:ffff:ffff:ffff:ffff:ffff,IN +2001:df4:d800::,2001:df4:d800:ffff:ffff:ffff:ffff:ffff,VN +2001:df4:e000::,2001:df4:e000:ffff:ffff:ffff:ffff:ffff,IN +2001:df4:e800::,2001:df4:e800:ffff:ffff:ffff:ffff:ffff,MN +2001:df4:f000::,2001:df4:f000:ffff:ffff:ffff:ffff:ffff,IN +2001:df4:f800::,2001:df4:f800:ffff:ffff:ffff:ffff:ffff,AU +2001:df5::,2001:df5::ffff:ffff:ffff:ffff:ffff,AU +2001:df5:800::,2001:df5:800:ffff:ffff:ffff:ffff:ffff,HK +2001:df5:1000::,2001:df5:1000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df5:1800::,2001:df5:1800:ffff:ffff:ffff:ffff:ffff,ID +2001:df5:2000::,2001:df5:2000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df5:2800::,2001:df5:2800:ffff:ffff:ffff:ffff:ffff,IN +2001:df5:3000::,2001:df5:3000:ffff:ffff:ffff:ffff:ffff,AU +2001:df5:3800::,2001:df5:3800:ffff:ffff:ffff:ffff:ffff,IN +2001:df5:4000::,2001:df5:4000:ffff:ffff:ffff:ffff:ffff,ID +2001:df5:4800::,2001:df5:4800:ffff:ffff:ffff:ffff:ffff,BN +2001:df5:5000::,2001:df5:5000:ffff:ffff:ffff:ffff:ffff,ID +2001:df5:5800::,2001:df5:5800:ffff:ffff:ffff:ffff:ffff,AU +2001:df5:6000::,2001:df5:6000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df5:6800::,2001:df5:6800:ffff:ffff:ffff:ffff:ffff,KR +2001:df5:7000::,2001:df5:7000:ffff:ffff:ffff:ffff:ffff,ID +2001:df5:7800::,2001:df5:7800:ffff:ffff:ffff:ffff:ffff,CN +2001:df5:8000::,2001:df5:8000:ffff:ffff:ffff:ffff:ffff,SG +2001:df5:8800::,2001:df5:8800:ffff:ffff:ffff:ffff:ffff,IN +2001:df5:9000::,2001:df5:9000:ffff:ffff:ffff:ffff:ffff,IN +2001:df5:9800::,2001:df5:9800:ffff:ffff:ffff:ffff:ffff,SG +2001:df5:a000::,2001:df5:a000:ffff:ffff:ffff:ffff:ffff,ID +2001:df5:a800::,2001:df5:a800:ffff:ffff:ffff:ffff:ffff,AU +2001:df5:b000::,2001:df5:b000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df5:b800::,2001:df5:b800:ffff:ffff:ffff:ffff:ffff,HK +2001:df5:c800::,2001:df5:c800:ffff:ffff:ffff:ffff:ffff,AU +2001:df5:d000::,2001:df5:d000:ffff:ffff:ffff:ffff:ffff,ID +2001:df5:d800::,2001:df5:d800:ffff:ffff:ffff:ffff:ffff,SG +2001:df5:e000::,2001:df5:e000:ffff:ffff:ffff:ffff:ffff,MY +2001:df5:e800::,2001:df5:e800:ffff:ffff:ffff:ffff:ffff,PH +2001:df5:f000::,2001:df5:f000:ffff:ffff:ffff:ffff:ffff,ID +2001:df5:f800::,2001:df5:f800:ffff:ffff:ffff:ffff:ffff,SG +2001:df6::,2001:df6:1:ffff:ffff:ffff:ffff:ffff,IN +2001:df6:800::,2001:df6:80f:ffff:ffff:ffff:ffff:ffff,HK +2001:df6:1000::,2001:df6:1000:ffff:ffff:ffff:ffff:ffff,PH +2001:df6:1800::,2001:df6:1800:ffff:ffff:ffff:ffff:ffff,ID +2001:df6:2000::,2001:df6:2001:ffff:ffff:ffff:ffff:ffff,HK +2001:df6:2800::,2001:df6:2800:ffff:ffff:ffff:ffff:ffff,IN +2001:df6:3000::,2001:df6:3000:ffff:ffff:ffff:ffff:ffff,NZ +2001:df6:3800::,2001:df6:3800:ffff:ffff:ffff:ffff:ffff,NZ +2001:df6:4000::,2001:df6:4001:ffff:ffff:ffff:ffff:ffff,AU +2001:df6:5000::,2001:df6:5000:ffff:ffff:ffff:ffff:ffff,AU +2001:df6:6000::,2001:df6:6000:ffff:ffff:ffff:ffff:ffff,JP +2001:df6:7000::,2001:df6:7000:ffff:ffff:ffff:ffff:ffff,VN +2001:df6:8000::,2001:df6:8000:ffff:ffff:ffff:ffff:ffff,JP +2001:df6:9000::,2001:df6:9000:ffff:ffff:ffff:ffff:ffff,AU +2001:df6:a000::,2001:df6:a000:ffff:ffff:ffff:ffff:ffff,JP +2001:df6:b000::,2001:df6:b000:ffff:ffff:ffff:ffff:ffff,TH +2001:df6:c000::,2001:df6:c000:ffff:ffff:ffff:ffff:ffff,IN +2001:df6:d000::,2001:df6:d000:ffff:ffff:ffff:ffff:ffff,HK +2001:df6:e000::,2001:df6:e000:ffff:ffff:ffff:ffff:ffff,VU +2001:df6:f000::,2001:df6:f000:ffff:ffff:ffff:ffff:ffff,HK +2001:df7::,2001:df7::ffff:ffff:ffff:ffff:ffff,IN +2001:df7:1000::,2001:df7:1000:ffff:ffff:ffff:ffff:ffff,IN +2001:df7:2000::,2001:df7:2000:ffff:ffff:ffff:ffff:ffff,AU +2001:df7:3000::,2001:df7:3001:ffff:ffff:ffff:ffff:ffff,NZ +2001:df7:4000::,2001:df7:4000:ffff:ffff:ffff:ffff:ffff,SG +2001:df7:5000::,2001:df7:5000:ffff:ffff:ffff:ffff:ffff,IN +2001:df7:6000::,2001:df7:6000:ffff:ffff:ffff:ffff:ffff,IN +2001:df7:7000::,2001:df7:7000:ffff:ffff:ffff:ffff:ffff,HK +2001:df7:9000::,2001:df7:9000:ffff:ffff:ffff:ffff:ffff,PH +2001:df7:a000::,2001:df7:a000:ffff:ffff:ffff:ffff:ffff,AU +2001:df7:b000::,2001:df7:b000:ffff:ffff:ffff:ffff:ffff,IN +2001:df7:c000::,2001:df7:c003:ffff:ffff:ffff:ffff:ffff,SG +2001:df7:d000::,2001:df7:d000:ffff:ffff:ffff:ffff:ffff,BD +2001:df7:e000::,2001:df7:e000:ffff:ffff:ffff:ffff:ffff,IN +2001:df7:f000::,2001:df7:f000:ffff:ffff:ffff:ffff:ffff,JP +2001:df8::,2001:df9:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:dfa::,2001:dfa:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:e00::,2001:eff:ffff:ffff:ffff:ffff:ffff:ffff,MZ +2001:f00::,2001:f00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2001:f08::,2001:f08:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:f10::,2001:f10:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:f18::,2001:f18:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:f20::,2001:f20:ffff:ffff:ffff:ffff:ffff:ffff,ID +2001:f28::,2001:f28:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:f30::,2001:f30:ffff:ffff:ffff:ffff:ffff:ffff,IN +2001:f38::,2001:f38:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:f40::,2001:f40:ffff:ffff:ffff:ffff:ffff:ffff,MY +2001:f48::,2001:f48:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:f50::,2001:f50:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2001:f58::,2001:f58:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:f60::,2001:f6f:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:f80::,2001:f80:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:f88::,2001:f88:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:f90::,2001:f90:ffff:ffff:ffff:ffff:ffff:ffff,MO +2001:f98::,2001:f98:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:fa0::,2001:fa0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:fa8::,2001:fa8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:fb0::,2001:fb1:ffff:ffff:ffff:ffff:ffff:ffff,TH +2001:fc0::,2001:fc0:ffff:ffff:ffff:ffff:ffff:ffff,SG +2001:fc8::,2001:fc8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:fd0::,2001:fd0:ffff:ffff:ffff:ffff:ffff:ffff,IN +2001:fd8::,2001:fd8:ffff:ffff:ffff:ffff:ffff:ffff,PH +2001:fe0::,2001:fe0:ffff:ffff:ffff:ffff:ffff:ffff,PH +2001:fe8::,2001:fe8:ffff:ffff:ffff:ffff:ffff:ffff,PK +2001:ff0::,2001:ff0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:ff8::,2001:ff8:ffff:ffff:ffff:ffff:ffff:ffff,MO +2001:1200::,2001:1200:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1208::,2001:1208:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1210::,2001:1210:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1218::,2001:1218:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1220::,2001:1220:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1228::,2001:1228:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:122c::,2001:122c:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1230::,2001:1230:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1238::,2001:1238:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1240::,2001:1240:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1248::,2001:1248:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1250::,2001:1250:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1258::,2001:1258:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1260::,2001:1260:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1270::,2001:1270:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1278::,2001:1278:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:1280::,2001:1280:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:1284::,2001:1284:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:1288::,2001:1288:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:128c::,2001:128c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:1290::,2001:1291:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:1294::,2001:1294:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:1298::,2001:1298:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:129c::,2001:129c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12a0::,2001:12a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12a4::,2001:12a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12ac::,2001:12ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12b0::,2001:12b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12b4::,2001:12b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12b8::,2001:12b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12bc::,2001:12bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12c0::,2001:12c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12c4::,2001:12c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12c8::,2001:12c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12d0::,2001:12d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12d8::,2001:12d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12e0::,2001:12e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12e8::,2001:12e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12f0::,2001:12f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:12f8::,2001:12f8:1:ffff:ffff:ffff:ffff:ffff,BR +2001:12f8:4::,2001:12f8:4:ffff:ffff:ffff:ffff:ffff,BR +2001:12fe::,2001:12ff:ffff:ffff:ffff:ffff:ffff:ffff,BR +2001:1300::,2001:1300:ffff:ffff:ffff:ffff:ffff:ffff,PE +2001:1308::,2001:1308:ffff:ffff:ffff:ffff:ffff:ffff,DO +2001:1310::,2001:1310:ffff:ffff:ffff:ffff:ffff:ffff,CL +2001:1318::,2001:1318:ffff:ffff:ffff:ffff:ffff:ffff,AR +2001:1320::,2001:1320:ffff:ffff:ffff:ffff:ffff:ffff,PY +2001:1328::,2001:1328:ffff:ffff:ffff:ffff:ffff:ffff,UY +2001:1330::,2001:1337:ffff:ffff:ffff:ffff:ffff:ffff,CR +2001:1338::,2001:1338:ffff:ffff:ffff:ffff:ffff:ffff,VE +2001:1340::,2001:1340:ffff:ffff:ffff:ffff:ffff:ffff,CU +2001:1348::,2001:1348:ffff:ffff:ffff:ffff:ffff:ffff,UY +2001:1350::,2001:1350:ffff:ffff:ffff:ffff:ffff:ffff,VE +2001:1358::,2001:1358:ffff:ffff:ffff:ffff:ffff:ffff,CU +2001:1360::,2001:1360:ffff:ffff:ffff:ffff:ffff:ffff,GT +2001:1368::,2001:1368:ffff:ffff:ffff:ffff:ffff:ffff,PA +2001:1370::,2001:1370:ffff:ffff:ffff:ffff:ffff:ffff,HT +2001:1378::,2001:1378:ffff:ffff:ffff:ffff:ffff:ffff,BO +2001:1380::,2001:1380:ffff:ffff:ffff:ffff:ffff:ffff,PE +2001:1388::,2001:1388:ffff:ffff:ffff:ffff:ffff:ffff,PE +2001:1398::,2001:1398:ffff:ffff:ffff:ffff:ffff:ffff,CL +2001:13a0::,2001:13a0:ffff:ffff:ffff:ffff:ffff:ffff,PE +2001:13a8::,2001:13a8:ffff:ffff:ffff:ffff:ffff:ffff,MX +2001:13b0::,2001:13b7:ffff:ffff:ffff:ffff:ffff:ffff,AR +2001:13c7:6000::,2001:13c7:6000:ffff:ffff:ffff:ffff:ffff,CO +2001:13c7:6001::,2001:13c7:6001:ffff:ffff:ffff:ffff:ffff,AR +2001:13c7:6002::,2001:13c7:6002:ffff:ffff:ffff:ffff:ffff,SX +2001:13c7:6003::,2001:13c7:6003:ffff:ffff:ffff:ffff:ffff,HT +2001:13c7:6004::,2001:13c7:6005:ffff:ffff:ffff:ffff:ffff,CW +2001:13c7:6006::,2001:13c7:6006:ffff:ffff:ffff:ffff:ffff,EC +2001:13c7:6007::,2001:13c7:600e:ffff:ffff:ffff:ffff:ffff,AR +2001:13c7:6010::,2001:13c7:601f:ffff:ffff:ffff:ffff:ffff,AR +2001:13c7:6f00::,2001:13c7:6fff:ffff:ffff:ffff:ffff:ffff,EC +2001:13c7:7000::,2001:13c7:7000:ffff:ffff:ffff:ffff:ffff,MX +2001:13c7:7001::,2001:13c7:7003:ffff:ffff:ffff:ffff:ffff,UY +2001:13c7:7004::,2001:13c7:7004:ffff:ffff:ffff:ffff:ffff,CR +2001:13c7:7005::,2001:13c7:7009:ffff:ffff:ffff:ffff:ffff,UY +2001:13c7:7010::,2001:13c7:7013:ffff:ffff:ffff:ffff:ffff,UY +2001:13c7:7014::,2001:13c7:7014:ffff:ffff:ffff:ffff:ffff,MX +2001:13c8::,2001:13c8:ffff:ffff:ffff:ffff:ffff:ffff,CU +2001:13d0::,2001:13d0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2001:13d8::,2001:13d8:ffff:ffff:ffff:ffff:ffff:ffff,CR +2001:13e0::,2001:13e0:ffff:ffff:ffff:ffff:ffff:ffff,DO +2001:13e8::,2001:13e8:ffff:ffff:ffff:ffff:ffff:ffff,AR +2001:13f0::,2001:13f0:ffff:ffff:ffff:ffff:ffff:ffff,DO +2001:13f8::,2001:13f8:ffff:ffff:ffff:ffff:ffff:ffff,CO +2001:1400::,2001:1400:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:1408::,2001:1408:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:1410::,2001:1410:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1418::,2001:1418:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:1420::,2001:1420:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1428::,2001:1428:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:1430::,2001:1430:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:1438::,2001:1438:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1440::,2001:1440:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1448::,2001:1448:ffff:ffff:ffff:ffff:ffff:ffff,DK +2001:1450::,2001:1450:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:1458::,2001:1459:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:1460::,2001:1460:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:1468::,2001:146f:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:1470::,2001:1477:ffff:ffff:ffff:ffff:ffff:ffff,SI +2001:1478::,2001:1478:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1488::,2001:1488:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:1490::,2001:1490:ffff:ffff:ffff:ffff:ffff:ffff,SA +2001:1498::,2001:1498:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:14a0::,2001:14a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:14a8::,2001:14a8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:14b0::,2001:14b0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:14b8::,2001:14bf:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:14c0::,2001:14c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:14c8::,2001:14c8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:14d0::,2001:14d0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2001:14d8::,2001:14d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:14e0::,2001:14e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:14e8::,2001:14e8:ffff:ffff:ffff:ffff:ffff:ffff,IR +2001:14f0::,2001:14f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:14f8::,2001:14f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1500::,2001:1500:ffff:ffff:ffff:ffff:ffff:ffff,IR +2001:1508::,2001:1508:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:1510::,2001:1510:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1520::,2001:1520:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1528::,2001:1528:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:1530::,2001:1530:ffff:ffff:ffff:ffff:ffff:ffff,EE +2001:1538::,2001:1538:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1540::,2001:1540:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:1548::,2001:1548:ffff:ffff:ffff:ffff:ffff:ffff,GR +2001:1558::,2001:1558:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:1560::,2001:1560:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1568::,2001:1568:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:1570::,2001:1570:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1578::,2001:1578:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1580::,2001:1580:ffff:ffff:ffff:ffff:ffff:ffff,DK +2001:1588::,2001:1588:ffff:ffff:ffff:ffff:ffff:ffff,PT +2001:1590::,2001:1590:ffff:ffff:ffff:ffff:ffff:ffff,SI +2001:1598::,2001:1598:ffff:ffff:ffff:ffff:ffff:ffff,BE +2001:15a0::,2001:15a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:15a8::,2001:15a8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:15b0::,2001:15b0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:15b8::,2001:15b8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:15c0::,2001:15c7:ffff:ffff:ffff:ffff:ffff:ffff,SI +2001:15c8::,2001:15c8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:15d8::,2001:15d8:ffff:ffff:ffff:ffff:ffff:ffff,PT +2001:15e0::,2001:15e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:15e8::,2001:15e8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:15f0::,2001:15f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:15f8::,2001:15f8:ffff:ffff:ffff:ffff:ffff:ffff,DK +2001:1600::,2001:1607:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:1608::,2001:1608:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1610::,2001:1610:ffff:ffff:ffff:ffff:ffff:ffff,LU +2001:1618::,2001:1618:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:1620::,2001:1623:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:1628::,2001:1628:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1630::,2001:1637:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:1638::,2001:1638:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1640::,2001:1640:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1650::,2001:1650:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1658::,2001:1658:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:1660::,2001:1660:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:1668::,2001:1668:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1670::,2001:1670:ffff:ffff:ffff:ffff:ffff:ffff,OM +2001:1678::,2001:1678:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:1680::,2001:1687:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:1688::,2001:168f:ffff:ffff:ffff:ffff:ffff:ffff,SI +2001:1690::,2001:1690:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:1698::,2001:1698:ffff:ffff:ffff:ffff:ffff:ffff,LU +2001:16a0::,2001:16a7:ffff:ffff:ffff:ffff:ffff:ffff,SA +2001:16a8::,2001:16a8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:16b0::,2001:16b0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:16b8::,2001:16b8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:16c0::,2001:16c0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2001:16c8::,2001:16c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:16d0::,2001:16d0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:16d8::,2001:16d8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:16e0::,2001:16e7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:16e8::,2001:16e8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:16f0::,2001:16f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:16f8::,2001:16f8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:1700::,2001:171f:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:1800::,2001:1800:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1808::,2001:1808:ffff:ffff:ffff:ffff:ffff:ffff,GD +2001:1810::,2001:1810:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1818::,2001:1818:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1820::,2001:1820:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1828::,2001:1828:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1830::,2001:1830:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1838::,2001:1838:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1840::,2001:1840:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1848::,2001:1848:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1850::,2001:1850:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1858::,2001:1858:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1860::,2001:1860:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1868::,2001:1868:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1878::,2001:1878:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1888::,2001:1888:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1890::,2001:1898:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18a0::,2001:18a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18a8::,2001:18a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18b0::,2001:18b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18b8::,2001:18b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18c0::,2001:18c0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:18c8::,2001:18c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18d8::,2001:18d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18e0::,2001:18e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18e8::,2001:18e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:18f0::,2001:18f0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:18f8::,2001:18f8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:1900::,2001:1900:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1908::,2001:1908:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1910::,2001:1910:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1920::,2001:1920:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:1928::,2001:1928:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:1930::,2001:1930:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1938::,2001:1938:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1940::,2001:1940:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1948::,2001:1948:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1950::,2001:1950:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1958::,2001:1958:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1960::,2001:1960:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1968::,2001:1968:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1970::,2001:1970:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:1978::,2001:1978:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1980::,2001:1980:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1988::,2001:1988:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1990::,2001:1990:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1998::,2001:1998:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19a0::,2001:19a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19a8::,2001:19a8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:19b0::,2001:19b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19b8::,2001:19b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19c0::,2001:19c0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:19c8::,2001:19c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19d0::,2001:19d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19d8::,2001:19d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19e0::,2001:19e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19e8::,2001:19e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19f0::,2001:19f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:19f8::,2001:19f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:1a00::,2001:1aff:ffff:ffff:ffff:ffff:ffff:ffff,NO +2001:1b00::,2001:1b00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:1b08::,2001:1b08:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1b10::,2001:1b10:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1b18::,2001:1b18:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1b20::,2001:1b20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1b28::,2001:1b28:ffff:ffff:ffff:ffff:ffff:ffff,EE +2001:1b30::,2001:1b37:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1b38::,2001:1b38:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1b40::,2001:1b40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1b48::,2001:1b48:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1b50::,2001:1b57:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:1b58::,2001:1b58:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1b60::,2001:1b60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1b68::,2001:1b68:ffff:ffff:ffff:ffff:ffff:ffff,TR +2001:1b70::,2001:1b77:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:1b78::,2001:1b78:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:1b80::,2001:1b80:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:1b88::,2001:1b88:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1b90::,2001:1b90:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1b98::,2001:1b98:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:1ba0::,2001:1ba0:ffff:ffff:ffff:ffff:ffff:ffff,SK +2001:1ba8::,2001:1ba8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:1bb0::,2001:1bb0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:1bb8::,2001:1bb8:ffff:ffff:ffff:ffff:ffff:ffff,IE +2001:1bc0::,2001:1bc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:1bc8::,2001:1bcf:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:1bd0::,2001:1bd0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:1bd8::,2001:1bd8:ffff:ffff:ffff:ffff:ffff:ffff,IE +2001:1be0::,2001:1be0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:1be8::,2001:1be8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:1bf0::,2001:1bf7:ffff:ffff:ffff:ffff:ffff:ffff,EE +2001:1bf8::,2001:1bf8:ffff:ffff:ffff:ffff:ffff:ffff,LV +2001:1c00::,2001:1dff:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:4000::,2001:4000:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:4010::,2001:4010:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4018::,2001:4018:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:4020::,2001:4020:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:4028::,2001:4028:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:4030::,2001:4030:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:4038::,2001:4038:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:4040::,2001:4040:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:4048::,2001:4048:ffff:ffff:ffff:ffff:ffff:ffff,LT +2001:4050::,2001:4050:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:4058::,2001:4058:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:4060::,2001:4060:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4068::,2001:4068:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4070::,2001:4070:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:4078::,2001:407f:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:4080::,2001:4080:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:4088::,2001:4088:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4090::,2001:4090:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:40a0::,2001:40a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:40a8::,2001:40a8:ffff:ffff:ffff:ffff:ffff:ffff,IL +2001:40b0::,2001:40b0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:40b8::,2001:40b8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:40c0::,2001:40c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:40c8::,2001:40cf:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:40d0::,2001:40d0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:40d8::,2001:40d8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:40e0::,2001:40e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:40e8::,2001:40e8:ffff:ffff:ffff:ffff:ffff:ffff,FI +2001:40f0::,2001:40f0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:40f8::,2001:40f8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:4100::,2001:4100:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:4108::,2001:4108:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:4118::,2001:4118:ffff:ffff:ffff:ffff:ffff:ffff,SK +2001:4120::,2001:4120:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4128::,2001:4128:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:4130::,2001:4130:ffff:ffff:ffff:ffff:ffff:ffff,UA +2001:4138::,2001:4140:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4150::,2001:4150:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4158::,2001:415f:ffff:ffff:ffff:ffff:ffff:ffff,BE +2001:4160::,2001:4160:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4168::,2001:4168:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4170::,2001:4170:ffff:ffff:ffff:ffff:ffff:ffff,RS +2001:4178::,2001:4180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4188::,2001:4188:ffff:ffff:ffff:ffff:ffff:ffff,IR +2001:4190::,2001:4190:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:4198::,2001:4198:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:41a0::,2001:41a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:41a8::,2001:41a8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:41b0::,2001:41b0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2001:41b8::,2001:41b8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:41c0::,2001:41cf:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:41d0::,2001:41d0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:41d8::,2001:41d8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:41e0::,2001:41e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:41e8::,2001:41e8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:41f0::,2001:41f0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:41f8::,2001:41f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4200::,2001:4200:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:4208::,2001:4208:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:4210::,2001:4210:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:4218::,2001:4218:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:4220::,2001:4220:ffff:ffff:ffff:ffff:ffff:ffff,EG +2001:4228::,2001:4228:ffff:ffff:ffff:ffff:ffff:ffff,SD +2001:4238::,2001:4238:ffff:ffff:ffff:ffff:ffff:ffff,KE +2001:4240::,2001:4240:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2001:4248::,2001:4248:ffff:ffff:ffff:ffff:ffff:ffff,MU +2001:4250::,2001:4250:ffff:ffff:ffff:ffff:ffff:ffff,AO +2001:4258::,2001:4258:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2001:4260::,2001:4260:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:4268::,2001:4268:ffff:ffff:ffff:ffff:ffff:ffff,CM +2001:4270::,2001:4270:ffff:ffff:ffff:ffff:ffff:ffff,NG +2001:4278::,2001:4278:ffff:ffff:ffff:ffff:ffff:ffff,SN +2001:4288::,2001:4288:ffff:ffff:ffff:ffff:ffff:ffff,MA +2001:4290::,2001:4290:ffff:ffff:ffff:ffff:ffff:ffff,MU +2001:4298::,2001:4298:ffff:ffff:ffff:ffff:ffff:ffff,DJ +2001:42a0::,2001:42a0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:42a8::,2001:42a8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:42b0::,2001:42b0:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2001:42b8::,2001:42b8:ffff:ffff:ffff:ffff:ffff:ffff,EG +2001:42c0::,2001:42c0:ffff:ffff:ffff:ffff:ffff:ffff,ML +2001:42c8::,2001:42c8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:42d0::,2001:42d0:ffff:ffff:ffff:ffff:ffff:ffff,MU +2001:42d8::,2001:42d8:ffff:ffff:ffff:ffff:ffff:ffff,CI +2001:42e0::,2001:42e0:ffff:ffff:ffff:ffff:ffff:ffff,SC +2001:42f0::,2001:42f0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:42f8::,2001:42f8:ffff:ffff:ffff:ffff:ffff:ffff,GH +2001:4300::,2001:4300:ffff:ffff:ffff:ffff:ffff:ffff,EG +2001:4308::,2001:4308:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:4310::,2001:4310:ffff:ffff:ffff:ffff:ffff:ffff,MA +2001:4318::,2001:4318:ffff:ffff:ffff:ffff:ffff:ffff,CI +2001:4320::,2001:4320:ffff:ffff:ffff:ffff:ffff:ffff,BJ +2001:4328::,2001:4328:ffff:ffff:ffff:ffff:ffff:ffff,MU +2001:4330::,2001:4330:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:4338::,2001:4338:ffff:ffff:ffff:ffff:ffff:ffff,SZ +2001:4340::,2001:4340:ffff:ffff:ffff:ffff:ffff:ffff,DZ +2001:4350::,2001:4350:ffff:ffff:ffff:ffff:ffff:ffff,TN +2001:4358::,2001:4358:ffff:ffff:ffff:ffff:ffff:ffff,KE +2001:4368::,2001:4368:ffff:ffff:ffff:ffff:ffff:ffff,KE +2001:4370::,2001:4370:ffff:ffff:ffff:ffff:ffff:ffff,KE +2001:4378::,2001:4378:ffff:ffff:ffff:ffff:ffff:ffff,MZ +2001:4388::,2001:4388:ffff:ffff:ffff:ffff:ffff:ffff,EG +2001:4398::,2001:4398:ffff:ffff:ffff:ffff:ffff:ffff,MG +2001:43a0::,2001:43a0:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2001:43a8::,2001:43a8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:43b0::,2001:43b0:ffff:ffff:ffff:ffff:ffff:ffff,NG +2001:43b8::,2001:43b8:ffff:ffff:ffff:ffff:ffff:ffff,MU +2001:43c0::,2001:43c0:ffff:ffff:ffff:ffff:ffff:ffff,GH +2001:43c8::,2001:43c8:ffff:ffff:ffff:ffff:ffff:ffff,EG +2001:43d0::,2001:43d0:ffff:ffff:ffff:ffff:ffff:ffff,KE +2001:43d8::,2001:43d8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:43e0::,2001:43e0:ffff:ffff:ffff:ffff:ffff:ffff,GH +2001:43e8::,2001:43e8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f0::,2001:43f0:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2001:43f8::,2001:43f8:1:ffff:ffff:ffff:ffff:ffff,TZ +2001:43f8:10::,2001:43f8:10:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:20::,2001:43f8:20:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:30::,2001:43f8:30:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:50::,2001:43f8:50:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:60::,2001:43f8:60:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:70::,2001:43f8:77:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:80::,2001:43f8:80:ffff:ffff:ffff:ffff:ffff,NA +2001:43f8:90::,2001:43f8:90:ffff:ffff:ffff:ffff:ffff,MU +2001:43f8:a0::,2001:43f8:a0:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:b0::,2001:43f8:b0:ffff:ffff:ffff:ffff:ffff,SL +2001:43f8:c0::,2001:43f8:c0:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:d0::,2001:43f8:d0:ffff:ffff:ffff:ffff:ffff,MU +2001:43f8:e0::,2001:43f8:e0:ffff:ffff:ffff:ffff:ffff,TZ +2001:43f8:100::,2001:43f8:100:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:110::,2001:43f8:110:ffff:ffff:ffff:ffff:ffff,MU +2001:43f8:120::,2001:43f8:120:ffff:ffff:ffff:ffff:ffff,MU +2001:43f8:130::,2001:43f8:130:ffff:ffff:ffff:ffff:ffff,UG +2001:43f8:140::,2001:43f8:140:ffff:ffff:ffff:ffff:ffff,ZM +2001:43f8:150::,2001:43f8:150:ffff:ffff:ffff:ffff:ffff,RW +2001:43f8:160::,2001:43f8:160:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:170::,2001:43f8:170:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:180::,2001:43f8:180:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:190::,2001:43f8:190:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:1a0::,2001:43f8:1a0:ffff:ffff:ffff:ffff:ffff,GH +2001:43f8:1c0::,2001:43f8:1c0:ffff:ffff:ffff:ffff:ffff,DZ +2001:43f8:1d0::,2001:43f8:1d0:ffff:ffff:ffff:ffff:ffff,GH +2001:43f8:1e0::,2001:43f8:1e0:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:1f0::,2001:43f8:1f5:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:200::,2001:43f8:200:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:210::,2001:43f8:210:ffff:ffff:ffff:ffff:ffff,LS +2001:43f8:220::,2001:43f8:220:ffff:ffff:ffff:ffff:ffff,MU +2001:43f8:230::,2001:43f8:230:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:240::,2001:43f8:241:ffff:ffff:ffff:ffff:ffff,GH +2001:43f8:250::,2001:43f8:250:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:260::,2001:43f8:260:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:270::,2001:43f8:270:ffff:ffff:ffff:ffff:ffff,MU +2001:43f8:290::,2001:43f8:290:ffff:ffff:ffff:ffff:ffff,MG +2001:43f8:2a0::,2001:43f8:2a0:ffff:ffff:ffff:ffff:ffff,BW +2001:43f8:2b0::,2001:43f8:2b0:ffff:ffff:ffff:ffff:ffff,BW +2001:43f8:2c0::,2001:43f8:2c0:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:2e0::,2001:43f8:2e0:ffff:ffff:ffff:ffff:ffff,EG +2001:43f8:2f0::,2001:43f8:2f0:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:310::,2001:43f8:310:ffff:ffff:ffff:ffff:ffff,ZW +2001:43f8:320::,2001:43f8:320:ffff:ffff:ffff:ffff:ffff,TN +2001:43f8:330::,2001:43f8:330:ffff:ffff:ffff:ffff:ffff,TZ +2001:43f8:340::,2001:43f8:340:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:360::,2001:43f8:360:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:370::,2001:43f8:370:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:380::,2001:43f8:380:ffff:ffff:ffff:ffff:ffff,MW +2001:43f8:390::,2001:43f8:390:ffff:ffff:ffff:ffff:ffff,AO +2001:43f8:3a0::,2001:43f8:3a0:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:3b0::,2001:43f8:3b0:ffff:ffff:ffff:ffff:ffff,NA +2001:43f8:3c0::,2001:43f8:3c0:ffff:ffff:ffff:ffff:ffff,CD +2001:43f8:3d0::,2001:43f8:3d0:ffff:ffff:ffff:ffff:ffff,BF +2001:43f8:400::,2001:43f8:4ff:ffff:ffff:ffff:ffff:ffff,AO +2001:43f8:600::,2001:43f8:60f:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:610::,2001:43f8:610:ffff:ffff:ffff:ffff:ffff,TZ +2001:43f8:620::,2001:43f8:620:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:630::,2001:43f8:630:ffff:ffff:ffff:ffff:ffff,MW +2001:43f8:640::,2001:43f8:640:ffff:ffff:ffff:ffff:ffff,MZ +2001:43f8:650::,2001:43f8:650:ffff:ffff:ffff:ffff:ffff,MA +2001:43f8:660::,2001:43f8:660:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:670::,2001:43f8:670:ffff:ffff:ffff:ffff:ffff,AO +2001:43f8:680::,2001:43f8:680:ffff:ffff:ffff:ffff:ffff,TZ +2001:43f8:6a0::,2001:43f8:6a0:ffff:ffff:ffff:ffff:ffff,CG +2001:43f8:6b0::,2001:43f8:6b3:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:6c0::,2001:43f8:6c0:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:6d0::,2001:43f8:6d3:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:6e0::,2001:43f8:6e0:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:700::,2001:43f8:70f:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:720::,2001:43f8:720:ffff:ffff:ffff:ffff:ffff,AO +2001:43f8:750::,2001:43f8:75f:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:760::,2001:43f8:760:ffff:ffff:ffff:ffff:ffff,AO +2001:43f8:770::,2001:43f8:773:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:780::,2001:43f8:780:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:790::,2001:43f8:790:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:7a0::,2001:43f8:7a0:ffff:ffff:ffff:ffff:ffff,MU +2001:43f8:7b0::,2001:43f8:7b0:ffff:ffff:ffff:ffff:ffff,KE +2001:43f8:7c0::,2001:43f8:7c0:ffff:ffff:ffff:ffff:ffff,AO +2001:43f8:7d0::,2001:43f8:7d0:ffff:ffff:ffff:ffff:ffff,NG +2001:43f8:7e0::,2001:43f8:7e0:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:7f0::,2001:43f8:7f0:ffff:ffff:ffff:ffff:ffff,SD +2001:43f8:800::,2001:43f8:83f:ffff:ffff:ffff:ffff:ffff,GH +2001:43f8:900::,2001:43f8:900:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:910::,2001:43f8:910:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:920::,2001:43f8:920:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:930::,2001:43f8:930:ffff:ffff:ffff:ffff:ffff,MZ +2001:43f8:940::,2001:43f8:940:ffff:ffff:ffff:ffff:ffff,CI +2001:43f8:950::,2001:43f8:950:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:960::,2001:43f8:960:ffff:ffff:ffff:ffff:ffff,ZA +2001:43f8:970::,2001:43f8:970:ffff:ffff:ffff:ffff:ffff,GM +2001:43f8:980::,2001:43f8:981:ffff:ffff:ffff:ffff:ffff,NA +2001:43f8:990::,2001:43f8:991:ffff:ffff:ffff:ffff:ffff,BI +2001:43f8:9a0::,2001:43f8:9a0:ffff:ffff:ffff:ffff:ffff,BJ +2001:43f8:9b0::,2001:43f8:9b1:ffff:ffff:ffff:ffff:ffff,SZ +2001:4400::,2001:4403:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2001:4408::,2001:4408:ffff:ffff:ffff:ffff:ffff:ffff,IN +2001:4410::,2001:4410:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2001:4420::,2001:4420:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:4428::,2001:4428:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2001:4430::,2001:4430:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:4438::,2001:4438:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:4450::,2001:4450:ffff:ffff:ffff:ffff:ffff:ffff,PH +2001:4458::,2001:4458:ffff:ffff:ffff:ffff:ffff:ffff,MY +2001:4460::,2001:4460:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:4470::,2001:4470:ffff:ffff:ffff:ffff:ffff:ffff,MY +2001:4478::,2001:447b:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:4480::,2001:4480:ffff:ffff:ffff:ffff:ffff:ffff,HK +2001:4488::,2001:448b:ffff:ffff:ffff:ffff:ffff:ffff,ID +2001:4490::,2001:4493:ffff:ffff:ffff:ffff:ffff:ffff,IN +2001:4498::,2001:4498:ffff:ffff:ffff:ffff:ffff:ffff,MY +2001:44a0::,2001:44a0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:44a8::,2001:44a8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:44b0::,2001:44b0:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:44b8::,2001:44b8:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:44c0::,2001:44c0:ffff:ffff:ffff:ffff:ffff:ffff,IN +2001:44c8::,2001:44c8:ffff:ffff:ffff:ffff:ffff:ffff,TH +2001:44d0::,2001:44df:ffff:ffff:ffff:ffff:ffff:ffff,KR +2001:44f0::,2001:44f0:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:4500::,2001:4500:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:4508::,2001:4508:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:4510::,2001:4517:ffff:ffff:ffff:ffff:ffff:ffff,CN +2001:4520::,2001:4520:ffff:ffff:ffff:ffff:ffff:ffff,IN +2001:4528::,2001:452b:ffff:ffff:ffff:ffff:ffff:ffff,IN +2001:4530::,2001:4530:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2001:4538::,2001:4538:ffff:ffff:ffff:ffff:ffff:ffff,PK +2001:4540::,2001:455f:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:4580::,2001:45bf:ffff:ffff:ffff:ffff:ffff:ffff,TW +2001:4600::,2001:46ff:ffff:ffff:ffff:ffff:ffff:ffff,NO +2001:4800::,2001:4808:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4810::,2001:4810:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4818::,2001:4818:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:4828::,2001:4828:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4830::,2001:4830:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4838::,2001:4838:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4840::,2001:4840:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4848::,2001:4848:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4850::,2001:4850:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4858::,2001:4858:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4860::,2001:4860:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4868::,2001:4868:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4870::,2001:4871:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4878::,2001:4878:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4880::,2001:4880:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4888::,2001:4888:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4890::,2001:4890:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4898::,2001:489a:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48a0::,2001:48a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48a8::,2001:48a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48b0::,2001:48b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48b8::,2001:48b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48c0::,2001:48c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48c8::,2001:48c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48d0::,2001:48d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48d8::,2001:48d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48e0::,2001:48e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48e8::,2001:48e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48f0::,2001:48f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:48f8::,2001:48f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4900::,2001:4900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:4908::,2001:4908:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4910::,2001:4910:ffff:ffff:ffff:ffff:ffff:ffff,BM +2001:4918::,2001:4918:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4920::,2001:4920:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4928::,2001:4928:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4930::,2001:4930:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4938::,2001:4938:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:4940::,2001:4940:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4948::,2001:4948:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4950::,2001:4950:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4958::,2001:4958:ffff:ffff:ffff:ffff:ffff:ffff,CA +2001:4960::,2001:4960:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4968::,2001:4968:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4970::,2001:4970:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4978::,2001:4978:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4980::,2001:4980:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4988::,2001:4988:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4990::,2001:4990:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4998::,2001:4998:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49a0::,2001:49a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49a8::,2001:49a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49b0::,2001:49b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49b8::,2001:49b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49c0::,2001:49c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49c8::,2001:49c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49d0::,2001:49d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49d8::,2001:49d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49e0::,2001:49e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49e8::,2001:49e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49f0::,2001:49f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:49f8::,2001:49f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2001:4a00::,2001:4a1f:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4b00::,2001:4b07:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4b08::,2001:4b08:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4b10::,2001:4b10:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4b18::,2001:4b18:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:4b20::,2001:4b28:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4b30::,2001:4b30:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:4b38::,2001:4b3f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4b40::,2001:4b40:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:4b48::,2001:4b48:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4b50::,2001:4b50:ffff:ffff:ffff:ffff:ffff:ffff,BE +2001:4b58::,2001:4b58:ffff:ffff:ffff:ffff:ffff:ffff,BG +2001:4b60::,2001:4b60:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:4b68::,2001:4b68:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:4b70::,2001:4b7f:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:4b80::,2001:4b87:ffff:ffff:ffff:ffff:ffff:ffff,NO +2001:4b88::,2001:4b88:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4b90::,2001:4b90:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:4b98::,2001:4b98:ffff:ffff:ffff:ffff:ffff:ffff,FR +2001:4ba0::,2001:4ba0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4ba8::,2001:4ba8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:4bb0::,2001:4bb0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:4bb8::,2001:4bb8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:4bc0::,2001:4bc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4bc8::,2001:4bc8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2001:4bd0::,2001:4bd0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4bd8::,2001:4bd8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4be0::,2001:4be0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2001:4be8::,2001:4be8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4bf0::,2001:4bf0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4bf8::,2001:4bf8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4c00::,2001:4cff:ffff:ffff:ffff:ffff:ffff:ffff,DJ +2001:4d00::,2001:4d00:ffff:ffff:ffff:ffff:ffff:ffff,AM +2001:4d08::,2001:4d08:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4d10::,2001:4d10:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:4d18::,2001:4d18:ffff:ffff:ffff:ffff:ffff:ffff,RO +2001:4d20::,2001:4d20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4d30::,2001:4d30:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4d38::,2001:4d38:ffff:ffff:ffff:ffff:ffff:ffff,IT +2001:4d48::,2001:4d48:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4d50::,2001:4d50:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4d58::,2001:4d58:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4d60::,2001:4d60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:4d68::,2001:4d68:ffff:ffff:ffff:ffff:ffff:ffff,IE +2001:4d70::,2001:4d70:ffff:ffff:ffff:ffff:ffff:ffff,GR +2001:4d78::,2001:4d78:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4d80::,2001:4d80:ffff:ffff:ffff:ffff:ffff:ffff,RO +2001:4d88::,2001:4d88:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4d90::,2001:4d90:ffff:ffff:ffff:ffff:ffff:ffff,ES +2001:4d98::,2001:4d98:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4da0::,2001:4da7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2001:4da8::,2001:4da8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2001:4db0::,2001:4db0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4db8::,2001:4db8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2001:4dc0::,2001:4dc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2001:4dc8::,2001:4dc8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4dd0::,2001:4dd7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2001:4dd8::,2001:4dd8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2001:4de0::,2001:4de0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2001:4de8::,2001:4de8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2001:4df0::,2001:4df0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2001:8000::,2001:8fff:ffff:ffff:ffff:ffff:ffff:ffff,AU +2001:a000::,2001:a7ff:ffff:ffff:ffff:ffff:ffff:ffff,JP +2001:b000::,2001:b7ff:ffff:ffff:ffff:ffff:ffff:ffff,TW +2003::,2003:1fff:ffff:ffff:ffff:ffff:ffff:ffff,DE +2400::,2400:fff:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:1000::,2400:1000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:1080::,2400:1080:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:1100::,2400:1100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:1180::,2400:1180:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:1200::,2400:1200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:1300::,2400:1300:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:1380::,2400:1380:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:1400::,2400:1400:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:1480::,2400:1480:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:1500::,2400:1500:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:1580::,2400:1580:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:1600::,2400:1600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:1680::,2400:1680:ffff:ffff:ffff:ffff:ffff:ffff,PK +2400:1700::,2400:1700:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:1780::,2400:1780:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:1800::,2400:1800:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:1880::,2400:1880:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:1900::,2400:1900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:1980::,2400:1980:ffff:ffff:ffff:ffff:ffff:ffff,AF +2400:1a00::,2400:1a00:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:1a80::,2400:1a80:ffff:ffff:ffff:ffff:ffff:ffff,PK +2400:1b00::,2400:1b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:1b80::,2400:1b80:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:1c00::,2400:1c00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:1c80::,2400:1c80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:1d00::,2400:1d00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:1d80::,2400:1d80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:1e00::,2400:1e00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:1e80::,2400:1e80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:1f00::,2400:1f00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:1f80::,2400:1f80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:2000::,2400:3000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:3080::,2400:3080:ffff:ffff:ffff:ffff:ffff:ffff,AF +2400:3100::,2400:3100:ffff:ffff:ffff:ffff:ffff:ffff,VU +2400:3180::,2400:3180:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:3200::,2400:3200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:3280::,2400:3280:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:3300::,2400:3300:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:3380::,2400:3380:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:3400::,2400:3400:ffff:ffff:ffff:ffff:ffff:ffff,VU +2400:3480::,2400:3480:ffff:ffff:ffff:ffff:ffff:ffff,TH +2400:3500::,2400:3500:ffff:ffff:ffff:ffff:ffff:ffff,TV +2400:3580::,2400:3580:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:3600::,2400:3600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:3680::,2400:3680:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:3700::,2400:3700:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:3800::,2400:3800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:3880::,2400:3880:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:3900::,2400:3900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:3980::,2400:3980:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:3a00::,2400:3a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:3a80::,2400:3a80:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:3b00::,2400:3b00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:3b80::,2400:3b80:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:3c00::,2400:3c00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:3c80::,2400:3c80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:3d00::,2400:3d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:3d80::,2400:3d80:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:3e00::,2400:3e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:3e80::,2400:3e80:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:3f00::,2400:3f00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:3f80::,2400:3f80:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:4000::,2400:43ff:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:4400::,2400:4400:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:4480::,2400:4480:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:4500::,2400:4500:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:4580::,2400:4580:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:4600::,2400:4600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:4680::,2400:4680:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:4700::,2400:4700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:4780::,2400:4780:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:4800::,2400:4800:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:4880::,2400:4880:ffff:ffff:ffff:ffff:ffff:ffff,KH +2400:4900::,2400:4900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:4980::,2400:4980:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:4a00::,2400:4a00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:4a80::,2400:4a80:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:4b00::,2400:4b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:4b80::,2400:4b80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:4c00::,2400:4c00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:4c80::,2400:4c80:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:4d00::,2400:4d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:4d80::,2400:4d80:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:4e00::,2400:4e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:4e80::,2400:4e80:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:4f00::,2400:4f00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2400:4f80::,2400:4f80:ffff:ffff:ffff:ffff:ffff:ffff,TH +2400:5000::,2400:5000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:5080::,2400:5080:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5100::,2400:5100:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:5180::,2400:5180:ffff:ffff:ffff:ffff:ffff:ffff,AF +2400:5200::,2400:5200:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:5280::,2400:5280:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5300::,2400:5300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:5380::,2400:5380:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:5400::,2400:5400:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5480::,2400:5480:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:5500::,2400:5500:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:5580::,2400:5580:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5600::,2400:5600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5680::,2400:5680:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:5700::,2400:5700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:5780::,2400:5780:ffff:ffff:ffff:ffff:ffff:ffff,TH +2400:5800::,2400:5800:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:5880::,2400:5880:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:5900::,2400:5900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:5980::,2400:5980:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:5a00::,2400:5a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5a80::,2400:5a80:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:5b00::,2400:5b00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:5b80::,2400:5b80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:5c00::,2400:5c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:5c80::,2400:5c80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5d00::,2400:5d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:5d80::,2400:5d80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:5e00::,2400:5e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:5e80::,2400:5e80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:5f00::,2400:5f00:ffff:ffff:ffff:ffff:ffff:ffff,PF +2400:5f80::,2400:5f80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:6000::,2400:6000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:6080::,2400:6080:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:6100::,2400:6100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:6180::,2400:6180:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:6200::,2400:6200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:6280::,2400:6280:ffff:ffff:ffff:ffff:ffff:ffff,TH +2400:6300::,2400:6300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:6380::,2400:6380:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:6400::,2400:6400:ffff:ffff:ffff:ffff:ffff:ffff,TO +2400:6480::,2400:6480:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:6500::,2400:6500:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:6580::,2400:6580:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:6600::,2400:6600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:6680::,2400:6680:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:6700::,2400:6700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:6780::,2400:6780:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:6800::,2400:6800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:6880::,2400:6880:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:6900::,2400:6900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:6980::,2400:6980:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:6a00::,2400:6a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:6a80::,2400:6a80:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:6b00::,2400:6b00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:6b80::,2400:6b80:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:6c00::,2400:6c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:6c80::,2400:6c80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:6d00::,2400:6d00:ffff:ffff:ffff:ffff:ffff:ffff,FJ +2400:6d80::,2400:6d80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:6e00::,2400:6e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:6e80::,2400:6e80:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:6f00::,2400:6f00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:6f80::,2400:6f80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:7000::,2400:7000:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:7080::,2400:7080:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:7100::,2400:7100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:7180::,2400:7180:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:7200::,2400:7200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:7300::,2400:7300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:7380::,2400:7380:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:7400::,2400:7400:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:7480::,2400:7480:ffff:ffff:ffff:ffff:ffff:ffff,MN +2400:7500::,2400:7500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:7580::,2400:7580:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:7600::,2400:7600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:7680::,2400:7680:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:7700::,2400:7700:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:7780::,2400:7780:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:7800::,2400:7800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:7880::,2400:7880:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:7900::,2400:7900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:7980::,2400:7980:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:7a00::,2400:7a00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:7a80::,2400:7a80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:7b00::,2400:7b00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:7b80::,2400:7b83:ffff:ffff:ffff:ffff:ffff:ffff,TH +2400:7c00::,2400:7c00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:7c80::,2400:7c80:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:7d00::,2400:7d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:7d80::,2400:7d80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:7e00::,2400:7e00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:7e80::,2400:7e80:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:7f00::,2400:7f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:7f80::,2400:7f80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8000::,2400:8000:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:8080::,2400:8080:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8100::,2400:8100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:8180::,2400:8180:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:8200::,2400:8200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8280::,2400:8280:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:8300::,2400:8300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:8380::,2400:8380:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:8400::,2400:8400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:8480::,2400:8480:ffff:ffff:ffff:ffff:ffff:ffff,MM +2400:8500::,2400:8500:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:8580::,2400:8580:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8600::,2400:8600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8680::,2400:8680:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:8700::,2400:8700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:8780::,2400:8780:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8800::,2400:8800:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:8880::,2400:8880:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:8900::,2400:8900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:8980::,2400:8980:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8a00::,2400:8a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:8a80::,2400:8a80:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:8b00::,2400:8b00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:8b80::,2400:8b80:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:8c00::,2400:8c00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:8c80::,2400:8c80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:8d00::,2400:8d00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:8d80::,2400:8d80:ffff:ffff:ffff:ffff:ffff:ffff,KH +2400:8e00::,2400:8e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8e80::,2400:8e80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:8f00::,2400:8f00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:8f80::,2400:8f80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:9000::,2400:9000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:9080::,2400:9080:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:9100::,2400:9100:ffff:ffff:ffff:ffff:ffff:ffff,VN +2400:9180::,2400:9180:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:9200::,2400:9200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:9280::,2400:9280:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:9300::,2400:9300:ffff:ffff:ffff:ffff:ffff:ffff,PG +2400:9380::,2400:9381:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:9400::,2400:9400:ffff:ffff:ffff:ffff:ffff:ffff,BN +2400:9480::,2400:9480:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:9500::,2400:9500:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:9580::,2400:9580:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:9600::,2400:9600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:9680::,2400:9680:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:9700::,2400:9700:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:9780::,2400:9780:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:9800::,2400:9800:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:9880::,2400:9880:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:9900::,2400:9900:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:9980::,2400:9980:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:9a00::,2400:9a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:9a80::,2400:9a80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:9b00::,2400:9b00:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:9b80::,2400:9b80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:9c00::,2400:9c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:9c80::,2400:9c80:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:9d00::,2400:9d00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:9d80::,2400:9d80:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:9e00::,2400:9e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:9e80::,2400:9e80:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:9f80::,2400:9f80:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:a000::,2400:a000:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:a080::,2400:a080:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:a100::,2400:a100:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:a180::,2400:a180:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:a280::,2400:a280:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:a300::,2400:a300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:a380::,2400:a380:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:a400::,2400:a400:ffff:ffff:ffff:ffff:ffff:ffff,NP +2400:a480::,2400:a480:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:a500::,2400:a500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:a580::,2400:a580:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:a600::,2400:a600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:a680::,2400:a680:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:a700::,2400:a700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:a780::,2400:a780:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:a800::,2400:a800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:a880::,2400:a880:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:a900::,2400:a900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:a980::,2400:a980:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:aa00::,2400:aa00:ffff:ffff:ffff:ffff:ffff:ffff,LA +2400:aa80::,2400:aa80:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:ab00::,2400:ab00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:ab80::,2400:ab80:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:ac00::,2400:ac00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:ac80::,2400:ac80:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:ad00::,2400:ad00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:ad80::,2400:ad80:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:ae00::,2400:ae00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:ae80::,2400:ae80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:af80::,2400:af80:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:b000::,2400:b000:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:b080::,2400:b080:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:b100::,2400:b100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:b180::,2400:b180:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:b200::,2400:b200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:b280::,2400:b280:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:b300::,2400:b300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:b380::,2400:b380:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:b400::,2400:b400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:b480::,2400:b480:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:b500::,2400:b500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:b580::,2400:b580:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:b600::,2400:b600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:b680::,2400:b680:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:b700::,2400:b700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:b780::,2400:b780:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:b800::,2400:b800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:b880::,2400:b880:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:b900::,2400:b900:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:b980::,2400:b980:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:ba00::,2400:ba00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:ba80::,2400:ba80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:bb00::,2400:bb00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:bb80::,2400:bb80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:bc00::,2400:bc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:bc80::,2400:bc80:ffff:ffff:ffff:ffff:ffff:ffff,VN +2400:bd00::,2400:bd00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:bd80::,2400:bd80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:be00::,2400:be00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:be80::,2400:be80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:bf00::,2400:bf00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:bf80::,2400:bf80:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:c000::,2400:c000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:c080::,2400:c080:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:c100::,2400:c100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:c180::,2400:c180:ffff:ffff:ffff:ffff:ffff:ffff,LA +2400:c200::,2400:c200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:c300::,2400:c300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:c380::,2400:c380:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:c400::,2400:c400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:c480::,2400:c480:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:c500::,2400:c500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:c580::,2400:c580:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:c600::,2400:c600:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:c680::,2400:c680:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:c700::,2400:c700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:c780::,2400:c780:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:c800::,2400:c807:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:c880::,2400:c880:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:c900::,2400:c900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:c980::,2400:c980:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:ca00::,2400:ca00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:ca80::,2400:ca80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:cb00::,2400:cb00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:cb80::,2400:cb80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:cc00::,2400:cc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:cc80::,2400:cc80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:cd00::,2400:cd00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2400:cd80::,2400:cd80:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:ce00::,2400:ce00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:ce80::,2400:ce80:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:cf00::,2400:cf00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:cf80::,2400:cf80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:d000::,2400:d000:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:d080::,2400:d080:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:d100::,2400:d100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:d180::,2400:d180:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:d200::,2400:d200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:d280::,2400:d280:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:d300::,2400:d300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:d380::,2400:d380:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:d400::,2400:d400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:d480::,2400:d480:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:d500::,2400:d500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:d580::,2400:d580:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:d600::,2400:d600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:d680::,2400:d680:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:d700::,2400:d700:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:d780::,2400:d780:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:d800::,2400:d803:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:d880::,2400:d880:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:d900::,2400:d900:ffff:ffff:ffff:ffff:ffff:ffff,LK +2400:d980::,2400:d980:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:da00::,2400:da00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:da80::,2400:da80:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:db00::,2400:db00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:db80::,2400:db80:ffff:ffff:ffff:ffff:ffff:ffff,MN +2400:dc00::,2400:dc00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:dc80::,2400:dc80:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:dd00::,2400:dd0f:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:dd80::,2400:dd80:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:de00::,2400:de00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:de80::,2400:de80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:df00::,2400:df00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:df80::,2400:df80:ffff:ffff:ffff:ffff:ffff:ffff,MY +2400:e000::,2400:e000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:e080::,2400:e080:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:e100::,2400:e100:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:e180::,2400:e180:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:e200::,2400:e200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:e280::,2400:e280:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:e300::,2400:e300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:e380::,2400:e380:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:e400::,2400:e400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:e480::,2400:e480:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:e500::,2400:e500:ffff:ffff:ffff:ffff:ffff:ffff,AF +2400:e580::,2400:e580:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:e680::,2400:e680:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:e780::,2400:e780:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:e880::,2400:e880:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:e900::,2400:e900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:e980::,2400:e980:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:ea00::,2400:ea00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2400:ea80::,2400:ea80:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:eb00::,2400:eb00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:eb80::,2400:eb80:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:ec00::,2400:ec00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:ec80::,2400:ec80:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:ed00::,2400:ed00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:ed80::,2400:ed80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:ee00::,2400:ee00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:ee80::,2400:ee80:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2400:ef00::,2400:ef00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:ef80::,2400:ef80:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:f000::,2400:f000:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:f080::,2400:f080:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:f100::,2400:f100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:f180::,2400:f180:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:f200::,2400:f200:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:f280::,2400:f280:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:f300::,2400:f300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:f380::,2400:f380:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:f400::,2400:f400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2400:f480::,2400:f480:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:f580::,2400:f580:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:f600::,2400:f600:ffff:ffff:ffff:ffff:ffff:ffff,PH +2400:f680::,2400:f680:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:f700::,2400:f700:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:f780::,2400:f780:ffff:ffff:ffff:ffff:ffff:ffff,IN +2400:f800::,2400:f800:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:f880::,2400:f880:ffff:ffff:ffff:ffff:ffff:ffff,HK +2400:f900::,2400:f900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:f980::,2400:f980:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:fa00::,2400:fa00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:fa80::,2400:fa80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:fb00::,2400:fb00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2400:fb80::,2400:fb80:ffff:ffff:ffff:ffff:ffff:ffff,SG +2400:fc00::,2400:fc00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2400:fc80::,2400:fc80:ffff:ffff:ffff:ffff:ffff:ffff,TW +2400:fd00::,2400:fd00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2400:fd80::,2400:fd80:ffff:ffff:ffff:ffff:ffff:ffff,KR +2400:fe00::,2400:fe00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2400:fe80::,2400:fe80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2400:ff00::,2400:ff00:ffff:ffff:ffff:ffff:ffff:ffff,LK +2400:ff80::,2400:ff80:ffff:ffff:ffff:ffff:ffff:ffff,AF +2401::,2401:1:ffff:ffff:ffff:ffff:ffff:ffff,PK +2401:80::,2401:80:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:100::,2401:100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:180::,2401:180:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:200::,2401:200:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:280::,2401:280:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:300::,2401:300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:380::,2401:380:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:400::,2401:400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:480::,2401:480:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:500::,2401:500:ffff:ffff:ffff:ffff:ffff:ffff,TH +2401:580::,2401:580:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:600::,2401:600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:680::,2401:680:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:700::,2401:700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:780::,2401:780:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:800::,2401:800:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:880::,2401:880:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:900::,2401:900:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:980::,2401:980:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:a00::,2401:a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:a80::,2401:a80:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:b00::,2401:b00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:c00::,2401:c00:ffff:ffff:ffff:ffff:ffff:ffff,NC +2401:d00::,2401:d00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:e00::,2401:e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:f00::,2401:f00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:1000::,2401:1000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:1100::,2401:1100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:1200::,2401:1200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:1300::,2401:1300:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:1400::,2401:1400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:1500::,2401:1500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:1600::,2401:1600:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:1700::,2401:1700:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:1800::,2401:1801:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:1900::,2401:1900:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:1a00::,2401:1a00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:1b00::,2401:1b00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:1c00::,2401:1c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:1d00::,2401:1d00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:1e00::,2401:1e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:1f00::,2401:1f01:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:2000::,2401:2000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:2001::,2401:2001:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:2100::,2401:2100:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:2200::,2401:2200:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:2300::,2401:2300:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:2400::,2401:2400:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:2500::,2401:2500:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:2600::,2401:2600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:2700::,2401:2700:ffff:ffff:ffff:ffff:ffff:ffff,KR +2401:2800::,2401:2800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:2900::,2401:2900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:2a00::,2401:2a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:2b00::,2401:2b00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:2c00::,2401:2c00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:2d00::,2401:2d00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:2e00::,2401:2e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:2f00::,2401:2f00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:3000::,2401:3000:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:3100::,2401:3100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:3200::,2401:3200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:3300::,2401:3300:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:3400::,2401:3400:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:3500::,2401:3500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:3600::,2401:3600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:3800::,2401:3800:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:3900::,2401:3900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:3a00::,2401:3a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:3b00::,2401:3b00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:3c00::,2401:3c00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:3d00::,2401:3d0f:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:3e00::,2401:3e00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2401:3f00::,2401:3f00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:4000::,2401:4000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2401:4100::,2401:4100:ffff:ffff:ffff:ffff:ffff:ffff,PK +2401:4200::,2401:4200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:4300::,2401:4300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:4400::,2401:4400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:4500::,2401:4500:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:4700::,2401:4700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:4800::,2401:4800:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:4900::,2401:4900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:4a00::,2401:4a00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:4b00::,2401:4b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:4c00::,2401:4c00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:4d00::,2401:4d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:4e00::,2401:4e00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:4f00::,2401:4f00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2401:5000::,2401:5000:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:5100::,2401:5100:ffff:ffff:ffff:ffff:ffff:ffff,FJ +2401:5200::,2401:5200:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:5300::,2401:5300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:5400::,2401:5400:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:5500::,2401:5500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:5700::,2401:5700:ffff:ffff:ffff:ffff:ffff:ffff,TH +2401:5800::,2401:5800:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:5900::,2401:5900:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:5a00::,2401:5a00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:5b00::,2401:5b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:5c00::,2401:5c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:5d00::,2401:5d00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:5e00::,2401:5e00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2401:5f00::,2401:5f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:6000::,2401:6fff:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:7000::,2401:7000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:7100::,2401:7100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:7200::,2401:7200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:7300::,2401:7300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:7400::,2401:7401:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:7500::,2401:7500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:7600::,2401:7600:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:7700::,2401:7700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:7800::,2401:7800:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:7900::,2401:7900:ffff:ffff:ffff:ffff:ffff:ffff,LK +2401:7a00::,2401:7a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:7b00::,2401:7b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:7c00::,2401:7c00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:7d00::,2401:7d00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:7e00::,2401:7e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:7f00::,2401:7f00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:8000::,2401:803f:ffff:ffff:ffff:ffff:ffff:ffff,TW +2401:8100::,2401:8100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:8200::,2401:8200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:8300::,2401:8300:ffff:ffff:ffff:ffff:ffff:ffff,MV +2401:8400::,2401:8400:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:8500::,2401:8500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:8600::,2401:8600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:8700::,2401:8700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:8800::,2401:8800:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:8900::,2401:8900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:8a00::,2401:8a00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:8b00::,2401:8b00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:8c00::,2401:8c01:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:8d00::,2401:8d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:8e00::,2401:8e00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2401:8f00::,2401:8f00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:9100::,2401:9100:ffff:ffff:ffff:ffff:ffff:ffff,MO +2401:9200::,2401:9200:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:9300::,2401:9300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:9400::,2401:9400:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:9500::,2401:9500:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:9600::,2401:9600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:9700::,2401:9700:ffff:ffff:ffff:ffff:ffff:ffff,KH +2401:9800::,2401:9800:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:9900::,2401:9900:ffff:ffff:ffff:ffff:ffff:ffff,LK +2401:9a00::,2401:9a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:9b00::,2401:9b00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:9c00::,2401:9c00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:9d00::,2401:9d00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2401:9e00::,2401:9e00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2401:9f00::,2401:9f00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:a000::,2401:a000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2401:a100::,2401:a100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:a300::,2401:a300:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:a400::,2401:a400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:a500::,2401:a500:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:a600::,2401:a600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:a700::,2401:a700:ffff:ffff:ffff:ffff:ffff:ffff,KH +2401:a800::,2401:a800:ffff:ffff:ffff:ffff:ffff:ffff,KR +2401:a900::,2401:a900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:aa00::,2401:aa00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:ab00::,2401:ab00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2401:ac00::,2401:ac00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:ad00::,2401:ad00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:ae00::,2401:ae00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:af00::,2401:af00:ffff:ffff:ffff:ffff:ffff:ffff,NC +2401:b000::,2401:b000:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:b100::,2401:b100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:b200::,2401:b200:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:b300::,2401:b300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:b400::,2401:b400:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:b500::,2401:b500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:b600::,2401:b600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:b700::,2401:b700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:b800::,2401:b800:ffff:ffff:ffff:ffff:ffff:ffff,VN +2401:b900::,2401:b900:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:ba00::,2401:ba00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:bb00::,2401:bb00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:bc00::,2401:bc00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2401:bd00::,2401:bd00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:be00::,2401:be00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:bf00::,2401:bf00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:c000::,2401:c000:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:c100::,2401:c100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:c200::,2401:c200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:c300::,2401:c300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:c400::,2401:c400:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:c500::,2401:c500:ffff:ffff:ffff:ffff:ffff:ffff,KR +2401:c600::,2401:c600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:c700::,2401:c700:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:c800::,2401:c800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:c900::,2401:c901:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:ca00::,2401:ca00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:cb00::,2401:cb00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2401:cc00::,2401:cc00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:cd00::,2401:cd00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:ce00::,2401:ce00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:cf00::,2401:cf00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:d000::,2401:d000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:d100::,2401:d100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:d200::,2401:d200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:d300::,2401:d300:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:d400::,2401:d400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:d500::,2401:d500:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:d600::,2401:d600:ffff:ffff:ffff:ffff:ffff:ffff,MN +2401:d700::,2401:d700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:d800::,2401:d800:ffff:ffff:ffff:ffff:ffff:ffff,VN +2401:d900::,2401:d900:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:da00::,2401:da00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:db00::,2401:db00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:dc00::,2401:dc00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:dd00::,2401:dd00:ffff:ffff:ffff:ffff:ffff:ffff,LK +2401:de00::,2401:de00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:df00::,2401:df01:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:e000::,2401:e000:ffff:ffff:ffff:ffff:ffff:ffff,TH +2401:e100::,2401:e100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:e200::,2401:e200:ffff:ffff:ffff:ffff:ffff:ffff,KR +2401:e300::,2401:e300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:e400::,2401:e400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:e500::,2401:e500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:e600::,2401:e600:ffff:ffff:ffff:ffff:ffff:ffff,FJ +2401:e700::,2401:e700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:e800::,2401:e800:ffff:ffff:ffff:ffff:ffff:ffff,VN +2401:e900::,2401:e900:ffff:ffff:ffff:ffff:ffff:ffff,BD +2401:ea00::,2401:ea00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2401:eb00::,2401:eb00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:ec00::,2401:ec00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:ed00::,2401:ed00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:ee00::,2401:ee00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2401:ef00::,2401:ef00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:f000::,2401:f000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:f100::,2401:f100:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:f200::,2401:f200:ffff:ffff:ffff:ffff:ffff:ffff,MM +2401:f300::,2401:f300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2401:f400::,2401:f400:ffff:ffff:ffff:ffff:ffff:ffff,HK +2401:f500::,2401:f500:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2401:f600::,2401:f600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:f700::,2401:f700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:f800::,2401:f800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2401:f900::,2401:f900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2401:fa00::,2401:fa00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:fb00::,2401:fb00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2401:fc00::,2401:fc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:fd00::,2401:fd00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2401:fe00::,2401:fe00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2401:ff00::,2401:ff00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402::,2402:3ff:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:400::,2402:400:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:500::,2402:500:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:600::,2402:600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:700::,2402:700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:800::,2402:800:ffff:ffff:ffff:ffff:ffff:ffff,VN +2402:900::,2402:900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:a00::,2402:a00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:b00::,2402:b00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:c00::,2402:c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:d00::,2402:d00:ffff:ffff:ffff:ffff:ffff:ffff,AF +2402:e00::,2402:e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:f00::,2402:f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:1000::,2402:1000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:1100::,2402:1100:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:1200::,2402:1200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:1300::,2402:1300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:1400::,2402:1400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:1500::,2402:1500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2402:1600::,2402:1600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:1700::,2402:1700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:1800::,2402:1800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:1900::,2402:1900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:1a00::,2402:1a00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:1b00::,2402:1b00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:1c00::,2402:1c00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:1d00::,2402:1d00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:1e00::,2402:1e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:1f00::,2402:1f00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2402:2000::,2402:2000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:2100::,2402:2100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2402:2200::,2402:2200:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:2300::,2402:2300:ffff:ffff:ffff:ffff:ffff:ffff,BD +2402:2400::,2402:2400:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:2500::,2402:2500:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:2600::,2402:2600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:2700::,2402:2700:ffff:ffff:ffff:ffff:ffff:ffff,TH +2402:2800::,2402:2800:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:2900::,2402:2900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:2a00::,2402:2a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:2b00::,2402:2b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:2c00::,2402:2c00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:2d00::,2402:2d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:2f00::,2402:2f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:3000::,2402:3000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:3100::,2402:3100:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:3200::,2402:3200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:3300::,2402:3300:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:3400::,2402:3400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:3500::,2402:3500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:3600::,2402:3600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:3700::,2402:3700:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:3800::,2402:3800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:3900::,2402:3900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:3a00::,2402:3a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:3b00::,2402:3b00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:3c00::,2402:3c00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:3d00::,2402:3d00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:3e00::,2402:3e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:3f00::,2402:3f00:ffff:ffff:ffff:ffff:ffff:ffff,MN +2402:4000::,2402:4000:ffff:ffff:ffff:ffff:ffff:ffff,LK +2402:4100::,2402:4100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:4200::,2402:4200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:4300::,2402:4300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:4400::,2402:4400:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:4500::,2402:4500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:4600::,2402:4600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:4700::,2402:4700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:4800::,2402:4800:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:4900::,2402:4900:ffff:ffff:ffff:ffff:ffff:ffff,TW +2402:4a00::,2402:4a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:4b00::,2402:4b00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:4c00::,2402:4c01:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:4d00::,2402:4d00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2402:4e00::,2402:4e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:4f00::,2402:4f00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2402:5100::,2402:5100:ffff:ffff:ffff:ffff:ffff:ffff,KH +2402:5200::,2402:5200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:5300::,2402:5300:ffff:ffff:ffff:ffff:ffff:ffff,VN +2402:5400::,2402:5400:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:5500::,2402:5500:ffff:ffff:ffff:ffff:ffff:ffff,PH +2402:5600::,2402:5600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:5700::,2402:5700:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:5800::,2402:5800:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:5900::,2402:5900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:5a00::,2402:5a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:5b00::,2402:5b00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:5c00::,2402:5c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:5d00::,2402:5d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:5e00::,2402:5e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:5f00::,2402:5f00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:6000::,2402:6000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:6100::,2402:6100:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:6200::,2402:6200:ffff:ffff:ffff:ffff:ffff:ffff,GU +2402:6300::,2402:6300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:6400::,2402:6400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:6500::,2402:6500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:6600::,2402:6600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:6700::,2402:6700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:6800::,2402:6800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:6900::,2402:6900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:6a00::,2402:6a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:6b00::,2402:6bff:ffff:ffff:ffff:ffff:ffff:ffff,KE +2402:6c00::,2402:6c00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:6d00::,2402:6d00:ffff:ffff:ffff:ffff:ffff:ffff,PF +2402:6e00::,2402:6e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:6f00::,2402:6f00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2402:7000::,2402:7000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:7100::,2402:7100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:7200::,2402:7200:ffff:ffff:ffff:ffff:ffff:ffff,TK +2402:7300::,2402:7300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2402:7400::,2402:7400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:7500::,2402:7500:ffff:ffff:ffff:ffff:ffff:ffff,TW +2402:7600::,2402:7600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:7700::,2402:7700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:7800::,2402:7800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:7900::,2402:7900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:7a00::,2402:7a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:7b00::,2402:7b00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:7c00::,2402:7c00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2402:7d00::,2402:7d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:7e00::,2402:7e00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:7f00::,2402:7f00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:8000::,2402:8000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:8100::,2402:8100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:8200::,2402:8200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:8300::,2402:8300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:8400::,2402:8400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:8500::,2402:8500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:8600::,2402:8600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:8700::,2402:8700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:8800::,2402:8800:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:8900::,2402:8900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:8a00::,2402:8a00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:8b00::,2402:8b00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:8c00::,2402:8c00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:8d00::,2402:8d03:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:8e00::,2402:8e00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:8f00::,2402:8f00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:9100::,2402:9100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:9200::,2402:9200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:9300::,2402:9300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:9400::,2402:9400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:9500::,2402:9500:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:9800::,2402:9800:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:9900::,2402:9900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:9a00::,2402:9a00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:9b00::,2402:9b00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2402:9c00::,2402:9c00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2402:9d00::,2402:9d00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2402:9e00::,2402:9e00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:9f00::,2402:9f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:a000::,2402:a000:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:a100::,2402:a100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:a200::,2402:a200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:a300::,2402:a300:ffff:ffff:ffff:ffff:ffff:ffff,NP +2402:a400::,2402:a400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:a500::,2402:a500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:a600::,2402:a600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:a700::,2402:a700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:a800::,2402:a800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:a900::,2402:a900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:ab00::,2402:ab00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:ac00::,2402:ac00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:ad00::,2402:ad00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:ae00::,2402:ae00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:af00::,2402:af00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:b100::,2402:b100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:b200::,2402:b200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:b300::,2402:b300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:b400::,2402:b400:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:b500::,2402:b500:ffff:ffff:ffff:ffff:ffff:ffff,BD +2402:b600::,2402:b600:ffff:ffff:ffff:ffff:ffff:ffff,TW +2402:b700::,2402:b700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:b800::,2402:b801:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:b900::,2402:b900:ffff:ffff:ffff:ffff:ffff:ffff,MN +2402:ba00::,2402:ba00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2402:bb00::,2402:bb00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:bc00::,2402:bc07:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:bd00::,2402:bd00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:be00::,2402:be00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:bf00::,2402:bf00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2402:c000::,2402:c000:ffff:ffff:ffff:ffff:ffff:ffff,BD +2402:c100::,2402:c100:ffff:ffff:ffff:ffff:ffff:ffff,KH +2402:c200::,2402:c200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:c300::,2402:c300:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:c400::,2402:c400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:c500::,2402:c500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:c600::,2402:c600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:c700::,2402:c700:ffff:ffff:ffff:ffff:ffff:ffff,VN +2402:c800::,2402:c800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:c900::,2402:c900:ffff:ffff:ffff:ffff:ffff:ffff,MN +2402:ca00::,2402:ca00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:cb00::,2402:cb00:ffff:ffff:ffff:ffff:ffff:ffff,LK +2402:cc00::,2402:cc00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:cd00::,2402:cd00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:ce00::,2402:ce01:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:cf00::,2402:cf00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:d000::,2402:d000:ffff:ffff:ffff:ffff:ffff:ffff,LK +2402:d100::,2402:d100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:d200::,2402:d200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:d300::,2402:d300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:d400::,2402:d400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:d500::,2402:d500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:d600::,2402:d600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:d700::,2402:d700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:d800::,2402:d800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:d900::,2402:d900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:da00::,2402:da00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:db00::,2402:db00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:dc00::,2402:dc00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:de00::,2402:de00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:df00::,2402:df00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:e000::,2402:e000:ffff:ffff:ffff:ffff:ffff:ffff,PK +2402:e100::,2402:e100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:e200::,2402:e200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:e300::,2402:e300:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:e400::,2402:e400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:e500::,2402:e500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:e600::,2402:e600:ffff:ffff:ffff:ffff:ffff:ffff,SG +2402:e800::,2402:e800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:e900::,2402:e900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:ea00::,2402:ea00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:eb00::,2402:eb00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:ec00::,2402:ec00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:ed00::,2402:ed00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2402:ee00::,2402:ee00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:ef00::,2402:ef3f:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:f000::,2402:f000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2402:f100::,2402:f100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:f200::,2402:f200:ffff:ffff:ffff:ffff:ffff:ffff,IN +2402:f300::,2402:f300:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:f400::,2402:f400:ffff:ffff:ffff:ffff:ffff:ffff,KR +2402:f500::,2402:f500:ffff:ffff:ffff:ffff:ffff:ffff,BD +2402:f600::,2402:f600:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:f700::,2402:f700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:f800::,2402:f800:ffff:ffff:ffff:ffff:ffff:ffff,VN +2402:f900::,2402:f900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2402:fa00::,2402:fa00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2402:fb00::,2402:fb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2402:fc00::,2402:fc00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2402:fd00::,2402:fd00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2402:fe00::,2402:fe00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2402:ff00::,2402:ff00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403::,2403:1:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:100::,2403:100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:200::,2403:200:ffff:ffff:ffff:ffff:ffff:ffff,NC +2403:300::,2403:300:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:400::,2403:400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:500::,2403:500:ffff:ffff:ffff:ffff:ffff:ffff,LA +2403:600::,2403:600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:700::,2403:700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:800::,2403:801:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:900::,2403:900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:a00::,2403:a00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:b00::,2403:b00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:c00::,2403:c00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:d00::,2403:d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:e00::,2403:e00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:f00::,2403:f00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:1000::,2403:1000:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:1100::,2403:1100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:1300::,2403:1300:ffff:ffff:ffff:ffff:ffff:ffff,MY +2403:1400::,2403:1400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:1500::,2403:1500:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:1600::,2403:1600:ffff:ffff:ffff:ffff:ffff:ffff,KH +2403:1700::,2403:1700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:1800::,2403:1800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:1900::,2403:1900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:1a00::,2403:1a00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:1b00::,2403:1b00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:1c00::,2403:1c00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:1d00::,2403:1d00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:1e00::,2403:1e00:ffff:ffff:ffff:ffff:ffff:ffff,AS +2403:1f00::,2403:1f00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:2000::,2403:2000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:2100::,2403:2100:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:2200::,2403:2200:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:2300::,2403:2300:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:2400::,2403:2400:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:2500::,2403:2500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:2600::,2403:2600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:2700::,2403:2700:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:2800::,2403:2801:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:2900::,2403:2900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:2a00::,2403:2a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:2c00::,2403:2c00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:2d00::,2403:2d00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:2e00::,2403:2e00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:2f00::,2403:2f00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:3100::,2403:3100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:3200::,2403:3200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:3300::,2403:3300:ffff:ffff:ffff:ffff:ffff:ffff,NL +2403:3400::,2403:3400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:3500::,2403:3500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:3600::,2403:3600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:3700::,2403:3700:ffff:ffff:ffff:ffff:ffff:ffff,KR +2403:3800::,2403:3800:ffff:ffff:ffff:ffff:ffff:ffff,NP +2403:3900::,2403:3900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:3a00::,2403:3a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:3b00::,2403:3b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:3c00::,2403:3c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:3d00::,2403:3d00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:3e00::,2403:3e00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2403:3f00::,2403:3f00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2403:4000::,2403:4000:ffff:ffff:ffff:ffff:ffff:ffff,BD +2403:4100::,2403:4100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:4200::,2403:4200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:4300::,2403:4300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:4400::,2403:4400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:4500::,2403:4500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:4600::,2403:4600:ffff:ffff:ffff:ffff:ffff:ffff,FJ +2403:4700::,2403:4700:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:4800::,2403:4800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:4900::,2403:4900:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:4a00::,2403:4a00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:4b00::,2403:4b00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:4c00::,2403:4c00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:4d00::,2403:4d00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:4e00::,2403:4e00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:4f00::,2403:4f00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:5000::,2403:5000:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:5100::,2403:5100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:5200::,2403:5200:ffff:ffff:ffff:ffff:ffff:ffff,TW +2403:5300::,2403:5300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:5400::,2403:5400:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:5500::,2403:5500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:5600::,2403:5600:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:5700::,2403:5700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:5800::,2403:5800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:5900::,2403:5900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:5a00::,2403:5a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:5b00::,2403:5b00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:5c00::,2403:5c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:5e00::,2403:5e00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2403:5f00::,2403:5f00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:6000::,2403:6000:ffff:ffff:ffff:ffff:ffff:ffff,VN +2403:6100::,2403:6100:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:6200::,2403:6200:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:6300::,2403:6300:ffff:ffff:ffff:ffff:ffff:ffff,KR +2403:6400::,2403:6400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:6500::,2403:6500:ffff:ffff:ffff:ffff:ffff:ffff,KR +2403:6600::,2403:6600:ffff:ffff:ffff:ffff:ffff:ffff,KH +2403:6700::,2403:6700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:6800::,2403:6800:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:6900::,2403:6900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:6a00::,2403:6a00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:6b00::,2403:6b00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:6c00::,2403:6c00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:6d00::,2403:6d00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:6e00::,2403:6e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:7000::,2403:7000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:7100::,2403:7100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:7200::,2403:7200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:7300::,2403:7300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:7400::,2403:7400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:7500::,2403:7500:ffff:ffff:ffff:ffff:ffff:ffff,KH +2403:7600::,2403:7600:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:7700::,2403:7700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:7800::,2403:7800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:7900::,2403:7900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:7a00::,2403:7a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:7b00::,2403:7b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:7c00::,2403:7c00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:7d00::,2403:7d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:7e00::,2403:7e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:7f00::,2403:7f00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:8000::,2403:8000:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:8100::,2403:8100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:8200::,2403:8200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:8300::,2403:8300:ffff:ffff:ffff:ffff:ffff:ffff,DE +2403:8400::,2403:8400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:8500::,2403:8500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:8600::,2403:8600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:8700::,2403:8700:ffff:ffff:ffff:ffff:ffff:ffff,BT +2403:8800::,2403:8800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:8900::,2403:8900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:8a00::,2403:8a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:8b00::,2403:8b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:8c00::,2403:8c00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:8d00::,2403:8d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:8e00::,2403:8e00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:8f00::,2403:8f00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:9000::,2403:9000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:9100::,2403:9100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:9200::,2403:9200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:9300::,2403:9300:ffff:ffff:ffff:ffff:ffff:ffff,BD +2403:9400::,2403:9400:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:9500::,2403:9500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:9600::,2403:9600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:9700::,2403:9700:ffff:ffff:ffff:ffff:ffff:ffff,MY +2403:9800::,2403:9800:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:9900::,2403:9a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:9b00::,2403:9b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:9c00::,2403:9c00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:9d00::,2403:9d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:9e00::,2403:9e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:9f00::,2403:9f00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2403:a000::,2403:a000:ffff:ffff:ffff:ffff:ffff:ffff,PH +2403:a100::,2403:a100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:a200::,2403:a200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:a300::,2403:a300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:a400::,2403:a400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:a500::,2403:a500:ffff:ffff:ffff:ffff:ffff:ffff,PK +2403:a600::,2403:a600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:a700::,2403:a700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:a800::,2403:a800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:a900::,2403:a900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:aa00::,2403:aa00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:ab00::,2403:ab00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:ac00::,2403:ac00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:ad00::,2403:ad00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:ae00::,2403:ae00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:af00::,2403:af00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:b000::,2403:b000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:b100::,2403:b100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:b200::,2403:b200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:b300::,2403:b300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:b400::,2403:b400:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:b500::,2403:b500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:b600::,2403:b600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:b700::,2403:b700:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:b800::,2403:b800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:b900::,2403:b900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:ba00::,2403:ba00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:bb00::,2403:bb00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:bc00::,2403:bc00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2403:bd00::,2403:bd00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:be00::,2403:be00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:bf00::,2403:bf00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:c000::,2403:c000:ffff:ffff:ffff:ffff:ffff:ffff,TH +2403:c100::,2403:c100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:c200::,2403:c200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:c300::,2403:c300:ffff:ffff:ffff:ffff:ffff:ffff,TW +2403:c400::,2403:c400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:c500::,2403:c500:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:c600::,2403:c600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:c800::,2403:c800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:c900::,2403:c900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:ca00::,2403:ca00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:cb00::,2403:cb00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:cc00::,2403:cc00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:cd00::,2403:cd00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2403:ce00::,2403:ce00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:cf00::,2403:cf00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:d000::,2403:d000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:d100::,2403:d100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:d200::,2403:d200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:d300::,2403:d300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:d400::,2403:d400:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:d500::,2403:d500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:d600::,2403:d600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:d700::,2403:d700:ffff:ffff:ffff:ffff:ffff:ffff,MN +2403:d800::,2403:d800:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:d900::,2403:d900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:da00::,2403:da00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:db00::,2403:db00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:dc00::,2403:dc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:dd00::,2403:dd00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2403:de00::,2403:de00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:df00::,2403:df00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:e000::,2403:e000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:e100::,2403:e100:ffff:ffff:ffff:ffff:ffff:ffff,BD +2403:e200::,2403:e200:ffff:ffff:ffff:ffff:ffff:ffff,VN +2403:e300::,2403:e300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:e400::,2403:e400:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:e500::,2403:e500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:e600::,2403:e600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2403:e700::,2403:e700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:e800::,2403:e800:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:e900::,2403:e900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2403:ea00::,2403:ea00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:eb00::,2403:eb00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2403:ec00::,2403:ec00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2403:ed00::,2403:ed00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:ee00::,2403:ee00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2403:f000::,2403:f000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:f100::,2403:f100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:f200::,2403:f200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2403:f300::,2403:f300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:f400::,2403:f400:ffff:ffff:ffff:ffff:ffff:ffff,BD +2403:f500::,2403:f500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:f600::,2403:f600:ffff:ffff:ffff:ffff:ffff:ffff,NR +2403:f700::,2403:f700:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2403:f800::,2403:f800:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:f900::,2403:f900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:fa00::,2403:fa00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2403:fb00::,2403:fb00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2403:fc00::,2403:fc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:fd00::,2403:fd00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2403:fe00::,2403:fe00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2403:ff00::,2403:ff00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404::,2404:3f:ffff:ffff:ffff:ffff:ffff:ffff,TW +2404:80::,2404:8f:ffff:ffff:ffff:ffff:ffff:ffff,TW +2404:a0::,2404:a0:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:a8::,2404:a8:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:b0::,2404:b1:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:b8::,2404:b8:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:c0::,2404:c0:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:c8::,2404:c8:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:d0::,2404:d0:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:d8::,2404:d8:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:e0::,2404:ef:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:100::,2404:100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:130::,2404:130:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:138::,2404:139:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:140::,2404:140:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:150::,2404:150:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:158::,2404:158:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:160::,2404:160:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:168::,2404:168:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:170::,2404:170:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:178::,2404:178:ffff:ffff:ffff:ffff:ffff:ffff,TW +2404:180::,2404:18f:ffff:ffff:ffff:ffff:ffff:ffff,KR +2404:1a0::,2404:1a3:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:1a8::,2404:1a8:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:1b0::,2404:1b0:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:1b8::,2404:1b8:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:200::,2404:200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:300::,2404:300:ffff:ffff:ffff:ffff:ffff:ffff,KH +2404:400::,2404:400:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:500::,2404:500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:600::,2404:600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:700::,2404:700:ffff:ffff:ffff:ffff:ffff:ffff,KH +2404:800::,2404:800:ffff:ffff:ffff:ffff:ffff:ffff,KR +2404:a00::,2404:a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:b00::,2404:b00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:c00::,2404:c00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:d00::,2404:d00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:e00::,2404:e00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:f00::,2404:f00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:1000::,2404:1000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:1100::,2404:1100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:1200::,2404:1200:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:1300::,2404:1300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:1400::,2404:1400:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:1500::,2404:1500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:1600::,2404:1600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:1700::,2404:1700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:1800::,2404:1800:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:1900::,2404:1900:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:1a00::,2404:1a00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:1b00::,2404:1b00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:1c00::,2404:1c00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:1d00::,2404:1d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:1e00::,2404:1e00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:1f00::,2404:1f00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:2000::,2404:2000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:2100::,2404:2100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:2200::,2404:2200:ffff:ffff:ffff:ffff:ffff:ffff,NC +2404:2300::,2404:2300:ffff:ffff:ffff:ffff:ffff:ffff,KR +2404:2400::,2404:2400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:2500::,2404:2500:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:2600::,2404:2600:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:2700::,2404:2700:ffff:ffff:ffff:ffff:ffff:ffff,MN +2404:2800::,2404:2800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:2900::,2404:2900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:2a00::,2404:2a00:ffff:ffff:ffff:ffff:ffff:ffff,NC +2404:2b00::,2404:2b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:2c00::,2404:2c00:ffff:ffff:ffff:ffff:ffff:ffff,NP +2404:2d00::,2404:2d00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:2e00::,2404:2e00:ffff:ffff:ffff:ffff:ffff:ffff,LA +2404:2f00::,2404:2f00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:3100::,2404:3100:ffff:ffff:ffff:ffff:ffff:ffff,PK +2404:3200::,2404:3200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:3300::,2404:3300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:3500::,2404:3500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:3600::,2404:3601:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:3700::,2404:3700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:3800::,2404:3800:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:3900::,2404:3900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:3a00::,2404:3a00:ffff:ffff:ffff:ffff:ffff:ffff,VN +2404:3b00::,2404:3b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:3c00::,2404:3c00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:3d00::,2404:3d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:3e00::,2404:3e00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:3f00::,2404:3f00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:4100::,2404:4100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:4200::,2404:4200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:4300::,2404:4300:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:4400::,2404:440f:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:4600::,2404:4600:ffff:ffff:ffff:ffff:ffff:ffff,KR +2404:4700::,2404:4700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:4800::,2404:4800:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:4900::,2404:4900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:4a00::,2404:4a00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:4c00::,2404:4c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:4d00::,2404:4d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:4e00::,2404:4e00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:4f00::,2404:4f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:5000::,2404:5000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:5100::,2404:5100:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:5200::,2404:5200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:5300::,2404:5300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:5400::,2404:5400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:5500::,2404:5500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:5600::,2404:5600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:5700::,2404:5700:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:5800::,2404:5800:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:5900::,2404:5900:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:5a00::,2404:5a00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:5b00::,2404:5b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:5c00::,2404:5c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:5d00::,2404:5d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:5e00::,2404:5e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:5f00::,2404:5f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:6000::,2404:6000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:6100::,2404:6100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:6200::,2404:6200:ffff:ffff:ffff:ffff:ffff:ffff,TW +2404:6300::,2404:6300:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:6400::,2404:6400:ffff:ffff:ffff:ffff:ffff:ffff,PG +2404:6500::,2404:6500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:6600::,2404:6600:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:6700::,2404:6700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:6800::,2404:6800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:6900::,2404:6900:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:6a00::,2404:6a00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:6b00::,2404:6b00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:6c00::,2404:6c00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:6d00::,2404:6d00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:6e00::,2404:6e00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:6f00::,2404:6f00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:7000::,2404:7000:ffff:ffff:ffff:ffff:ffff:ffff,PK +2404:7100::,2404:7100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:7200::,2404:7200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:7300::,2404:7300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:7400::,2404:7400:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:7500::,2404:7500:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:7600::,2404:7600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:7700::,2404:7700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:7800::,2404:7800:ffff:ffff:ffff:ffff:ffff:ffff,PW +2404:7900::,2404:7900:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:7a00::,2404:7a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:7b00::,2404:7b00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:7c00::,2404:7c00:ffff:ffff:ffff:ffff:ffff:ffff,NP +2404:7d00::,2404:7d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:7e00::,2404:7e00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:7f00::,2404:7f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:8000::,2404:8000:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:8100::,2404:8100:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:8200::,2404:8200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:8300::,2404:8300:ffff:ffff:ffff:ffff:ffff:ffff,PK +2404:8500::,2404:8500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:8600::,2404:8600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:8700::,2404:8700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:8800::,2404:8800:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:8900::,2404:8900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:8a00::,2404:8a00:ffff:ffff:ffff:ffff:ffff:ffff,LK +2404:8b00::,2404:8b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:8c00::,2404:8c00:ffff:ffff:ffff:ffff:ffff:ffff,GU +2404:8d00::,2404:8d00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:8e00::,2404:8e01:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:8f00::,2404:8f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:9000::,2404:9000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:9100::,2404:9100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:9200::,2404:9200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:9400::,2404:9400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:9500::,2404:9500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:9600::,2404:9601:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:9700::,2404:9700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:9800::,2404:9800:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:9900::,2404:9900:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:9a00::,2404:9a00:ffff:ffff:ffff:ffff:ffff:ffff,GU +2404:9b00::,2404:9b00:ffff:ffff:ffff:ffff:ffff:ffff,AF +2404:9c00::,2404:9c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:9d00::,2404:9d00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:9e00::,2404:9e00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:9f00::,2404:9f00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:a000::,2404:a000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:a100::,2404:a100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:a200::,2404:a200:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:a300::,2404:a300:ffff:ffff:ffff:ffff:ffff:ffff,TH +2404:a500::,2404:a500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:a600::,2404:a600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:a700::,2404:a700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:a800::,2404:a800:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:aa00::,2404:aa00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:ab00::,2404:ab00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:ac00::,2404:ac00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:ad00::,2404:ad00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:ae00::,2404:ae00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:af00::,2404:af00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:b000::,2404:b000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:b100::,2404:b100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:b200::,2404:b200:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:b300::,2404:b300:ffff:ffff:ffff:ffff:ffff:ffff,KH +2404:b400::,2404:b400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:b500::,2404:b500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:b600::,2404:b600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:b700::,2404:b700:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:b800::,2404:b800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:b900::,2404:b900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:ba00::,2404:ba00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:bb00::,2404:bb00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:bc00::,2404:bc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:bd00::,2404:bd00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:be00::,2404:be00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2404:bf00::,2404:bf00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:c000::,2404:c000:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:c100::,2404:c100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:c200::,2404:c200:ffff:ffff:ffff:ffff:ffff:ffff,LA +2404:c300::,2404:c300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:c400::,2404:c400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:c500::,2404:c500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:c600::,2404:c600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:c700::,2404:c700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:c800::,2404:c807:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:c900::,2404:c900:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:ca00::,2404:ca00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:cb00::,2404:cb00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:cc00::,2404:cc00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2404:cd00::,2404:cd00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:ce00::,2404:ce00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:cf00::,2404:cf00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:d000::,2404:d000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:d100::,2404:d100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:d200::,2404:d200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:d300::,2404:d300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:d400::,2404:d400:ffff:ffff:ffff:ffff:ffff:ffff,PK +2404:d500::,2404:d500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:d600::,2404:d600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:d700::,2404:d700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:d800::,2404:d800:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:d900::,2404:d900:ffff:ffff:ffff:ffff:ffff:ffff,BD +2404:da00::,2404:da00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:db00::,2404:db00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2404:dc00::,2404:dc00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2404:dd00::,2404:dd00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:de00::,2404:de00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:df00::,2404:df00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2404:e000::,2404:e000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:e100::,2404:e101:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:e200::,2404:e200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2404:e300::,2404:e300:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:e400::,2404:e400:ffff:ffff:ffff:ffff:ffff:ffff,NC +2404:e500::,2404:e500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:e600::,2404:e600:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:e700::,2404:e700:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:e800::,2404:e8ff:ffff:ffff:ffff:ffff:ffff:ffff,SH +2404:e900::,2404:e900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:ea00::,2404:ea00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:eb00::,2404:eb00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:ec00::,2404:ec00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:ed00::,2404:ed00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:ee00::,2404:ee00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:ef00::,2404:ef00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:f000::,2404:f000:ffff:ffff:ffff:ffff:ffff:ffff,LK +2404:f100::,2404:f100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2404:f200::,2404:f200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:f300::,2404:f300:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:f400::,2404:f400:ffff:ffff:ffff:ffff:ffff:ffff,PK +2404:f500::,2404:f500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:f600::,2404:f600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:f700::,2404:f700:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:f800::,2404:f800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2404:f801::,2404:f801:ffff:ffff:ffff:ffff:ffff:ffff,SG +2404:f900::,2404:f900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:fa00::,2404:fa00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:fb00::,2404:fb00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:fc00::,2404:fc00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2404:fd00::,2404:fd00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2404:fe00::,2404:fe00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2404:ff00::,2404:ff00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405::,2405::ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:100::,2405:100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:200::,2405:207:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:400::,2405:400:ffff:ffff:ffff:ffff:ffff:ffff,MH +2405:500::,2405:500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:600::,2405:600:ffff:ffff:ffff:ffff:ffff:ffff,MN +2405:700::,2405:700:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:800::,2405:800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:900::,2405:900:ffff:ffff:ffff:ffff:ffff:ffff,LA +2405:a00::,2405:a00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:b00::,2405:b00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2405:c00::,2405:c00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2405:d00::,2405:d00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:e00::,2405:e00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:f00::,2405:f00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:1000::,2405:1000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:1200::,2405:1200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:1300::,2405:1300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:1400::,2405:1400:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:1500::,2405:1500:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:1600::,2405:1600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:1700::,2405:1700:ffff:ffff:ffff:ffff:ffff:ffff,BN +2405:1800::,2405:1800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:1a00::,2405:1a00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2405:1b00::,2405:1b00:ffff:ffff:ffff:ffff:ffff:ffff,NP +2405:1c00::,2405:1c00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:1d00::,2405:1d00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:1e00::,2405:1e00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:1f00::,2405:1f00:ffff:ffff:ffff:ffff:ffff:ffff,TL +2405:2000::,2405:2001:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:2200::,2405:2200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:2300::,2405:2300:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:2400::,2405:2400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:2500::,2405:2500:ffff:ffff:ffff:ffff:ffff:ffff,TH +2405:2600::,2405:2600:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:2700::,2405:2700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:2900::,2405:2900:ffff:ffff:ffff:ffff:ffff:ffff,MY +2405:2a00::,2405:2a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:2b00::,2405:2b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:2c00::,2405:2c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:2d00::,2405:2d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:2e00::,2405:2e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:2f00::,2405:2f00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:3000::,2405:3001:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:3100::,2405:3100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:3200::,2405:3200:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:3300::,2405:3300:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:3400::,2405:3400:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:3500::,2405:3500:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:3600::,2405:3600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:3700::,2405:3700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:3800::,2405:3800:ffff:ffff:ffff:ffff:ffff:ffff,MY +2405:3900::,2405:3900:ffff:ffff:ffff:ffff:ffff:ffff,KH +2405:3a00::,2405:3a00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:3b00::,2405:3b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:3c00::,2405:3c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:3d00::,2405:3d00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:3e00::,2405:3e00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:3f00::,2405:3f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:4000::,2405:4000:ffff:ffff:ffff:ffff:ffff:ffff,TH +2405:4100::,2405:4100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:4200::,2405:4200:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:4300::,2405:4300:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:4400::,2405:4400:ffff:ffff:ffff:ffff:ffff:ffff,LK +2405:4500::,2405:4500:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:4600::,2405:4600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:4700::,2405:4700:ffff:ffff:ffff:ffff:ffff:ffff,MY +2405:4800::,2405:4800:ffff:ffff:ffff:ffff:ffff:ffff,VN +2405:4900::,2405:4900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:4a00::,2405:4a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:4b00::,2405:4b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:4c00::,2405:4c00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:4d00::,2405:4d00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:4e00::,2405:4e00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:4f00::,2405:4f00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2405:5000::,2405:5000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:5100::,2405:5100:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:5200::,2405:5200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:5300::,2405:5300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:5400::,2405:5400:ffff:ffff:ffff:ffff:ffff:ffff,LK +2405:5500::,2405:5500:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:5600::,2405:5600:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:5700::,2405:5700:ffff:ffff:ffff:ffff:ffff:ffff,MN +2405:5800::,2405:5800:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:5900::,2405:5900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:5a00::,2405:5a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:5b00::,2405:5b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:5c00::,2405:5c00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:5d00::,2405:5d00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:5e00::,2405:5e00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:5f00::,2405:5f00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:6000::,2405:6000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:6100::,2405:6100:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:6200::,2405:6200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:6400::,2405:6400:ffff:ffff:ffff:ffff:ffff:ffff,MY +2405:6500::,2405:6500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:6600::,2405:6600:ffff:ffff:ffff:ffff:ffff:ffff,NP +2405:6700::,2405:6700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:6800::,2405:6800:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:6900::,2405:6900:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:6a00::,2405:6a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:6b00::,2405:6b00:ffff:ffff:ffff:ffff:ffff:ffff,LK +2405:6c00::,2405:6c00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:6d00::,2405:6d00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2405:6e00::,2405:6e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:6f00::,2405:6f00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:7000::,2405:7000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:7100::,2405:7100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:7200::,2405:7200:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:7300::,2405:7300:ffff:ffff:ffff:ffff:ffff:ffff,MN +2405:7400::,2405:7400:ffff:ffff:ffff:ffff:ffff:ffff,GU +2405:7500::,2405:7500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:7600::,2405:7600:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:7700::,2405:7700:ffff:ffff:ffff:ffff:ffff:ffff,MY +2405:7800::,2405:7800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:7900::,2405:7900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:7a00::,2405:7a00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:7b00::,2405:7b00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:7c00::,2405:7c00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2405:7d00::,2405:7d00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:7e00::,2405:7e00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:7f00::,2405:7f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:8000::,2405:8000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:8100::,2405:8100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:8200::,2405:8200:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:8300::,2405:8300:ffff:ffff:ffff:ffff:ffff:ffff,SB +2405:8400::,2405:8400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:8500::,2405:8500:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:8600::,2405:8600:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:8700::,2405:8700:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:8800::,2405:8800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:8900::,2405:8900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:8a00::,2405:8a00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:8b00::,2405:8b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:8c00::,2405:8c00:ffff:ffff:ffff:ffff:ffff:ffff,WS +2405:8d00::,2405:8d00:ffff:ffff:ffff:ffff:ffff:ffff,GU +2405:8e00::,2405:8e00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:8f00::,2405:8f00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:9000::,2405:9000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:9100::,2405:9100:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:9200::,2405:9200:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:9300::,2405:9300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:9400::,2405:9400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:9500::,2405:9500:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:9600::,2405:9600:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:9700::,2405:9700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:9800::,2405:9800:ffff:ffff:ffff:ffff:ffff:ffff,TH +2405:9900::,2405:9900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:9a00::,2405:9a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:9b00::,2405:9b00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:9c00::,2405:9c00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:9d00::,2405:9d00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:9e00::,2405:9e00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:9f00::,2405:9f00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:a000::,2405:a000:ffff:ffff:ffff:ffff:ffff:ffff,TH +2405:a100::,2405:a100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:a200::,2405:a200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:a300::,2405:a300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:a400::,2405:a400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:a500::,2405:a500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:a600::,2405:a600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:a700::,2405:a700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:a900::,2405:a900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:aa00::,2405:aa00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2405:ab00::,2405:ab00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:ac00::,2405:ac00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:ad00::,2405:ad00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:ae00::,2405:ae00:ffff:ffff:ffff:ffff:ffff:ffff,MN +2405:af00::,2405:af00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:b000::,2405:b000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:b100::,2405:b100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:b200::,2405:b200:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:b300::,2405:b300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:b400::,2405:b400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:b500::,2405:b500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:b600::,2405:b600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:b800::,2405:b800:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:b900::,2405:b900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2405:ba00::,2405:ba00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:bb00::,2405:bb00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:bc00::,2405:bc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:bd00::,2405:bd00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:be00::,2405:be00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:bf00::,2405:bf00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:c000::,2405:c000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2405:c100::,2405:c100:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:c200::,2405:c200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:c300::,2405:c300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:c400::,2405:c400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:c500::,2405:c500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:c600::,2405:c600:ffff:ffff:ffff:ffff:ffff:ffff,TW +2405:c700::,2405:c700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:c800::,2405:c800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:c900::,2405:c900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:ca00::,2405:ca00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:cb00::,2405:cb00:ffff:ffff:ffff:ffff:ffff:ffff,VN +2405:cc00::,2405:cc00:ffff:ffff:ffff:ffff:ffff:ffff,PF +2405:cd00::,2405:cd00:ffff:ffff:ffff:ffff:ffff:ffff,VN +2405:ce00::,2405:ce00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:cf00::,2405:cf00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:d000::,2405:d000:ffff:ffff:ffff:ffff:ffff:ffff,BT +2405:d100::,2405:d100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:d200::,2405:d200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:d300::,2405:d300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:d400::,2405:d400:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:d500::,2405:d500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:d600::,2405:d600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:d700::,2405:d700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:d800::,2405:d800:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:d900::,2405:d900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:da00::,2405:da00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2405:db00::,2405:db00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:dc00::,2405:dc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:e000::,2405:e000:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:e100::,2405:e100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:e200::,2405:e200:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:e300::,2405:e300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:e400::,2405:e400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:e500::,2405:e500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:e600::,2405:e600:ffff:ffff:ffff:ffff:ffff:ffff,CN +2405:e700::,2405:e700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:e800::,2405:e800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:e900::,2405:e900:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:ea00::,2405:ea00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:eb00::,2405:eb00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:ec00::,2405:ec00:ffff:ffff:ffff:ffff:ffff:ffff,BT +2405:ed00::,2405:ed00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:ee00::,2405:ee00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2405:ef00::,2405:ef00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2405:f000::,2405:f000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:f100::,2405:f100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:f200::,2405:f200:ffff:ffff:ffff:ffff:ffff:ffff,BD +2405:f300::,2405:f300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:f400::,2405:f400:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:f500::,2405:f500:ffff:ffff:ffff:ffff:ffff:ffff,KH +2405:f600::,2405:f600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:f700::,2405:f700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2405:f800::,2405:f800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2405:f900::,2405:f900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2405:fa00::,2405:fa00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2405:fb00::,2405:fb00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:fc00::,2405:fc00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2405:fe00::,2405:fe00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2405:ff00::,2405:ff00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406::,2406::ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:100::,2406:100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:200::,2406:200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:300::,2406:300:ffff:ffff:ffff:ffff:ffff:ffff,TW +2406:400::,2406:400:ffff:ffff:ffff:ffff:ffff:ffff,TH +2406:500::,2406:500:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:600::,2406:600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:700::,2406:700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:800::,2406:800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:900::,2406:900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:a00::,2406:a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:b00::,2406:b00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:c00::,2406:c00:ffff:ffff:ffff:ffff:ffff:ffff,LK +2406:d00::,2406:d00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2406:e00::,2406:e00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:f00::,2406:f00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:1000::,2406:1000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:1100::,2406:1100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:1200::,2406:1200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:1300::,2406:1300:ffff:ffff:ffff:ffff:ffff:ffff,PK +2406:1400::,2406:1400:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:1500::,2406:1500:ffff:ffff:ffff:ffff:ffff:ffff,TO +2406:1600::,2406:1600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:1700::,2406:1700:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:1900::,2406:1900:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:1a00::,2406:1a00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:1b00::,2406:1b00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:1c00::,2406:1c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:1d00::,2406:1d00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:1e00::,2406:1e00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:1f00::,2406:1f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:2000::,2406:2000:ffff:ffff:ffff:ffff:ffff:ffff,TW +2406:2100::,2406:2100:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:2200::,2406:2200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:2300::,2406:2300:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:2400::,2406:2400:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:2500::,2406:2500:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:2600::,2406:2600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:2700::,2406:2700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:2800::,2406:2800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:2900::,2406:2900:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:2a00::,2406:2a00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2406:2b00::,2406:2b00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:2c00::,2406:2c00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:2d00::,2406:2d00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:2e00::,2406:2e00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:2f00::,2406:2f00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:3000::,2406:3003:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:3100::,2406:3100:ffff:ffff:ffff:ffff:ffff:ffff,TH +2406:3200::,2406:3200:ffff:ffff:ffff:ffff:ffff:ffff,PH +2406:3300::,2406:3300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:3400::,2406:3400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:3500::,2406:3500:ffff:ffff:ffff:ffff:ffff:ffff,PG +2406:3600::,2406:3600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:3700::,2406:3700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:3800::,2406:3800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:3900::,2406:3900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:3a00::,2406:3a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:3b00::,2406:3b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:3c00::,2406:3c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:3d00::,2406:3d00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:3e00::,2406:3e00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:3f00::,2406:3f00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:4000::,2406:4000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:4100::,2406:4100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:4200::,2406:4200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:4300::,2406:4300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:4400::,2406:4400:ffff:ffff:ffff:ffff:ffff:ffff,PH +2406:4500::,2406:4500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:4600::,2406:4600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:4700::,2406:4700:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:4800::,2406:4800:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:4900::,2406:4900:ffff:ffff:ffff:ffff:ffff:ffff,MY +2406:4a00::,2406:4a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:4b00::,2406:4b00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:4c00::,2406:4c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:4d00::,2406:4d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:4e00::,2406:4e00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:4f00::,2406:4f00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:5000::,2406:5000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:5100::,2406:5100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:5200::,2406:5200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:5300::,2406:5300:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:5400::,2406:5400:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:5500::,2406:5500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:5600::,2406:5600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:5700::,2406:5700:ffff:ffff:ffff:ffff:ffff:ffff,AF +2406:5800::,2406:5800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:5900::,2406:5900:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:5a00::,2406:5a00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:5b00::,2406:5b00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2406:5c00::,2406:5c00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:5d00::,2406:5d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:5e00::,2406:5e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:5f00::,2406:5f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:6000::,2406:6000:ffff:ffff:ffff:ffff:ffff:ffff,MY +2406:6100::,2406:6100:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:6200::,2406:6200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:6300::,2406:6300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:6400::,2406:6400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:6500::,2406:6500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:6600::,2406:6600:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:6700::,2406:6700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:6800::,2406:6800:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:6900::,2406:6900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:6a00::,2406:6a00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:6b00::,2406:6b00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:6c00::,2406:6c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:6d00::,2406:6d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:6e00::,2406:6e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:6f00::,2406:6f00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:7000::,2406:7000:ffff:ffff:ffff:ffff:ffff:ffff,PK +2406:7100::,2406:7100:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:7200::,2406:7200:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:7300::,2406:7300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:7400::,2406:7400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:7500::,2406:7500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:7600::,2406:7600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:7800::,2406:7801:ffff:ffff:ffff:ffff:ffff:ffff,BN +2406:7900::,2406:7900:ffff:ffff:ffff:ffff:ffff:ffff,TH +2406:7a00::,2406:7a00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:7c00::,2406:7c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:7d00::,2406:7d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:7e00::,2406:7e00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:7f00::,2406:7f00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:8000::,2406:8000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:8100::,2406:8100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:8200::,2406:8200:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:8400::,2406:8400:ffff:ffff:ffff:ffff:ffff:ffff,PK +2406:8500::,2406:8500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:8600::,2406:8600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:8700::,2406:8700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:8800::,2406:8800:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:8900::,2406:8900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:8a00::,2406:8a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:8b00::,2406:8b00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2406:8c00::,2406:8c00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:8d00::,2406:8d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:8e00::,2406:8e00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:8f00::,2406:8f00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:9000::,2406:9000:ffff:ffff:ffff:ffff:ffff:ffff,VN +2406:9100::,2406:9100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:9200::,2406:9200:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:9300::,2406:9300:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:9400::,2406:9400:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:9500::,2406:9500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:9600::,2406:9600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:9700::,2406:9700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:9900::,2406:9900:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:9a00::,2406:9a01:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:9b00::,2406:9b00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:9c00::,2406:9c00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:9d00::,2406:9d00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:9e00::,2406:9e00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:9f00::,2406:9f00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:a000::,2406:a000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:a100::,2406:a100:ffff:ffff:ffff:ffff:ffff:ffff,AF +2406:a200::,2406:a200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:a300::,2406:a300:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:a400::,2406:a400:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:a500::,2406:a500:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:a600::,2406:a600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:a700::,2406:a700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:a800::,2406:a800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:a900::,2406:a900:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:aa00::,2406:aa00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:ab00::,2406:ab00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:ac00::,2406:ac00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2406:ad00::,2406:ad00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:ae00::,2406:ae00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:af00::,2406:af00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:b000::,2406:b000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:b100::,2406:b100:ffff:ffff:ffff:ffff:ffff:ffff,KH +2406:b200::,2406:b200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:b300::,2406:b300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:b400::,2406:b400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:b500::,2406:b500:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:b600::,2406:b600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:b700::,2406:b700:ffff:ffff:ffff:ffff:ffff:ffff,NP +2406:b800::,2406:b800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:b900::,2406:b900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:ba00::,2406:ba00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:bb00::,2406:bb07:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:bc00::,2406:bc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:bd00::,2406:bd00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:be00::,2406:be00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:bf00::,2406:bf00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:c000::,2406:c000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:c100::,2406:c100:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:c200::,2406:c200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:c300::,2406:c300:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:c400::,2406:c400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:c500::,2406:c500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:c600::,2406:c600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:c700::,2406:c700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:c800::,2406:c800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:c900::,2406:c900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:ca00::,2406:ca00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:cb00::,2406:cb00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:cc00::,2406:cc00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:cd00::,2406:cd00:ffff:ffff:ffff:ffff:ffff:ffff,KI +2406:ce00::,2406:ce07:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:cf00::,2406:cf00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:d000::,2406:d000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:d100::,2406:d100:ffff:ffff:ffff:ffff:ffff:ffff,AF +2406:d200::,2406:d200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:d300::,2406:d300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:d400::,2406:d400:ffff:ffff:ffff:ffff:ffff:ffff,TW +2406:d500::,2406:d501:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:d600::,2406:d600:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:d700::,2406:d700:ffff:ffff:ffff:ffff:ffff:ffff,KR +2406:d800::,2406:d800:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:db00::,2406:db00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:dc00::,2406:dc00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:dd00::,2406:dd00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:de00::,2406:de00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:df00::,2406:df00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:e000::,2406:e007:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:e100::,2406:e100:ffff:ffff:ffff:ffff:ffff:ffff,PH +2406:e200::,2406:e200:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:e300::,2406:e300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:e400::,2406:e400:ffff:ffff:ffff:ffff:ffff:ffff,MV +2406:e500::,2406:e500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:e600::,2406:e600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:e700::,2406:e700:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:e800::,2406:e800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:e900::,2406:e900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:ea00::,2406:ea00:ffff:ffff:ffff:ffff:ffff:ffff,MM +2406:eb00::,2406:eb00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2406:ec00::,2406:ec00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:ed00::,2406:ed00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:ee00::,2406:ee00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2406:ef00::,2406:ef00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:f000::,2406:f000:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:f100::,2406:f100:ffff:ffff:ffff:ffff:ffff:ffff,BD +2406:f200::,2406:f200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:f300::,2406:f300:ffff:ffff:ffff:ffff:ffff:ffff,CN +2406:f400::,2406:f400:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:f500::,2406:f500:ffff:ffff:ffff:ffff:ffff:ffff,PK +2406:f600::,2406:f600:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:f700::,2406:f700:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:f800::,2406:f800:ffff:ffff:ffff:ffff:ffff:ffff,FJ +2406:f900::,2406:f900:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:fa00::,2406:fa00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2406:fb00::,2406:fb00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2406:fc00::,2406:fc00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2406:fd00::,2406:fd00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2406:fe00::,2406:fe00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2406:ff00::,2406:ff00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407::,2407::ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:100::,2407:100:ffff:ffff:ffff:ffff:ffff:ffff,VN +2407:200::,2407:200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:300::,2407:300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:400::,2407:400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:500::,2407:500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:600::,2407:600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:700::,2407:700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:800::,2407:800:ffff:ffff:ffff:ffff:ffff:ffff,FJ +2407:900::,2407:900:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:a00::,2407:a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:b00::,2407:b00:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:c00::,2407:c00:ffff:ffff:ffff:ffff:ffff:ffff,LK +2407:d00::,2407:d00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:e00::,2407:e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:f00::,2407:f00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:1000::,2407:1000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:1100::,2407:1100:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:1200::,2407:1200:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:1300::,2407:1300:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:1400::,2407:1400:ffff:ffff:ffff:ffff:ffff:ffff,NP +2407:1500::,2407:1500:ffff:ffff:ffff:ffff:ffff:ffff,BD +2407:1600::,2407:1600:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:1700::,2407:1700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:1800::,2407:1800:ffff:ffff:ffff:ffff:ffff:ffff,PG +2407:1900::,2407:1900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:1b00::,2407:1b00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2407:1c00::,2407:1c00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:1d00::,2407:1d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:1e00::,2407:1e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:1f00::,2407:1f00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:2000::,2407:2000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:2100::,2407:2100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:2200::,2407:2200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:2300::,2407:2300:ffff:ffff:ffff:ffff:ffff:ffff,PG +2407:2400::,2407:2400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:2500::,2407:2500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:2600::,2407:2600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:2700::,2407:2700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:2800::,2407:2800:ffff:ffff:ffff:ffff:ffff:ffff,WS +2407:2900::,2407:2900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:2a00::,2407:2a00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:2b00::,2407:2b00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:2c00::,2407:2c00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2407:2d00::,2407:2d00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:2e00::,2407:2e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:2f00::,2407:2f00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:3000::,2407:3000:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:3100::,2407:3100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:3300::,2407:3300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:3400::,2407:3400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:3500::,2407:3500:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:3600::,2407:3600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:3700::,2407:3700:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:3800::,2407:3800:ffff:ffff:ffff:ffff:ffff:ffff,SB +2407:3900::,2407:3900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:3a00::,2407:3a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:3b00::,2407:3b00:ffff:ffff:ffff:ffff:ffff:ffff,PG +2407:3c00::,2407:3c00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:3d00::,2407:3d00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2407:3e00::,2407:3e00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:3f00::,2407:3f00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2407:4000::,2407:4000:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:4100::,2407:4100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:4200::,2407:4200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:4300::,2407:4300:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:4400::,2407:4400:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:4500::,2407:4500:ffff:ffff:ffff:ffff:ffff:ffff,PK +2407:4600::,2407:4600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:4700::,2407:4700:ffff:ffff:ffff:ffff:ffff:ffff,TW +2407:4800::,2407:4800:ffff:ffff:ffff:ffff:ffff:ffff,FM +2407:4900::,2407:4900:ffff:ffff:ffff:ffff:ffff:ffff,TW +2407:4a00::,2407:4a00:ffff:ffff:ffff:ffff:ffff:ffff,NC +2407:4b00::,2407:4b00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2407:4c00::,2407:4c00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:4d00::,2407:4d00:ffff:ffff:ffff:ffff:ffff:ffff,TW +2407:4e00::,2407:4e00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:4f00::,2407:4f00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:5000::,2407:5000:ffff:ffff:ffff:ffff:ffff:ffff,BD +2407:5100::,2407:5100:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:5200::,2407:5200:ffff:ffff:ffff:ffff:ffff:ffff,NP +2407:5300::,2407:5300:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:5400::,2407:5400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:5500::,2407:5500:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:5600::,2407:5600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:5700::,2407:5700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:5800::,2407:5800:ffff:ffff:ffff:ffff:ffff:ffff,CK +2407:5900::,2407:5900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:5a00::,2407:5a00:ffff:ffff:ffff:ffff:ffff:ffff,PH +2407:5b00::,2407:5b00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:5c00::,2407:5c00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:5d00::,2407:5d00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:5e00::,2407:5e00:ffff:ffff:ffff:ffff:ffff:ffff,KH +2407:5f00::,2407:5f00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:6000::,2407:6000:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:6100::,2407:6100:ffff:ffff:ffff:ffff:ffff:ffff,MM +2407:6200::,2407:6200:ffff:ffff:ffff:ffff:ffff:ffff,NP +2407:6300::,2407:6300:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:6400::,2407:6400:ffff:ffff:ffff:ffff:ffff:ffff,MN +2407:6500::,2407:6500:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:6600::,2407:6600:ffff:ffff:ffff:ffff:ffff:ffff,TH +2407:6700::,2407:6700:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:6800::,2407:6800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:6900::,2407:6900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:6a00::,2407:6a00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:6b00::,2407:6b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:6c00::,2407:6c00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:6d00::,2407:6d00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2407:6e00::,2407:6e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:6f00::,2407:6f00:ffff:ffff:ffff:ffff:ffff:ffff,BD +2407:7000::,2407:7000:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:7100::,2407:7100:ffff:ffff:ffff:ffff:ffff:ffff,TW +2407:7200::,2407:7200:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:7300::,2407:7300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:7400::,2407:7400:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:7500::,2407:7500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:7600::,2407:7600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:7700::,2407:7700:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:7800::,2407:7800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:7900::,2407:7900:ffff:ffff:ffff:ffff:ffff:ffff,TH +2407:7a00::,2407:7a00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2407:7b00::,2407:7b00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:7c00::,2407:7c00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:7d00::,2407:7d00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:7e00::,2407:7e00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:7f00::,2407:7f00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:8000::,2407:8000:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:8100::,2407:8100:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:8200::,2407:8200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:8300::,2407:8300:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:8400::,2407:8400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:8500::,2407:8500:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:8600::,2407:8600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:8700::,2407:8700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:8800::,2407:8800:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:8900::,2407:8900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:8a00::,2407:8a00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:8b00::,2407:8b00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:8c00::,2407:8c00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:8e00::,2407:8e00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:8f00::,2407:8f00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:9000::,2407:9000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:9100::,2407:9100:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:9300::,2407:9300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:9400::,2407:9400:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:9500::,2407:9500:ffff:ffff:ffff:ffff:ffff:ffff,NP +2407:9700::,2407:9700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:9800::,2407:9800:ffff:ffff:ffff:ffff:ffff:ffff,PH +2407:9900::,2407:9900:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:9a00::,2407:9a00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:9b00::,2407:9b00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:9c00::,2407:9c00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2407:9d00::,2407:9d00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:9e00::,2407:9e00:ffff:ffff:ffff:ffff:ffff:ffff,PK +2407:9f00::,2407:9f00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:a000::,2407:a000:ffff:ffff:ffff:ffff:ffff:ffff,FJ +2407:a100::,2407:a100:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:a200::,2407:a200:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:a300::,2407:a300:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:a500::,2407:a500:ffff:ffff:ffff:ffff:ffff:ffff,TH +2407:a600::,2407:a600:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:a700::,2407:a700:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:a800::,2407:a800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:a900::,2407:a900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:aa00::,2407:aa00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:ab00::,2407:ab00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:ac00::,2407:ac00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:ad00::,2407:ad00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:ae00::,2407:ae00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:af00::,2407:af00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:b000::,2407:b001:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:b100::,2407:b100:ffff:ffff:ffff:ffff:ffff:ffff,BD +2407:b200::,2407:b200:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:b300::,2407:b300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:b400::,2407:b400:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:b500::,2407:b500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:b600::,2407:b600:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:b700::,2407:b700:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:b800::,2407:b800:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:b900::,2407:b900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:ba00::,2407:ba00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:bb00::,2407:bb00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:bc00::,2407:bc00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:bd00::,2407:bd00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:be00::,2407:be00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:bf00::,2407:bf00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:c000::,2407:c000:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:c100::,2407:c100:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:c200::,2407:c200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:c300::,2407:c300:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:c400::,2407:c400:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:c500::,2407:c500:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:c600::,2407:c600:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:c700::,2407:c700:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:c800::,2407:c800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:c900::,2407:c900:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:ca00::,2407:ca00:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:cb00::,2407:cb00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:cc00::,2407:cc00:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:cd00::,2407:cd00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:ce00::,2407:ce00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:cf00::,2407:cf00:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:d000::,2407:d000:ffff:ffff:ffff:ffff:ffff:ffff,PK +2407:d100::,2407:d100:ffff:ffff:ffff:ffff:ffff:ffff,KR +2407:d200::,2407:d200:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:d300::,2407:d300:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:d400::,2407:d400:ffff:ffff:ffff:ffff:ffff:ffff,NP +2407:d500::,2407:d500:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:d600::,2407:d600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:d700::,2407:d700:ffff:ffff:ffff:ffff:ffff:ffff,BD +2407:d800::,2407:d800:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:d900::,2407:d900:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:da00::,2407:da00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:db00::,2407:db00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:dc00::,2407:dc00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:dd00::,2407:dd00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:de00::,2407:de00:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:df00::,2407:df00:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:e000::,2407:e000:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:e100::,2407:e100:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:e200::,2407:e200:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:e300::,2407:e300:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:e400::,2407:e400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:e500::,2407:e501:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:e600::,2407:e600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:e700::,2407:e700:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:e800::,2407:e800:ffff:ffff:ffff:ffff:ffff:ffff,CN +2407:e900::,2407:e900:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:ea00::,2407:ea00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:eb00::,2407:eb00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:ec00::,2407:ec00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:ed00::,2407:ed00:ffff:ffff:ffff:ffff:ffff:ffff,TH +2407:ee00::,2407:ee00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:ef00::,2407:ef00:ffff:ffff:ffff:ffff:ffff:ffff,SG +2407:f000::,2407:f000:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:f100::,2407:f100:ffff:ffff:ffff:ffff:ffff:ffff,NZ +2407:f200::,2407:f200:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:f300::,2407:f300:ffff:ffff:ffff:ffff:ffff:ffff,MM +2407:f400::,2407:f400:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:f500::,2407:f500:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:f600::,2407:f600:ffff:ffff:ffff:ffff:ffff:ffff,JP +2407:f700::,2407:f700:ffff:ffff:ffff:ffff:ffff:ffff,IN +2407:f800::,2407:f800:ffff:ffff:ffff:ffff:ffff:ffff,MY +2407:f900::,2407:f900:ffff:ffff:ffff:ffff:ffff:ffff,ID +2407:fa00::,2407:fa00:ffff:ffff:ffff:ffff:ffff:ffff,HK +2407:fd00::,2407:fd00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:fe00::,2407:fe00:ffff:ffff:ffff:ffff:ffff:ffff,AU +2407:ff00::,2407:ff00:ffff:ffff:ffff:ffff:ffff:ffff,IN +2408::,2408:3ff:ffff:ffff:ffff:ffff:ffff:ffff,JP +2408:8000::,2408:8fff:ffff:ffff:ffff:ffff:ffff:ffff,CN +2409:10::,2409:1f:ffff:ffff:ffff:ffff:ffff:ffff,JP +2409:250::,2409:25f:ffff:ffff:ffff:ffff:ffff:ffff,JP +2409:8000::,2409:8fff:ffff:ffff:ffff:ffff:ffff:ffff,CN +240a::,240a:7f:ffff:ffff:ffff:ffff:ffff:ffff,JP +240a:8000::,240a:87ff:ffff:ffff:ffff:ffff:ffff:ffff,CN +240b::,240b:3f:ffff:ffff:ffff:ffff:ffff:ffff,JP +240b:240::,240b:27f:ffff:ffff:ffff:ffff:ffff:ffff,JP +240b:8000::,240b:87ff:ffff:ffff:ffff:ffff:ffff:ffff,CN +240c::,240c:f:ffff:ffff:ffff:ffff:ffff:ffff,CN +240d::,240d:1f:ffff:ffff:ffff:ffff:ffff:ffff,JP +240e::,240e:fff:ffff:ffff:ffff:ffff:ffff:ffff,CN +240f::,240f:ff:ffff:ffff:ffff:ffff:ffff:ffff,KE +2600::,2600:7:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:100::,2600:10f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:200::,2600:20f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:300::,2600:400:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:800::,2600:81f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:900::,2600:90f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:a00::,2600:a01:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:b00::,2600:b0f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:c00::,2600:c14:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:d00::,2600:d0f:ffff:ffff:ffff:ffff:ffff:ffff,CA +2600:f00::,2600:fff:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:1000::,2600:1007:ffff:ffff:ffff:ffff:ffff:ffff,UY +2600:1008::,2600:1009:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2600:100a::,2600:100b:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:100c::,2600:100d:ffff:ffff:ffff:ffff:ffff:ffff,EG +2600:100e::,2600:1017:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:1100::,2600:110f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:1200::,2600:130f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:1400::,2600:141f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:1500::,2600:150f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:1600::,2600:16ff:ffff:ffff:ffff:ffff:ffff:ffff,CA +2600:1800::,2600:180f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:1c00::,2600:1c0f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:2000::,2600:200f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:2400::,2600:2407:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:2800::,2600:2803:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:2c00::,2600:2c03:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:3000::,2600:3007:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:3400::,2600:340f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:3800::,2600:380f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:3c00::,2600:3c03:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:4000::,2600:40ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:4400::,2600:4407:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:4800::,2600:480f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:4c00::,2600:4c01:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:5000::,2600:500f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:5400::,2600:541f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:5800::,2600:5801:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:5c00::,2600:5c01:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:6000::,2600:6001:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:6400::,2600:640f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:6800::,2600:68ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:6c00::,2600:6cff:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:7000::,2600:70ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:7400::,2600:740f:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:8000::,2600:80ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2600:e000::,2600:e00f:ffff:ffff:ffff:ffff:ffff:ffff,CA +2601::,2601:ff:ffff:ffff:ffff:ffff:ffff:ffff,UY +2602::,2602:10f:ffff:ffff:ffff:ffff:ffff:ffff,US +2602:200::,2602:200:ffff:ffff:ffff:ffff:ffff:ffff,CA +2602:210::,2602:210:ffff:ffff:ffff:ffff:ffff:ffff,CA +2602:220::,2602:220:ffff:ffff:ffff:ffff:ffff:ffff,CA +2602:230::,2602:230:ffff:ffff:ffff:ffff:ffff:ffff,US +2602:240::,2602:24f:ffff:ffff:ffff:ffff:ffff:ffff,US +2602:300::,2602:3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2602:ffc0::,2602:ffc0:fff:ffff:ffff:ffff:ffff:ffff,US +2602:ffd0::,2602:ffd0:fff:ffff:ffff:ffff:ffff:ffff,US +2602:ffe0::,2602:ffe0:fff:ffff:ffff:ffff:ffff:ffff,US +2602:ffeb::,2602:ffeb:fff:ffff:ffff:ffff:ffff:ffff,US +2602:ffec::,2602:ffec:fff:ffff:ffff:ffff:ffff:ffff,CA +2602:ffed::,2602:ffed:fff:ffff:ffff:ffff:ffff:ffff,US +2602:ffee::,2602:ffee:fff:ffff:ffff:ffff:ffff:ffff,US +2602:ffef::,2602:ffef:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff0::,2602:fff0:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff1::,2602:fff1:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff2::,2602:fff2:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff3::,2602:fff3:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff4::,2602:fff4:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff5::,2602:fff5:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff6::,2602:fff6:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff7::,2602:fff7:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff8::,2602:fff8:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fff9::,2602:fff9:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fffa::,2602:fffa:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fffb::,2602:fffb:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fffc::,2602:fffc:fff:ffff:ffff:ffff:ffff:ffff,US +2602:fffd::,2602:fffd:fff:ffff:ffff:ffff:ffff:ffff,CA +2602:ffff::,2602:ffff:fff:ffff:ffff:ffff:ffff:ffff,US +2604::,2604::ffff:ffff:ffff:ffff:ffff:ffff,US +2604:10::,2604:10:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:100::,2604:100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:180::,2604:180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:200::,2604:200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:280::,2604:280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:300::,2604:300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:380::,2604:380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:400::,2604:400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:480::,2604:480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:500::,2604:500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:580::,2604:580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:600::,2604:600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:680::,2604:680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:700::,2604:700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:780::,2604:780:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:800::,2604:800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:880::,2604:880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:900::,2604:900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:980::,2604:980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a00::,2604:a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a80::,2604:a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b00::,2604:b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b80::,2604:b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c00::,2604:c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c80::,2604:c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d00::,2604:d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d80::,2604:d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e00::,2604:e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e80::,2604:e80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:f00::,2604:f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f80::,2604:f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1000::,2604:1000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1080::,2604:1080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1100::,2604:1100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1180::,2604:1180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1200::,2604:1200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1280::,2604:1280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1300::,2604:1300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1380::,2604:1380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1400::,2604:1400:ffff:ffff:ffff:ffff:ffff:ffff,PR +2604:1480::,2604:1480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1500::,2604:1500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:1580::,2604:1580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1600::,2604:1600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1680::,2604:1680:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:1700::,2604:1700:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:1780::,2604:1780:ffff:ffff:ffff:ffff:ffff:ffff,KY +2604:1800::,2604:1800:ffff:ffff:ffff:ffff:ffff:ffff,GP +2604:1880::,2604:1880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1900::,2604:1900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1980::,2604:1980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1a00::,2604:1a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1a80::,2604:1a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1b00::,2604:1b00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:1b80::,2604:1b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1c00::,2604:1c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1c80::,2604:1c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1d00::,2604:1d00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:1d80::,2604:1d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1e00::,2604:1e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1e80::,2604:1e80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:1f00::,2604:1f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:1f80::,2604:1f80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:2000::,2604:20ff:ffff:ffff:ffff:ffff:ffff:ffff,GH +2604:2100::,2604:2100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2180::,2604:2180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2200::,2604:2200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2280::,2604:2280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2300::,2604:2300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2380::,2604:2380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2400::,2604:2400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2480::,2604:2480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2500::,2604:2500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2580::,2604:2580:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:2600::,2604:2600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2680::,2604:2680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2700::,2604:2700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2780::,2604:2780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2800::,2604:2800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2880::,2604:2880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2900::,2604:2900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2980::,2604:2980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2a00::,2604:2a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2a80::,2604:2a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2b00::,2604:2b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2b80::,2604:2b80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:2c00::,2604:2c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2c80::,2604:2c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2d00::,2604:2d00:fff:ffff:ffff:ffff:ffff:ffff,US +2604:2d80::,2604:2d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2e00::,2604:2e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2e80::,2604:2e80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2f00::,2604:2f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:2f80::,2604:2f80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:3000::,2604:3000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3080::,2604:3080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3100::,2604:3100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3180::,2604:3180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3200::,2604:3200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3280::,2604:3280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3300::,2604:3300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3380::,2604:3380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3400::,2604:3400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3480::,2604:3480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3500::,2604:3500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3580::,2604:3580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3600::,2604:3600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3680::,2604:3680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3700::,2604:3700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3780::,2604:3780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3800::,2604:3800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3880::,2604:3880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3900::,2604:3900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3980::,2604:3980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3a00::,2604:3a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3a80::,2604:3a80:ffff:ffff:ffff:ffff:ffff:ffff,VC +2604:3b00::,2604:3b00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:3b80::,2604:3b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3c00::,2604:3c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3c80::,2604:3c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3d00::,2604:3d00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:3d80::,2604:3d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3e00::,2604:3e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3e80::,2604:3e80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3f00::,2604:3f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:3f80::,2604:3f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4000::,2604:4000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:4080::,2604:4080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4100::,2604:4100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4180::,2604:4180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4200::,2604:4200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4280::,2604:4280:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:4300::,2604:4300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4380::,2604:4380:ffff:ffff:ffff:ffff:ffff:ffff,GD +2604:4400::,2604:4400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4480::,2604:4480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4500::,2604:4500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4580::,2604:4580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4600::,2604:4600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4680::,2604:4680:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:4700::,2604:4700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4780::,2604:4780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4800::,2604:4800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4880::,2604:4880:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:4900::,2604:4900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4980::,2604:4980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4a00::,2604:4a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4a80::,2604:4a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4b00::,2604:4b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4b80::,2604:4b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4c00::,2604:4c00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:4c80::,2604:4c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4d00::,2604:4d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4d80::,2604:4d80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:4e00::,2604:4e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:4e80::,2604:4e80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:4f00::,2604:4f00:fff:ffff:ffff:ffff:ffff:ffff,US +2604:4f80::,2604:4f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5000::,2604:5000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5080::,2604:5080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5100::,2604:5100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5180::,2604:5180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5200::,2604:5200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5280::,2604:5280:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:5300::,2604:5300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5380::,2604:5380:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:5400::,2604:5400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5480::,2604:5480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5500::,2604:5500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5580::,2604:5580:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:5600::,2604:5600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5680::,2604:5680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5700::,2604:5700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5780::,2604:5780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5800::,2604:5800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5880::,2604:5880:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:5900::,2604:5900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5980::,2604:5980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5a00::,2604:5a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5a80::,2604:5a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5b00::,2604:5b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5b80::,2604:5b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5c00::,2604:5c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5c80::,2604:5c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5d00::,2604:5d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5d80::,2604:5d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5e00::,2604:5e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5e80::,2604:5e80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5f00::,2604:5f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:5f80::,2604:5f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6000::,2604:60ff:ffff:ffff:ffff:ffff:ffff:ffff,KE +2604:6100::,2604:6100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6180::,2604:6180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6200::,2604:6200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6280::,2604:6280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6300::,2604:6300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6380::,2604:6380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6400::,2604:6400:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:6480::,2604:6480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6500::,2604:6500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:6580::,2604:6580:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:6600::,2604:6600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6680::,2604:6680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6700::,2604:6700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6780::,2604:6780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6800::,2604:6800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6880::,2604:6880:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:6900::,2604:6900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6980::,2604:6980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6a00::,2604:6a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6a80::,2604:6a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6b00::,2604:6b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6b80::,2604:6b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6c00::,2604:6c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6c80::,2604:6c80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:6d00::,2604:6d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6d80::,2604:6d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6e00::,2604:6e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6e80::,2604:6e80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6f00::,2604:6f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:6f80::,2604:6f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7000::,2604:7000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7080::,2604:7080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7100::,2604:7100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7180::,2604:7180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7200::,2604:7200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7280::,2604:7280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7300::,2604:7300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7380::,2604:7380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7400::,2604:7400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7480::,2604:7480:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:7500::,2604:7500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7580::,2604:7580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7600::,2604:7600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7680::,2604:7680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7700::,2604:7700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7780::,2604:7780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7800::,2604:7800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7880::,2604:7880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7900::,2604:7900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7980::,2604:7980:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:7a00::,2604:7a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7a80::,2604:7a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7b00::,2604:7b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7b80::,2604:7b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7c00::,2604:7c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7c80::,2604:7c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7d00::,2604:7d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7d80::,2604:7d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7e00::,2604:7e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7e80::,2604:7e80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:7f00::,2604:7f00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:7f80::,2604:7f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8000::,2604:8000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8080::,2604:8080:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:8100::,2604:8100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8180::,2604:8180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8200::,2604:8200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8280::,2604:8280:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:8300::,2604:8300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8380::,2604:8380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8400::,2604:8400:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:8480::,2604:8480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8500::,2604:8500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8580::,2604:8580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8600::,2604:8600:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:8680::,2604:8680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8700::,2604:8700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8780::,2604:8780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8800::,2604:8800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8880::,2604:8880:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:8900::,2604:8900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8980::,2604:8980:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:8a00::,2604:8a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8a80::,2604:8a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8b00::,2604:8b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8b80::,2604:8b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8c00::,2604:8c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8c80::,2604:8c80:ffff:ffff:ffff:ffff:ffff:ffff,DM +2604:8d00::,2604:8d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8d80::,2604:8d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8e00::,2604:8e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8e80::,2604:8e80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8f00::,2604:8f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:8f80::,2604:8f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9000::,2604:9000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9080::,2604:9080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9100::,2604:9100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9180::,2604:9180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9200::,2604:9200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9280::,2604:9280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9300::,2604:9300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9380::,2604:9380:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:9480::,2604:9480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9500::,2604:9500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9580::,2604:9580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9600::,2604:9600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9680::,2604:9680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9700::,2604:9700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9780::,2604:9780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9800::,2604:9800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9880::,2604:9880:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:9900::,2604:9900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9980::,2604:9980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9a00::,2604:9a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9a80::,2604:9a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9b00::,2604:9b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9b80::,2604:9b80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9c00::,2604:9c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9c80::,2604:9c80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9d00::,2604:9d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9d80::,2604:9d80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9e00::,2604:9e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9e80::,2604:9e80:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:9f00::,2604:9f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:9f80::,2604:9f80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a000::,2604:a000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a080::,2604:a080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a100::,2604:a100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a180::,2604:a180:ffff:ffff:ffff:ffff:ffff:ffff,BB +2604:a200::,2604:a200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a280::,2604:a280:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:a300::,2604:a300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a380::,2604:a380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a400::,2604:a400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a480::,2604:a480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a500::,2604:a500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a580::,2604:a580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a600::,2604:a600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a680::,2604:a680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a700::,2604:a700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a780::,2604:a780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a800::,2604:a800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a880::,2604:a880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a900::,2604:a900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:a980::,2604:a980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:aa00::,2604:aa00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:aa80::,2604:aa80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ab00::,2604:ab00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ab80::,2604:ab80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ac00::,2604:ac00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ac80::,2604:ac80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ad00::,2604:ad00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ad80::,2604:ad80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ae00::,2604:ae00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ae80::,2604:ae80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:af00::,2604:af00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:af80::,2604:af80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b000::,2604:b000:ffff:ffff:ffff:ffff:ffff:ffff,PR +2604:b080::,2604:b080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b100::,2604:b100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b180::,2604:b180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b200::,2604:b200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b280::,2604:b280:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:b300::,2604:b300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b380::,2604:b380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b400::,2604:b400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b480::,2604:b480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b500::,2604:b500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b580::,2604:b580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b600::,2604:b600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b680::,2604:b680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b700::,2604:b700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b780::,2604:b780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b800::,2604:b800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b880::,2604:b880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b900::,2604:b900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:b980::,2604:b980:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:ba00::,2604:ba00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ba80::,2604:ba80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bb00::,2604:bb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bb80::,2604:bb80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bc00::,2604:bc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bc80::,2604:bc80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bd00::,2604:bd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bd80::,2604:bd80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:be00::,2604:be00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:be80::,2604:be80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bf00::,2604:bf00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:bf80::,2604:bf80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c000::,2604:c000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c080::,2604:c080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c100::,2604:c100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c180::,2604:c180:ffff:ffff:ffff:ffff:ffff:ffff,VI +2604:c200::,2604:c200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c280::,2604:c280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c300::,2604:c300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c380::,2604:c380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c400::,2604:c400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c480::,2604:c480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c500::,2604:c500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c580::,2604:c580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c600::,2604:c600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c680::,2604:c680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c700::,2604:c700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c780::,2604:c780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c800::,2604:c800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c880::,2604:c880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c900::,2604:c900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:c980::,2604:c980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ca00::,2604:ca00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ca80::,2604:ca80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:cb00::,2604:cb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:cb80::,2604:cb80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:cc00::,2604:cc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:cc80::,2604:cc80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:cd00::,2604:cd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:cd80::,2604:cd80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ce00::,2604:ce00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ce80::,2604:ce80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:cf00::,2604:cf00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:cf80::,2604:cf80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d000::,2604:d000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d080::,2604:d080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d100::,2604:d100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d180::,2604:d180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d200::,2604:d200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d280::,2604:d280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d300::,2604:d300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d380::,2604:d380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d400::,2604:d400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d480::,2604:d480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d500::,2604:d500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d580::,2604:d580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d600::,2604:d600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d680::,2604:d680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d700::,2604:d700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d780::,2604:d780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d800::,2604:d801:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d880::,2604:d880:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:d900::,2604:d900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:d980::,2604:d980:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:da00::,2604:da00:fff:ffff:ffff:ffff:ffff:ffff,US +2604:da80::,2604:da80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:db00::,2604:db00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:db80::,2604:db80:ffff:ffff:ffff:ffff:ffff:ffff,BB +2604:dc00::,2604:dc00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:dc80::,2604:dc80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:dd00::,2604:dd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:dd80::,2604:dd80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:de00::,2604:de00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:de80::,2604:de80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:df00::,2604:df00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:df80::,2604:df80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e000::,2604:e000:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e080::,2604:e080:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e100::,2604:e100:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:e180::,2604:e180:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e200::,2604:e200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e280::,2604:e280:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e300::,2604:e300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e380::,2604:e380:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e400::,2604:e400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e480::,2604:e480:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e500::,2604:e500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e580::,2604:e580:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e600::,2604:e600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e680::,2604:e680:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e700::,2604:e700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e780::,2604:e780:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e800::,2604:e800:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e880::,2604:e880:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e900::,2604:e900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:e980::,2604:e980:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ea00::,2604:ea00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ea80::,2604:ea80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:eb00::,2604:eb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:eb80::,2604:eb80:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ec00::,2604:ec00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:ed00::,2604:ed00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ee00::,2604:ee00:fff:ffff:ffff:ffff:ffff:ffff,US +2604:ef00::,2604:ef00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:f000::,2604:f000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:f100::,2604:f100:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f200::,2604:f200:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f300::,2604:f300:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f400::,2604:f400:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f500::,2604:f500:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f600::,2604:f600:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f700::,2604:f700:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:f800::,2604:f800:ffff:ffff:ffff:ffff:ffff:ffff,CA +2604:f900::,2604:f900:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:fa00::,2604:fa00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:fb00::,2604:fb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:fc00::,2604:fc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:fd00::,2604:fd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:fe00::,2604:fe00:ffff:ffff:ffff:ffff:ffff:ffff,US +2604:ff00::,2604:ff00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605::,2605::ffff:ffff:ffff:ffff:ffff:ffff,US +2605:100::,2605:100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:200::,2605:200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:300::,2605:300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:400::,2605:400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:500::,2605:500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:600::,2605:600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:700::,2605:700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:800::,2605:800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:900::,2605:900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:a00::,2605:a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:b00::,2605:b00:fff:ffff:ffff:ffff:ffff:ffff,US +2605:c00::,2605:c00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:d00::,2605:d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e00::,2605:e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f00::,2605:f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1000::,2605:1000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:1100::,2605:1100:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:1200::,2605:1200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1300::,2605:1300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:1400::,2605:1400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1500::,2605:1500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1600::,2605:1600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1700::,2605:1700:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:1800::,2605:1800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1900::,2605:1900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1a00::,2605:1a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1b00::,2605:1b00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:1c00::,2605:1c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1d00::,2605:1d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1e00::,2605:1e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:1f00::,2605:1f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2000::,2605:2000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2100::,2605:2100:fff:ffff:ffff:ffff:ffff:ffff,CA +2605:2200::,2605:2200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2300::,2605:2300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2400::,2605:2400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2500::,2605:2500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2600::,2605:2600:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:2700::,2605:2700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2800::,2605:2800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2900::,2605:2900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:2a00::,2605:2a00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:2b00::,2605:2b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2c00::,2605:2c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2d00::,2605:2d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:2e00::,2605:2e00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:2f00::,2605:2f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3000::,2605:3000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3100::,2605:3100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3200::,2605:3200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3300::,2605:3300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3400::,2605:3400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3500::,2605:3500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3600::,2605:3600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3700::,2605:3700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3800::,2605:3800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3900::,2605:3900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3a00::,2605:3a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3b00::,2605:3b00:fff:ffff:ffff:ffff:ffff:ffff,US +2605:3c00::,2605:3c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3d00::,2605:3d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3e00::,2605:3e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:3f00::,2605:3f00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:4000::,2605:4000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4100::,2605:4100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4200::,2605:4200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4300::,2605:4300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4400::,2605:4400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4500::,2605:4500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4600::,2605:4600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4700::,2605:4700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4800::,2605:4800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4900::,2605:4900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4a00::,2605:4a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4b00::,2605:4b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4c00::,2605:4c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4d00::,2605:4d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4e00::,2605:4e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:4f00::,2605:4f00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:5000::,2605:5000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5100::,2605:5100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5200::,2605:5200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5300::,2605:5300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5400::,2605:5400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5500::,2605:5500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5600::,2605:5600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5700::,2605:5700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5800::,2605:5800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5900::,2605:5900:ffff:ffff:ffff:ffff:ffff:ffff,JM +2605:5a00::,2605:5a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5b00::,2605:5b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5c00::,2605:5c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5d00::,2605:5d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5e00::,2605:5e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:5f00::,2605:5f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6000::,2605:60ff:ffff:ffff:ffff:ffff:ffff:ffff,EG +2605:6100::,2605:6100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6200::,2605:6200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6300::,2605:6300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6400::,2605:6400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6500::,2605:6500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6600::,2605:6600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6700::,2605:6700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6800::,2605:6800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6900::,2605:6900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6a00::,2605:6a00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:6b00::,2605:6b00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:6c00::,2605:6c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6d00::,2605:6d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6e00::,2605:6e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:6f00::,2605:6f00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:7000::,2605:7000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7100::,2605:7100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7200::,2605:7200:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:7300::,2605:7300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7400::,2605:7400:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:7500::,2605:7500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7600::,2605:7600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7700::,2605:7700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7800::,2605:7801:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7900::,2605:7900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7a00::,2605:7a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7b00::,2605:7b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7c00::,2605:7c00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:7d00::,2605:7d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7e00::,2605:7e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:7f00::,2605:7f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8000::,2605:8000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8100::,2605:8100:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:8200::,2605:8200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8300::,2605:8300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8400::,2605:8400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8500::,2605:8500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8600::,2605:8600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8700::,2605:8700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8800::,2605:8800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8900::,2605:8900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8a00::,2605:8a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8b00::,2605:8b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8c00::,2605:8c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8d00::,2605:8d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8e00::,2605:8e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:8f00::,2605:8f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9000::,2605:9000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:9100::,2605:9100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9200::,2605:9200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9300::,2605:9300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:9400::,2605:9400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9500::,2605:9500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9600::,2605:9600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9700::,2605:9700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9800::,2605:9800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9900::,2605:9900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9a00::,2605:9a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9b00::,2605:9b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9c00::,2605:9c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9d00::,2605:9d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9e00::,2605:9e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:9f00::,2605:9f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:a000::,2605:a0ff:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2605:a100::,2605:a100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:a200::,2605:a200:ffff:ffff:ffff:ffff:ffff:ffff,JM +2605:a300::,2605:a300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:a400::,2605:a407:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:a500::,2605:a500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:a600::,2605:a6ff:ffff:ffff:ffff:ffff:ffff:ffff,EG +2605:a700::,2605:a700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:a800::,2605:a800:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:a900::,2605:a900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:aa00::,2605:aa00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ab00::,2605:ab00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:ac00::,2605:ac00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:ad00::,2605:ad00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ae00::,2605:ae00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:af00::,2605:af00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:b000::,2605:b000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:b100::,2605:b100:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:b200::,2605:b200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:b300::,2605:b300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:b400::,2605:b400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:b500::,2605:b500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:b600::,2605:b600:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:b700::,2605:b700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:b800::,2605:b800:ffff:ffff:ffff:ffff:ffff:ffff,PR +2605:b900::,2605:b900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:ba00::,2605:ba00:ffff:ffff:ffff:ffff:ffff:ffff,PR +2605:bb00::,2605:bb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:bc00::,2605:bc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:bd00::,2605:bd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:be00::,2605:be00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:bf00::,2605:bf00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c000::,2605:c000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c100::,2605:c100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c200::,2605:c200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c300::,2605:c300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c400::,2605:c400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c500::,2605:c500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:c600::,2605:c600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c700::,2605:c700:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:c800::,2605:c800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:c900::,2605:c900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ca00::,2605:ca00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:cb00::,2605:cb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:cc00::,2605:cc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:cd00::,2605:cd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ce00::,2605:ce00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:cf00::,2605:cf00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:d000::,2605:d000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d100::,2605:d100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d200::,2605:d200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d300::,2605:d300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d400::,2605:d400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d500::,2605:d500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:d600::,2605:d600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d700::,2605:d700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d800::,2605:d800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:d900::,2605:d900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:da00::,2605:da00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:db00::,2605:db00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:dc00::,2605:dc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:dd00::,2605:dd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:de00::,2605:de00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:df00::,2605:df00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e000::,2605:e0ff:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2605:e100::,2605:e100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e200::,2605:e200:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:e300::,2605:e300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e400::,2605:e400:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e500::,2605:e500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e600::,2605:e600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e700::,2605:e700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e800::,2605:e800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:e900::,2605:e900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ea00::,2605:ea00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:eb00::,2605:eb01:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ec00::,2605:ec00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ed00::,2605:ed00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ee00::,2605:ee00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ef00::,2605:ef00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f000::,2605:f000:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f100::,2605:f100:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f200::,2605:f200:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f300::,2605:f300:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f500::,2605:f500:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f600::,2605:f600:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f700::,2605:f700:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f800::,2605:f800:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:f900::,2605:f900:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:fa00::,2605:fa00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:fb00::,2605:fb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:fc00::,2605:fc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:fd00::,2605:fd00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2605:fe00::,2605:fe00:ffff:ffff:ffff:ffff:ffff:ffff,US +2605:ff00::,2605:ff00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606::,2606::ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:100::,2606:100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:200::,2606:200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:300::,2606:300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:400::,2606:400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:500::,2606:500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:600::,2606:600:ffff:ffff:ffff:ffff:ffff:ffff,KY +2606:700::,2606:700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:800::,2606:800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:900::,2606:900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a00::,2606:a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:b00::,2606:b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c00::,2606:c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d00::,2606:d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e00::,2606:e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f00::,2606:f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1000::,2606:1000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1100::,2606:1100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1200::,2606:1200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1300::,2606:1300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1400::,2606:1400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1500::,2606:1500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1600::,2606:1600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1700::,2606:1700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1800::,2606:1800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1900::,2606:1900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1a00::,2606:1a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1b00::,2606:1b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1c00::,2606:1c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1d00::,2606:1d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1e00::,2606:1e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:1f00::,2606:1f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2000::,2606:2000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2100::,2606:2100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2200::,2606:2200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2300::,2606:2300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2400::,2606:2400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2500::,2606:2500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2600::,2606:2600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2700::,2606:2700:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:2800::,2606:2800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2900::,2606:2900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2a00::,2606:2a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2b00::,2606:2b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2c00::,2606:2c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2d00::,2606:2d00:fff:ffff:ffff:ffff:ffff:ffff,US +2606:2e00::,2606:2e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:2f00::,2606:2f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3000::,2606:3000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:3100::,2606:3100:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:3200::,2606:3200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3300::,2606:3300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3400::,2606:3400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3500::,2606:3500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3600::,2606:3600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3700::,2606:3700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3800::,2606:3800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3900::,2606:3900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3a00::,2606:3a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3b00::,2606:3b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3c00::,2606:3c00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:3d00::,2606:3d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3e00::,2606:3e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:3f00::,2606:3f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4000::,2606:4000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4100::,2606:4100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4200::,2606:4200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4300::,2606:4300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4400::,2606:4400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4500::,2606:4500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4600::,2606:4600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4700::,2606:4700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4800::,2606:4800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4900::,2606:4900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4a00::,2606:4a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4b00::,2606:4b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4c00::,2606:4c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4d00::,2606:4d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4e00::,2606:4e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:4f00::,2606:4f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5000::,2606:5000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5100::,2606:5100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5200::,2606:5200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5300::,2606:5300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:5400::,2606:5400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5500::,2606:5500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5600::,2606:5600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5700::,2606:5700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5800::,2606:5800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5900::,2606:5900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5a00::,2606:5a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5b00::,2606:5b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5c00::,2606:5c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5d00::,2606:5d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:5e00::,2606:5e00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:5f00::,2606:5f00:ffff:ffff:ffff:ffff:ffff:ffff,PR +2606:6000::,2606:60ff:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2606:6100::,2606:6100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6200::,2606:6200:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:6300::,2606:6300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:6400::,2606:6400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6500::,2606:6500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6600::,2606:6600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6700::,2606:6700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6800::,2606:6800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6900::,2606:6900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6a00::,2606:6a00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:6b00::,2606:6b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6c00::,2606:6c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6d00::,2606:6d00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:6e00::,2606:6e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:6f00::,2606:6f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7000::,2606:7000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7100::,2606:7100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7200::,2606:7200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7300::,2606:7300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7400::,2606:7400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7500::,2606:7500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7600::,2606:7600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7700::,2606:7700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7800::,2606:7800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7900::,2606:7900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7a00::,2606:7a00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:7b00::,2606:7b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7c00::,2606:7c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7d00::,2606:7d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7e00::,2606:7e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:7f00::,2606:7f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8000::,2606:8000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8100::,2606:8100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8200::,2606:8200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8300::,2606:8300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:8400::,2606:8400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8500::,2606:8500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8600::,2606:8600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8700::,2606:8700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8800::,2606:8800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8900::,2606:8900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:8a00::,2606:8a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8b00::,2606:8b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8c00::,2606:8c00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:8d00::,2606:8d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8e00::,2606:8e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:8f00::,2606:8f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9000::,2606:9000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9100::,2606:9100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9200::,2606:9200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9300::,2606:9300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9400::,2606:9400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9500::,2606:9500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9600::,2606:9600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9700::,2606:9700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9800::,2606:9800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9900::,2606:9900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9a00::,2606:9a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9b00::,2606:9b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9c00::,2606:9c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9d00::,2606:9d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:9e00::,2606:9e00:ffff:ffff:ffff:ffff:ffff:ffff,BM +2606:9f00::,2606:9f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a000::,2606:a0ff:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2606:a100::,2606:a100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a200::,2606:a200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a300::,2606:a300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a400::,2606:a400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a500::,2606:a500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a600::,2606:a600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a700::,2606:a700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a800::,2606:a800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:a900::,2606:a900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:aa00::,2606:aa00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ab00::,2606:ab00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ac00::,2606:ac00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ad00::,2606:ad00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ae00::,2606:ae00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:af00::,2606:af00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:b000::,2606:b000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:b100::,2606:b100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:b200::,2606:b200:ffff:ffff:ffff:ffff:ffff:ffff,KY +2606:b300::,2606:b300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:b400::,2606:b400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:b500::,2606:b500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:b600::,2606:b600:fff:ffff:ffff:ffff:ffff:ffff,US +2606:b700::,2606:b700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:b800::,2606:b800:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:b900::,2606:b900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ba00::,2606:ba00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:bb00::,2606:bb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:bc00::,2606:bc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:bd00::,2606:bd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:be00::,2606:be00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:bf00::,2606:bf00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c000::,2606:c000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c100::,2606:c100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c200::,2606:c200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c300::,2606:c300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c400::,2606:c400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c500::,2606:c500:ffff:ffff:ffff:ffff:ffff:ffff,JM +2606:c600::,2606:c600:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:c700::,2606:c700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c800::,2606:c800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:c900::,2606:c900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ca00::,2606:ca00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:cb00::,2606:cb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:cc00::,2606:cc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:cd00::,2606:cd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ce00::,2606:ce00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:cf00::,2606:cf00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d000::,2606:d000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d100::,2606:d100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d200::,2606:d200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d300::,2606:d300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d400::,2606:d400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d500::,2606:d500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d600::,2606:d600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d700::,2606:d700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d800::,2606:d800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:d900::,2606:d900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:da00::,2606:da00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:db00::,2606:db00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:dc00::,2606:dc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:dd00::,2606:dd00:fff:ffff:ffff:ffff:ffff:ffff,US +2606:de00::,2606:de00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:df00::,2606:df00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e000::,2606:e000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:e100::,2606:e100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e200::,2606:e200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e300::,2606:e300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e400::,2606:e400:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e500::,2606:e500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e600::,2606:e600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e700::,2606:e700:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e800::,2606:e800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:e900::,2606:e900:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ea00::,2606:ea00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:eb00::,2606:eb00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:ec00::,2606:ec00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ed00::,2606:ed00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ee00::,2606:ee00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:ef00::,2606:ef00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f000::,2606:f000:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f100::,2606:f100:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f200::,2606:f200:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f300::,2606:f300:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f400::,2606:f40f:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f500::,2606:f500:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f600::,2606:f600:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f700::,2606:f700:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:f800::,2606:f800:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:f900::,2606:f900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:fa00::,2606:fa00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2606:fb00::,2606:fb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:fc00::,2606:fc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:fd00::,2606:fd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:fe00::,2606:fe00:ffff:ffff:ffff:ffff:ffff:ffff,US +2606:ff00::,2606:ff00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607::,2607::ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:100::,2607:100:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:200::,2607:200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:300::,2607:300:ffff:ffff:ffff:ffff:ffff:ffff,BS +2607:400::,2607:400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:500::,2607:500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:600::,2607:600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:700::,2607:700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:800::,2607:800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:900::,2607:900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a00::,2607:a00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:b00::,2607:b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c00::,2607:c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d00::,2607:d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e00::,2607:e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f00::,2607:f00:ffff:ffff:ffff:ffff:ffff:ffff,PR +2607:1000::,2607:1000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1100::,2607:1100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1200::,2607:1200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1300::,2607:1300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1400::,2607:1400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1500::,2607:1500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1600::,2607:1600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1700::,2607:1700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1800::,2607:1800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1900::,2607:1900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1a00::,2607:1a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1b00::,2607:1b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1c00::,2607:1c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1d00::,2607:1d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1e00::,2607:1e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:1f00::,2607:1f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2000::,2607:2000:ffff:ffff:ffff:ffff:ffff:ffff,PR +2607:2100::,2607:2100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2200::,2607:2200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2300::,2607:2300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2400::,2607:2400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2500::,2607:2500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:2600::,2607:2600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2700::,2607:2700:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:2800::,2607:2800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2900::,2607:2900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:2a00::,2607:2a00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:2b00::,2607:2b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2c00::,2607:2c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2d00::,2607:2d00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:2e00::,2607:2e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:2f00::,2607:2f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3000::,2607:3000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3100::,2607:3100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3200::,2607:3200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3300::,2607:3300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3400::,2607:3400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3500::,2607:3500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3600::,2607:3600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3700::,2607:3700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3800::,2607:3800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3900::,2607:3900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3a00::,2607:3a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3b00::,2607:3b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3c00::,2607:3c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3d00::,2607:3d0f:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3e00::,2607:3e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:3f00::,2607:3f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4000::,2607:4000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4100::,2607:4100:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:4200::,2607:4200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4300::,2607:4300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:4400::,2607:4400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4500::,2607:4500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4600::,2607:4600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4700::,2607:4700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4800::,2607:4800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4900::,2607:4900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4a00::,2607:4a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4b00::,2607:4b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4c00::,2607:4c00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:4d00::,2607:4d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4e00::,2607:4e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:4f00::,2607:4f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5000::,2607:5006:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5100::,2607:5100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5200::,2607:5200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5300::,2607:5300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:5400::,2607:5400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5500::,2607:5500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5600::,2607:5600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5700::,2607:5700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5800::,2607:5800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5900::,2607:5900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:5a00::,2607:5a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5b00::,2607:5b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5c00::,2607:5c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5d00::,2607:5d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:5e00::,2607:5e00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:5f00::,2607:5f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6000::,2607:6000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6100::,2607:6100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6200::,2607:6200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6300::,2607:6300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6400::,2607:6400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6500::,2607:6500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:6600::,2607:6600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6700::,2607:6700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6800::,2607:6800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6900::,2607:6900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6a00::,2607:6a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6b00::,2607:6b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6c00::,2607:6c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6d00::,2607:6d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6e00::,2607:6e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:6f00::,2607:6f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7000::,2607:7000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7100::,2607:7100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7200::,2607:7200:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:7300::,2607:7300:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:7400::,2607:7400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7500::,2607:7500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7600::,2607:7600:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:7700::,2607:7700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7800::,2607:7800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7900::,2607:7900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7a00::,2607:7a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7b00::,2607:7b00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:7c00::,2607:7c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7d00::,2607:7d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:7e00::,2607:7e00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:7f00::,2607:7f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8000::,2607:8000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8100::,2607:8100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8200::,2607:8200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8300::,2607:8300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8400::,2607:8400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8500::,2607:8500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8600::,2607:8600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8800::,2607:8800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8900::,2607:8900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8a00::,2607:8a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8b00::,2607:8b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8c00::,2607:8c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8d00::,2607:8d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8e00::,2607:8e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:8f00::,2607:8f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9000::,2607:9000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9100::,2607:9100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9200::,2607:9200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9300::,2607:9300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9400::,2607:9400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9500::,2607:9500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:9600::,2607:9600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9700::,2607:9700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9800::,2607:9800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9900::,2607:9900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:9a00::,2607:9a00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9b00::,2607:9b00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9c00::,2607:9c00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9d00::,2607:9d00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9e00::,2607:9e00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:9f00::,2607:9f00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a000::,2607:a000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:a100::,2607:a10f:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a200::,2607:a200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a300::,2607:a300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a400::,2607:a400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a500::,2607:a500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a600::,2607:a600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a700::,2607:a700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a800::,2607:a800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:a900::,2607:a900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:aa00::,2607:aa00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ab00::,2607:ab00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ac00::,2607:ac00:ffff:ffff:ffff:ffff:ffff:ffff,PR +2607:ad00::,2607:ad00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ae00::,2607:ae00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:af00::,2607:af00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b000::,2607:b000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b100::,2607:b100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b200::,2607:b200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b300::,2607:b300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b400::,2607:b400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b500::,2607:b500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b600::,2607:b600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b700::,2607:b700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b800::,2607:b800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:b900::,2607:b900:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ba00::,2607:ba00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:bb00::,2607:bb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:bc00::,2607:bc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:bd00::,2607:bd00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:be00::,2607:be00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:bf00::,2607:bf00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c000::,2607:c000:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:c100::,2607:c100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c200::,2607:c200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c300::,2607:c300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c400::,2607:c400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c500::,2607:c500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c600::,2607:c600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c700::,2607:c700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c800::,2607:c800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:c900::,2607:c900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ca00::,2607:ca00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:cb00::,2607:cb00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:cc00::,2607:cc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:cd00::,2607:cd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ce00::,2607:ce00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:cf00::,2607:cf03:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d000::,2607:d000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d100::,2607:d100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d200::,2607:d200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d300::,2607:d300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d400::,2607:d400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d500::,2607:d500:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:d600::,2607:d600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d700::,2607:d700:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:d800::,2607:d800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:d900::,2607:d900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:da00::,2607:da00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:db00::,2607:db00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:dc00::,2607:dc00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:dd00::,2607:dd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:de00::,2607:de00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:df00::,2607:df00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e000::,2607:e000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e100::,2607:e100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e200::,2607:e200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e300::,2607:e300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e400::,2607:e400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e500::,2607:e500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e600::,2607:e600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e700::,2607:e700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e800::,2607:e800:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:e900::,2607:e900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ea00::,2607:ea00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:eb00::,2607:eb00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ec00::,2607:ec00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ed00::,2607:ed00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ee00::,2607:ee00:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ef00::,2607:ef00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f000::,2607:f000:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f008::,2607:f008:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f010::,2607:f010:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f018::,2607:f018:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f020::,2607:f020:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f028::,2607:f028:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f030::,2607:f030:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f038::,2607:f038:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f040::,2607:f040:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f048::,2607:f048:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f050::,2607:f050:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f058::,2607:f058:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f060::,2607:f060:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f068::,2607:f068:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f070::,2607:f070:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f078::,2607:f078:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f080::,2607:f080:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f088::,2607:f088:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f090::,2607:f090:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f098::,2607:f098:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f0a0::,2607:f0a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f0a8::,2607:f0a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f0b0::,2607:f0b0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f0c0::,2607:f0c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f0c8::,2607:f0c8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f0d0::,2607:f0d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f0d8::,2607:f0e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f0e8::,2607:f0e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f0f8::,2607:f0f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f100::,2607:f100:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f108::,2607:f108:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f110::,2607:f110:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f118::,2607:f118:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f128::,2607:f128:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f130::,2607:f130:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f138::,2607:f138:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f140::,2607:f140:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f148::,2607:f148:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f150::,2607:f150:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f158::,2607:f158:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f160::,2607:f160:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f168::,2607:f168:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f170::,2607:f170:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f178::,2607:f178:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f180::,2607:f181:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f188::,2607:f188:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f190::,2607:f190:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f198::,2607:f198:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1a0::,2607:f1a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1a8::,2607:f1a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1b0::,2607:f1b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1b8::,2607:f1b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1c0::,2607:f1c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1c8::,2607:f1c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1d0::,2607:f1d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1d8::,2607:f1d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1e0::,2607:f1e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1e8::,2607:f1e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f1f0::,2607:f1f0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f1f8::,2607:f1f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f200::,2607:f200:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f208::,2607:f208:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f210::,2607:f212:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f218::,2607:f218:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f220::,2607:f220:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f228::,2607:f228:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f230::,2607:f230:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f238::,2607:f238:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f240::,2607:f240:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f248::,2607:f248:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f250::,2607:f250:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f258::,2607:f258:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f260::,2607:f260:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f270::,2607:f270:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f278::,2607:f278:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f280::,2607:f281:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f288::,2607:f288:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f290::,2607:f290:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f298::,2607:f298:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2a8::,2607:f2a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2b0::,2607:f2b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2c0::,2607:f2c0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f2c8::,2607:f2c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2d0::,2607:f2d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2d8::,2607:f2d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2e0::,2607:f2e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2e8::,2607:f2e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2f0::,2607:f2f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f2f8::,2607:f2f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f300::,2607:f300:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f308::,2607:f308:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f310::,2607:f310:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f318::,2607:f318:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f330::,2607:f330:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f338::,2607:f338:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f340::,2607:f340:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f348::,2607:f348:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f350::,2607:f350:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f358::,2607:f358:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f360::,2607:f360:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f368::,2607:f368:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f370::,2607:f370:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f378::,2607:f378:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f380::,2607:f380:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f388::,2607:f388:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f390::,2607:f390:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f398::,2607:f398:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3a0::,2607:f3a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3b0::,2607:f3b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3b8::,2607:f3b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3c0::,2607:f3c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3c8::,2607:f3c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3d0::,2607:f3d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3d8::,2607:f3d8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f3e0::,2607:f3e0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f3e8::,2607:f3e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3f0::,2607:f3f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f3f8::,2607:f3f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f400::,2607:f400:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f408::,2607:f408:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f410::,2607:f410:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f418::,2607:f418:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f420::,2607:f420:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f428::,2607:f428:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f430::,2607:f430:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f438::,2607:f438:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f440::,2607:f440:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f450::,2607:f450:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f458::,2607:f458:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f460::,2607:f460:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f468::,2607:f468:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f470::,2607:f470:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f478::,2607:f478:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f480::,2607:f480:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f488::,2607:f488:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f490::,2607:f490:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f498::,2607:f498:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4a0::,2607:f4a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4a8::,2607:f4a8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f4b0::,2607:f4b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4b8::,2607:f4b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4c0::,2607:f4c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4c8::,2607:f4c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4d0::,2607:f4d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4d8::,2607:f4d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4e0::,2607:f4e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4e8::,2607:f4e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4f0::,2607:f4f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f4f8::,2607:f4f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f500::,2607:f500:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f508::,2607:f508:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f510::,2607:f510:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f518::,2607:f518:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f520::,2607:f520:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f528::,2607:f528:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f530::,2607:f530:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f538::,2607:f538:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f540::,2607:f540:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f548::,2607:f548:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f550::,2607:f550:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f558::,2607:f558:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f560::,2607:f560:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f568::,2607:f568:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f570::,2607:f570:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f578::,2607:f578:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f588::,2607:f588:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f590::,2607:f590:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f598::,2607:f598:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5a0::,2607:f5a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5a8::,2607:f5a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5b0::,2607:f5b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5c0::,2607:f5c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5c8::,2607:f5c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5d0::,2607:f5d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5d8::,2607:f5d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5e0::,2607:f5e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5e8::,2607:f5e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5f0::,2607:f5f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f5f8::,2607:f5f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f600::,2607:f600:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f608::,2607:f608:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f610::,2607:f610:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f618::,2607:f618:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f620::,2607:f620:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f628::,2607:f628:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f630::,2607:f630:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f638::,2607:f638:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f640::,2607:f640:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f648::,2607:f648:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f650::,2607:f650:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f658::,2607:f658:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f660::,2607:f660:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f668::,2607:f668:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f670::,2607:f670:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f678::,2607:f678:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f680::,2607:f680:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f688::,2607:f688:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f690::,2607:f690:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f698::,2607:f699:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f6a0::,2607:f6a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6a8::,2607:f6a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6b0::,2607:f6b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6b8::,2607:f6b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6c0::,2607:f6c0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f6c8::,2607:f6c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6d0::,2607:f6d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6d8::,2607:f6d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6e0::,2607:f6e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6e8::,2607:f6e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6f0::,2607:f6f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f6f8::,2607:f6f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f700::,2607:f700:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f708::,2607:f708:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f710::,2607:f710:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f718::,2607:f718:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f720::,2607:f720:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f728::,2607:f728:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f738::,2607:f738:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f740::,2607:f740:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f748::,2607:f748:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f750::,2607:f750:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f758::,2607:f758:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f760::,2607:f760:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f768::,2607:f768:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f770::,2607:f770:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f778::,2607:f778:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f788::,2607:f788:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f790::,2607:f790:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f798::,2607:f798:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f7a0::,2607:f7a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7a8::,2607:f7a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7b0::,2607:f7b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7b8::,2607:f7b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7c0::,2607:f7c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7c8::,2607:f7c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7d0::,2607:f7d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7d8::,2607:f7d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7e0::,2607:f7e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7e8::,2607:f7e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7f0::,2607:f7f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f7f8::,2607:f7f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f800::,2607:f800:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f808::,2607:f808:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f810::,2607:f810:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f818::,2607:f818:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f820::,2607:f820:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f828::,2607:f828:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f830::,2607:f830:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f838::,2607:f838:ffff:ffff:ffff:ffff:ffff:ffff,VI +2607:f848::,2607:f848:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f850::,2607:f850:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f858::,2607:f858:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f860::,2607:f860:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f868::,2607:f868:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f870::,2607:f870:ffff:ffff:ffff:ffff:ffff:ffff,PR +2607:f878::,2607:f878:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f880::,2607:f880:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f888::,2607:f888:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f890::,2607:f890:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f898::,2607:f898:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8a0::,2607:f8a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8a8::,2607:f8a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8b0::,2607:f8b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8b8::,2607:f8b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8c0::,2607:f8c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8c8::,2607:f8c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8d0::,2607:f8d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8d8::,2607:f8d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8e0::,2607:f8e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8e8::,2607:f8e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f8f0::,2607:f8f0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f8f8::,2607:f8f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f900::,2607:f900:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f908::,2607:f908:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f910::,2607:f910:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f920::,2607:f920:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f928::,2607:f928:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f930::,2607:f930:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f938::,2607:f938:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f940::,2607:f940:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f948::,2607:f948:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f950::,2607:f950:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f958::,2607:f958:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f960::,2607:f960:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f968::,2607:f968:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f978::,2607:f978:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f980::,2607:f980:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f990::,2607:f990:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:f998::,2607:f998:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9a0::,2607:f9a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9a8::,2607:f9a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9b0::,2607:f9b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9b8::,2607:f9b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9c0::,2607:f9c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9c8::,2607:f9c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9d0::,2607:f9d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9d8::,2607:f9d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9e0::,2607:f9e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9f0::,2607:f9f1:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:f9f8::,2607:f9f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fa00::,2607:faff:ffff:ffff:ffff:ffff:ffff:ffff,TN +2607:fb00::,2607:fbff:ffff:ffff:ffff:ffff:ffff:ffff,UY +2607:fc00::,2607:fcff:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2607:fd00::,2607:fd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd08::,2607:fd08:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd10::,2607:fd10:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd18::,2607:fd18:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd28::,2607:fd28:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd30::,2607:fd30:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd38::,2607:fd38:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd40::,2607:fd40:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd48::,2607:fd48:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd50::,2607:fd50:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd60::,2607:fd60:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd68::,2607:fd68:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd70::,2607:fd70:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd78::,2607:fd78:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:fd80::,2607:fd80:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd88::,2607:fd88:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd90::,2607:fd90:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fd98::,2607:fd98:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fda0::,2607:fda0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fda8::,2607:fda8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdb0::,2607:fdb0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdb8::,2607:fdb8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdc0::,2607:fdc0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdc8::,2607:fdc8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdd0::,2607:fdd0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdd8::,2607:fdd8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fde0::,2607:fde0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fde8::,2607:fde8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdf0::,2607:fdf0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fdf8::,2607:fdf8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe00::,2607:fe00:ffff:ffff:ffff:ffff:ffff:ffff,JM +2607:fe08::,2607:fe08:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe10::,2607:fe10:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe18::,2607:fe18:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe20::,2607:fe20:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe28::,2607:fe28:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe30::,2607:fe30:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe38::,2607:fe38:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe40::,2607:fe40:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe48::,2607:fe48:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe50::,2607:fe50:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe58::,2607:fe58:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe60::,2607:fe60:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe68::,2607:fe68:ffff:ffff:ffff:ffff:ffff:ffff,BS +2607:fe70::,2607:fe70:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe78::,2607:fe78:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe80::,2607:fe80:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe88::,2607:fe88:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:fe90::,2607:fe90:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fe98::,2607:fe98:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fea0::,2607:fea0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fea8::,2607:fea8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:feb0::,2607:feb0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:feb8::,2607:feb8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fec0::,2607:fec0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fec8::,2607:fec8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:fed0::,2607:fed0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fed8::,2607:fed8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fee0::,2607:fee0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fee8::,2607:fee8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fef8::,2607:fef8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff00::,2607:ff00:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff08::,2607:ff08:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff10::,2607:ff10:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff18::,2607:ff18:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff28::,2607:ff28:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff30::,2607:ff30:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff38::,2607:ff38:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff40::,2607:ff40:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff48::,2607:ff48:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff50::,2607:ff50:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff58::,2607:ff58:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff60::,2607:ff60:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff68::,2607:ff68:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff70::,2607:ff70:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff78::,2607:ff78:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ff80::,2607:ff80:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ff90::,2607:ff90:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ffa0::,2607:ffa0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ffa8::,2607:ffa8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ffb0::,2607:ffb0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ffb8::,2607:ffb8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ffc0::,2607:ffc0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ffc8::,2607:ffc8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ffd0::,2607:ffd0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ffd8::,2607:ffd8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:ffe0::,2607:ffe0:ffff:ffff:ffff:ffff:ffff:ffff,CA +2607:ffe8::,2607:ffe8:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fff0::,2607:fff0:ffff:ffff:ffff:ffff:ffff:ffff,US +2607:fff8::,2607:fff8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2608::,2608:3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2608:4000::,2608:43ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2608:8000::,2608:83ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2608:c000::,2608:c3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2609::,2609:3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2609:4000::,2609:43ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2609:8000::,2609:83ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2609:a000::,2609:a3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2609:c000::,2609:c3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2609:e000::,2609:e3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c::,260c:3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:2000::,260c:23ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:4000::,260c:43ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:6000::,260c:63ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:8000::,260c:83ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:a000::,260c:a3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:c000::,260c:c3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:d000::,260c:d3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:e000::,260c:e3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260c:f000::,260c:f3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260f:d000::,260f:d3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +260f:f000::,260f:f3ff:ffff:ffff:ffff:ffff:ffff:ffff,US +2610::,2610::ffff:ffff:ffff:ffff:ffff:ffff,CA +2610:8::,2610:8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:10::,2610:10:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:18::,2610:18:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:20::,2610:20:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:28::,2610:28:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:30::,2610:30:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:38::,2610:38:ffff:ffff:ffff:ffff:ffff:ffff,CA +2610:40::,2610:40:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:48::,2610:48:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:50::,2610:50:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:58::,2610:58:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:60::,2610:60:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:68::,2610:68:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:78::,2610:78:ffff:ffff:ffff:ffff:ffff:ffff,CA +2610:80::,2610:88:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:98::,2610:98:ffff:ffff:ffff:ffff:ffff:ffff,CA +2610:a0::,2610:a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:b0::,2610:b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:b8::,2610:b8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:c0::,2610:c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:c8::,2610:c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:d0::,2610:d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:d8::,2610:d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:e0::,2610:e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:e8::,2610:e8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:f0::,2610:f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:f8::,2610:f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:100::,2610:100:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:108::,2610:108:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:110::,2610:110:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:120::,2610:120:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:128::,2610:128:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:130::,2610:130:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:140::,2610:140:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:148::,2610:148:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:150::,2610:150:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:158::,2610:158:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:160::,2610:160:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:168::,2610:168:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:170::,2610:170:ffff:ffff:ffff:ffff:ffff:ffff,CA +2610:178::,2610:178:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:180::,2610:180:ffff:ffff:ffff:ffff:ffff:ffff,BS +2610:188::,2610:188:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:190::,2610:190:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:198::,2610:198:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1a0::,2610:1a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1a8::,2610:1a8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1b0::,2610:1b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1c0::,2610:1c2:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1c8::,2610:1c8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1d0::,2610:1d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1d8::,2610:1d8:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1e0::,2610:1e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1e8::,2610:1e8:ffff:ffff:ffff:ffff:ffff:ffff,CA +2610:1f0::,2610:1f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2610:1f8::,2610:1f8:ffff:ffff:ffff:ffff:ffff:ffff,US +2620::,2620::ffff:ffff:ffff:ffff:ffff,US +2620:0:10::,2620::10:ffff:ffff:ffff:ffff:ffff,US +2620:0:20::,2620::20:ffff:ffff:ffff:ffff:ffff,US +2620:0:30::,2620::37:ffff:ffff:ffff:ffff:ffff,US +2620:0:40::,2620::40:ffff:ffff:ffff:ffff:ffff,US +2620:0:60::,2620::60:ffff:ffff:ffff:ffff:ffff,US +2620:0:70::,2620::70:ffff:ffff:ffff:ffff:ffff,US +2620:0:80::,2620::80:ffff:ffff:ffff:ffff:ffff,US +2620:0:90::,2620::90:ffff:ffff:ffff:ffff:ffff,US +2620:0:a0::,2620::a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:b0::,2620::b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:c0::,2620::c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:f0::,2620::f0:ffff:ffff:ffff:ffff:ffff,CA +2620:0:100::,2620::100:ffff:ffff:ffff:ffff:ffff,US +2620:0:110::,2620::110:ffff:ffff:ffff:ffff:ffff,US +2620:0:120::,2620::120:ffff:ffff:ffff:ffff:ffff,US +2620:0:140::,2620::140:ffff:ffff:ffff:ffff:ffff,US +2620:0:150::,2620::150:ffff:ffff:ffff:ffff:ffff,US +2620:0:160::,2620::160:ffff:ffff:ffff:ffff:ffff,CA +2620:0:170::,2620::170:ffff:ffff:ffff:ffff:ffff,US +2620:0:180::,2620::180:ffff:ffff:ffff:ffff:ffff,US +2620:0:190::,2620::190:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a0::,2620::1a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1b0::,2620::1b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1c0::,2620::1c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1d0::,2620::1d0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1f0::,2620::1f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:200::,2620::200:ffff:ffff:ffff:ffff:ffff,US +2620:0:210::,2620::210:ffff:ffff:ffff:ffff:ffff,US +2620:0:220::,2620::220:ffff:ffff:ffff:ffff:ffff,US +2620:0:230::,2620::230:ffff:ffff:ffff:ffff:ffff,CA +2620:0:240::,2620::240:ffff:ffff:ffff:ffff:ffff,US +2620:0:250::,2620::250:ffff:ffff:ffff:ffff:ffff,US +2620:0:260::,2620::260:ffff:ffff:ffff:ffff:ffff,US +2620:0:270::,2620::270:ffff:ffff:ffff:ffff:ffff,US +2620:0:280::,2620::280:ffff:ffff:ffff:ffff:ffff,US +2620:0:290::,2620::290:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b0::,2620::2b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2c0::,2620::2c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2d0::,2620::2d0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2f0::,2620::2f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:300::,2620::300:ffff:ffff:ffff:ffff:ffff,US +2620:0:320::,2620::320:ffff:ffff:ffff:ffff:ffff,US +2620:0:350::,2620::353:ffff:ffff:ffff:ffff:ffff,US +2620:0:360::,2620::361:ffff:ffff:ffff:ffff:ffff,US +2620:0:380::,2620::380:ffff:ffff:ffff:ffff:ffff,US +2620:0:390::,2620::390:ffff:ffff:ffff:ffff:ffff,US +2620:0:3a0::,2620::3a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:3b0::,2620::3b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:3c0::,2620::3c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:3d0::,2620::3d0:ffff:ffff:ffff:ffff:ffff,US +2620:0:3e0::,2620::3e0:ffff:ffff:ffff:ffff:ffff,US +2620:0:3f0::,2620::3f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:400::,2620::57f:ffff:ffff:ffff:ffff:ffff,US +2620:0:600::,2620::600:ffff:ffff:ffff:ffff:ffff,US +2620:0:610::,2620::610:ffff:ffff:ffff:ffff:ffff,US +2620:0:630::,2620::630:ffff:ffff:ffff:ffff:ffff,US +2620:0:640::,2620::640:ffff:ffff:ffff:ffff:ffff,US +2620:0:650::,2620::650:ffff:ffff:ffff:ffff:ffff,US +2620:0:660::,2620::660:ffff:ffff:ffff:ffff:ffff,US +2620:0:670::,2620::671:ffff:ffff:ffff:ffff:ffff,US +2620:0:680::,2620::680:ffff:ffff:ffff:ffff:ffff,US +2620:0:690::,2620::691:ffff:ffff:ffff:ffff:ffff,US +2620:0:6a0::,2620::6a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:6b0::,2620::6b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:6c0::,2620::6c7:ffff:ffff:ffff:ffff:ffff,US +2620:0:6d0::,2620::6d0:ffff:ffff:ffff:ffff:ffff,US +2620:0:6e0::,2620::6e0:ffff:ffff:ffff:ffff:ffff,US +2620:0:6f0::,2620::6f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:700::,2620::77f:ffff:ffff:ffff:ffff:ffff,US +2620:0:800::,2620::802:ffff:ffff:ffff:ffff:ffff,US +2620:0:810::,2620::810:ffff:ffff:ffff:ffff:ffff,CA +2620:0:820::,2620::820:ffff:ffff:ffff:ffff:ffff,US +2620:0:840::,2620::840:ffff:ffff:ffff:ffff:ffff,US +2620:0:850::,2620::850:ffff:ffff:ffff:ffff:ffff,US +2620:0:860::,2620::863:ffff:ffff:ffff:ffff:ffff,US +2620:0:870::,2620::877:ffff:ffff:ffff:ffff:ffff,US +2620:0:880::,2620::880:ffff:ffff:ffff:ffff:ffff,US +2620:0:890::,2620::890:ffff:ffff:ffff:ffff:ffff,US +2620:0:8a0::,2620::8a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:8d0::,2620::8d0:ffff:ffff:ffff:ffff:ffff,US +2620:0:8e0::,2620::8e0:ffff:ffff:ffff:ffff:ffff,US +2620:0:8f0::,2620::8f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:900::,2620::900:ffff:ffff:ffff:ffff:ffff,US +2620:0:910::,2620::910:ffff:ffff:ffff:ffff:ffff,US +2620:0:920::,2620::920:ffff:ffff:ffff:ffff:ffff,US +2620:0:930::,2620::930:ffff:ffff:ffff:ffff:ffff,US +2620:0:940::,2620::940:ffff:ffff:ffff:ffff:ffff,US +2620:0:950::,2620::950:ffff:ffff:ffff:ffff:ffff,US +2620:0:960::,2620::960:ffff:ffff:ffff:ffff:ffff,US +2620:0:970::,2620::970:ffff:ffff:ffff:ffff:ffff,US +2620:0:980::,2620::980:ffff:ffff:ffff:ffff:ffff,US +2620:0:990::,2620::990:ffff:ffff:ffff:ffff:ffff,US +2620:0:9a0::,2620::9a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:9b0::,2620::9b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:9c0::,2620::9c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:9e0::,2620::9e0:ffff:ffff:ffff:ffff:ffff,US +2620:0:9f0::,2620::9f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:a00::,2620::a1f:ffff:ffff:ffff:ffff:ffff,US +2620:0:b00::,2620::b00:ffff:ffff:ffff:ffff:ffff,US +2620:0:b10::,2620::b13:ffff:ffff:ffff:ffff:ffff,US +2620:0:b20::,2620::b20:ffff:ffff:ffff:ffff:ffff,US +2620:0:b30::,2620::b30:ffff:ffff:ffff:ffff:ffff,US +2620:0:b40::,2620::b40:ffff:ffff:ffff:ffff:ffff,US +2620:0:b50::,2620::b50:ffff:ffff:ffff:ffff:ffff,US +2620:0:b60::,2620::b61:ffff:ffff:ffff:ffff:ffff,US +2620:0:b80::,2620::b80:ffff:ffff:ffff:ffff:ffff,US +2620:0:b90::,2620::b90:ffff:ffff:ffff:ffff:ffff,US +2620:0:ba0::,2620::ba0:ffff:ffff:ffff:ffff:ffff,US +2620:0:bb0::,2620::bb0:ffff:ffff:ffff:ffff:ffff,US +2620:0:bd0::,2620::bd0:ffff:ffff:ffff:ffff:ffff,CA +2620:0:be0::,2620::be0:ffff:ffff:ffff:ffff:ffff,US +2620:0:bf0::,2620::bf0:ffff:ffff:ffff:ffff:ffff,US +2620:0:c10::,2620::c20:ffff:ffff:ffff:ffff:ffff,US +2620:0:c30::,2620::c30:ffff:ffff:ffff:ffff:ffff,US +2620:0:c40::,2620::c40:ffff:ffff:ffff:ffff:ffff,US +2620:0:c60::,2620::c60:ffff:ffff:ffff:ffff:ffff,US +2620:0:c70::,2620::c70:ffff:ffff:ffff:ffff:ffff,US +2620:0:c80::,2620::c80:ffff:ffff:ffff:ffff:ffff,US +2620:0:c90::,2620::ca0:ffff:ffff:ffff:ffff:ffff,US +2620:0:cb0::,2620::cb0:ffff:ffff:ffff:ffff:ffff,US +2620:0:cc0::,2620::ccf:ffff:ffff:ffff:ffff:ffff,US +2620:0:ce0::,2620::ce0:ffff:ffff:ffff:ffff:ffff,US +2620:0:cf0::,2620::cf0:ffff:ffff:ffff:ffff:ffff,US +2620:0:d00::,2620::d00:ffff:ffff:ffff:ffff:ffff,US +2620:0:d20::,2620::d20:ffff:ffff:ffff:ffff:ffff,US +2620:0:d30::,2620::d30:ffff:ffff:ffff:ffff:ffff,US +2620:0:d50::,2620::d50:ffff:ffff:ffff:ffff:ffff,US +2620:0:d60::,2620::d63:ffff:ffff:ffff:ffff:ffff,US +2620:0:d70::,2620::d77:ffff:ffff:ffff:ffff:ffff,US +2620:0:d80::,2620::d80:ffff:ffff:ffff:ffff:ffff,US +2620:0:d90::,2620::d90:ffff:ffff:ffff:ffff:ffff,US +2620:0:dc0::,2620::dc0:ffff:ffff:ffff:ffff:ffff,US +2620:0:dd0::,2620::dd0:ffff:ffff:ffff:ffff:ffff,US +2620:0:de0::,2620::de0:ffff:ffff:ffff:ffff:ffff,US +2620:0:df0::,2620::df0:ffff:ffff:ffff:ffff:ffff,US +2620:0:e00::,2620::e00:ffff:ffff:ffff:ffff:ffff,US +2620:0:e10::,2620::e10:ffff:ffff:ffff:ffff:ffff,US +2620:0:e20::,2620::e23:ffff:ffff:ffff:ffff:ffff,US +2620:0:e30::,2620::e30:ffff:ffff:ffff:ffff:ffff,US +2620:0:e50::,2620::e50:ffff:ffff:ffff:ffff:ffff,US +2620:0:e60::,2620::e60:ffff:ffff:ffff:ffff:ffff,US +2620:0:e80::,2620::e80:ffff:ffff:ffff:ffff:ffff,US +2620:0:e90::,2620::e90:ffff:ffff:ffff:ffff:ffff,US +2620:0:ea0::,2620::eb0:ffff:ffff:ffff:ffff:ffff,US +2620:0:ed0::,2620::ed0:ffff:ffff:ffff:ffff:ffff,US +2620:0:ee0::,2620::ee0:ffff:ffff:ffff:ffff:ffff,US +2620:0:ef0::,2620::ef0:ffff:ffff:ffff:ffff:ffff,US +2620:0:f00::,2620::f7f:ffff:ffff:ffff:ffff:ffff,US +2620:0:1000::,2620::10ff:ffff:ffff:ffff:ffff:ffff,US +2620:0:1400::,2620::143f:ffff:ffff:ffff:ffff:ffff,US +2620:0:1500::,2620::157f:ffff:ffff:ffff:ffff:ffff,US +2620:0:1600::,2620::167f:ffff:ffff:ffff:ffff:ffff,US +2620:0:1700::,2620::170f:ffff:ffff:ffff:ffff:ffff,US +2620:0:1800::,2620::181f:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a00::,2620::1a00:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a10::,2620::1a10:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a20::,2620::1a20:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a30::,2620::1a30:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a40::,2620::1a40:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a50::,2620::1a50:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a60::,2620::1a60:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a70::,2620::1a70:ffff:ffff:ffff:ffff:ffff,US +2620:0:1a80::,2620::1a80:ffff:ffff:ffff:ffff:ffff,US +2620:0:1aa0::,2620::1aa0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1ab0::,2620::1ab0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1ac0::,2620::1ac0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1ad0::,2620::1ad7:ffff:ffff:ffff:ffff:ffff,US +2620:0:1ae0::,2620::1ae0:ffff:ffff:ffff:ffff:ffff,US +2620:0:1af0::,2620::1af0:ffff:ffff:ffff:ffff:ffff,CA +2620:0:1b00::,2620::1b07:ffff:ffff:ffff:ffff:ffff,US +2620:0:1c00::,2620::1cff:ffff:ffff:ffff:ffff:ffff,US +2620:0:2000::,2620::203f:ffff:ffff:ffff:ffff:ffff,US +2620:0:2100::,2620::213f:ffff:ffff:ffff:ffff:ffff,US +2620:0:2210::,2620::2210:ffff:ffff:ffff:ffff:ffff,US +2620:0:2220::,2620::2220:ffff:ffff:ffff:ffff:ffff,CA +2620:0:2240::,2620::2240:ffff:ffff:ffff:ffff:ffff,US +2620:0:2250::,2620::2250:ffff:ffff:ffff:ffff:ffff,US +2620:0:2260::,2620::2260:ffff:ffff:ffff:ffff:ffff,US +2620:0:2270::,2620::2270:ffff:ffff:ffff:ffff:ffff,US +2620:0:2280::,2620::2280:ffff:ffff:ffff:ffff:ffff,US +2620:0:2290::,2620::2290:ffff:ffff:ffff:ffff:ffff,US +2620:0:22a0::,2620::22a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:22b0::,2620::22b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:22c0::,2620::22c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:22d0::,2620::22d0:ffff:ffff:ffff:ffff:ffff,US +2620:0:22e0::,2620::22e0:ffff:ffff:ffff:ffff:ffff,CA +2620:0:22f0::,2620::22f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2300::,2620::230f:ffff:ffff:ffff:ffff:ffff,US +2620:0:2400::,2620::24ff:ffff:ffff:ffff:ffff:ffff,US +2620:0:2800::,2620::2800:ffff:ffff:ffff:ffff:ffff,US +2620:0:2810::,2620::2810:ffff:ffff:ffff:ffff:ffff,US +2620:0:2820::,2620::2820:ffff:ffff:ffff:ffff:ffff,US +2620:0:2830::,2620::2830:ffff:ffff:ffff:ffff:ffff,US +2620:0:2840::,2620::2840:ffff:ffff:ffff:ffff:ffff,US +2620:0:2850::,2620::2850:ffff:ffff:ffff:ffff:ffff,US +2620:0:2860::,2620::2860:ffff:ffff:ffff:ffff:ffff,US +2620:0:2870::,2620::2870:ffff:ffff:ffff:ffff:ffff,US +2620:0:2880::,2620::2880:ffff:ffff:ffff:ffff:ffff,US +2620:0:28a0::,2620::28a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:28b0::,2620::28b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:28c0::,2620::28c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:28d0::,2620::28d0:ffff:ffff:ffff:ffff:ffff,US +2620:0:28f0::,2620::28f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2900::,2620::290f:ffff:ffff:ffff:ffff:ffff,US +2620:0:2a00::,2620::2a1f:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b00::,2620::2b00:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b10::,2620::2b10:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b20::,2620::2b20:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b30::,2620::2b40:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b50::,2620::2b50:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b60::,2620::2b60:ffff:ffff:ffff:ffff:ffff,US +2620:0:2b70::,2620::2b8f:ffff:ffff:ffff:ffff:ffff,US +2620:0:2bc0::,2620::2bc3:ffff:ffff:ffff:ffff:ffff,US +2620:0:2be0::,2620::2be0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2bf0::,2620::2bf0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2d00::,2620::2d7f:ffff:ffff:ffff:ffff:ffff,US +2620:0:2e00::,2620::2e00:ffff:ffff:ffff:ffff:ffff,US +2620:0:2e10::,2620::2e10:ffff:ffff:ffff:ffff:ffff,US +2620:0:2e30::,2620::2e30:ffff:ffff:ffff:ffff:ffff,US +2620:0:2e40::,2620::2e40:ffff:ffff:ffff:ffff:ffff,US +2620:0:2e50::,2620::2e50:ffff:ffff:ffff:ffff:ffff,US +2620:0:2e60::,2620::2e60:ffff:ffff:ffff:ffff:ffff,US +2620:0:2e70::,2620::2e80:ffff:ffff:ffff:ffff:ffff,US +2620:0:2ea0::,2620::2ea0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2eb0::,2620::2eb0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2ed0::,2620::2ed0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2ee0::,2620::2ee0:ffff:ffff:ffff:ffff:ffff,US +2620:0:2f00::,2620::2f7f:ffff:ffff:ffff:ffff:ffff,US +2620:0:3000::,2620::31ff:ffff:ffff:ffff:ffff:ffff,US +2620:0:5000::,2620::5000:ffff:ffff:ffff:ffff:ffff,US +2620:0:5010::,2620::5010:ffff:ffff:ffff:ffff:ffff,US +2620:0:5030::,2620::5030:ffff:ffff:ffff:ffff:ffff,US +2620:0:5040::,2620::5040:ffff:ffff:ffff:ffff:ffff,US +2620:0:5050::,2620::5050:ffff:ffff:ffff:ffff:ffff,US +2620:0:5060::,2620::5060:ffff:ffff:ffff:ffff:ffff,CA +2620:0:5070::,2620::5070:ffff:ffff:ffff:ffff:ffff,US +2620:0:5080::,2620::5080:ffff:ffff:ffff:ffff:ffff,US +2620:0:5090::,2620::5090:ffff:ffff:ffff:ffff:ffff,US +2620:0:50a0::,2620::50a0:ffff:ffff:ffff:ffff:ffff,US +2620:0:50b0::,2620::50b0:ffff:ffff:ffff:ffff:ffff,US +2620:0:50c0::,2620::50c0:ffff:ffff:ffff:ffff:ffff,US +2620:0:50d0::,2620::50d1:ffff:ffff:ffff:ffff:ffff,US +2620:0:50e0::,2620::50e0:ffff:ffff:ffff:ffff:ffff,US +2620:0:50f0::,2620::50f0:ffff:ffff:ffff:ffff:ffff,US +2620:0:5100::,2620::510f:ffff:ffff:ffff:ffff:ffff,US +2620:0:5200::,2620::5200:ffff:ffff:ffff:ffff:ffff,US +2620:0:5300::,2620::530f:ffff:ffff:ffff:ffff:ffff,US +2620:0:aa00::,2620::aa00:ffff:ffff:ffff:ffff:ffff,US +2620:1::,2620:1::ffff:ffff:ffff:ffff:ffff,US +2620:1:4000::,2620:1:4000:ffff:ffff:ffff:ffff:ffff,US +2620:1:8000::,2620:1:8000:ffff:ffff:ffff:ffff:ffff,US +2620:1:c000::,2620:1:c000:ffff:ffff:ffff:ffff:ffff,US +2620:2::,2620:2::ffff:ffff:ffff:ffff:ffff,US +2620:2:4000::,2620:2:4000:ffff:ffff:ffff:ffff:ffff,CA +2620:2:8000::,2620:2:8000:ffff:ffff:ffff:ffff:ffff,US +2620:2:c000::,2620:2:c000:ffff:ffff:ffff:ffff:ffff,US +2620:3::,2620:3::ffff:ffff:ffff:ffff:ffff,US +2620:3:4000::,2620:3:4000:ffff:ffff:ffff:ffff:ffff,US +2620:3:8000::,2620:3:8000:ffff:ffff:ffff:ffff:ffff,US +2620:3:c000::,2620:3:c000:ffff:ffff:ffff:ffff:ffff,US +2620:4::,2620:4::ffff:ffff:ffff:ffff:ffff,US +2620:4:4000::,2620:4:4000:ffff:ffff:ffff:ffff:ffff,US +2620:4:8000::,2620:4:8000:ffff:ffff:ffff:ffff:ffff,US +2620:4:c000::,2620:4:c000:ffff:ffff:ffff:ffff:ffff,US +2620:5::,2620:5::ffff:ffff:ffff:ffff:ffff,US +2620:5:4000::,2620:5:400f:ffff:ffff:ffff:ffff:ffff,US +2620:5:8000::,2620:5:8000:ffff:ffff:ffff:ffff:ffff,US +2620:5:c000::,2620:5:c000:ffff:ffff:ffff:ffff:ffff,US +2620:6::,2620:6::ffff:ffff:ffff:ffff:ffff,CA +2620:6:4000::,2620:6:4000:ffff:ffff:ffff:ffff:ffff,US +2620:6:8000::,2620:6:8000:ffff:ffff:ffff:ffff:ffff,US +2620:6:c000::,2620:6:c000:ffff:ffff:ffff:ffff:ffff,US +2620:7::,2620:7::ffff:ffff:ffff:ffff:ffff,US +2620:7:4000::,2620:7:4000:ffff:ffff:ffff:ffff:ffff,US +2620:7:8000::,2620:7:8000:ffff:ffff:ffff:ffff:ffff,US +2620:7:c000::,2620:7:c000:ffff:ffff:ffff:ffff:ffff,US +2620:8::,2620:8:7f:ffff:ffff:ffff:ffff:ffff,CA +2620:8:8200::,2620:8:8200:ffff:ffff:ffff:ffff:ffff,US +2620:9::,2620:9::ffff:ffff:ffff:ffff:ffff,US +2620:9:4000::,2620:9:4000:ffff:ffff:ffff:ffff:ffff,US +2620:9:8000::,2620:9:8000:ffff:ffff:ffff:ffff:ffff,US +2620:9:c000::,2620:9:c000:ffff:ffff:ffff:ffff:ffff,US +2620:a::,2620:a::ffff:ffff:ffff:ffff:ffff,CA +2620:a:4000::,2620:a:4000:ffff:ffff:ffff:ffff:ffff,US +2620:a:8000::,2620:a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a:c000::,2620:a:c000:ffff:ffff:ffff:ffff:ffff,US +2620:b::,2620:b::ffff:ffff:ffff:ffff:ffff,US +2620:b:4000::,2620:b:4000:ffff:ffff:ffff:ffff:ffff,US +2620:b:8000::,2620:b:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b:c000::,2620:b:c000:ffff:ffff:ffff:ffff:ffff,US +2620:c::,2620:c:3:ffff:ffff:ffff:ffff:ffff,US +2620:c:4000::,2620:c:4000:ffff:ffff:ffff:ffff:ffff,US +2620:c:8000::,2620:c:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c:c000::,2620:c:c000:ffff:ffff:ffff:ffff:ffff,US +2620:d::,2620:d::ffff:ffff:ffff:ffff:ffff,US +2620:d:4000::,2620:d:4000:ffff:ffff:ffff:ffff:ffff,US +2620:d:8000::,2620:d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d:c000::,2620:d:c000:ffff:ffff:ffff:ffff:ffff,US +2620:e::,2620:e::ffff:ffff:ffff:ffff:ffff,US +2620:e:4000::,2620:e:4000:ffff:ffff:ffff:ffff:ffff,US +2620:e:8000::,2620:e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e:c000::,2620:e:c000:ffff:ffff:ffff:ffff:ffff,US +2620:f::,2620:f:3:ffff:ffff:ffff:ffff:ffff,US +2620:f:4000::,2620:f:4000:ffff:ffff:ffff:ffff:ffff,US +2620:f:8000::,2620:f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f:c000::,2620:f:c000:ffff:ffff:ffff:ffff:ffff,US +2620:10::,2620:10::ffff:ffff:ffff:ffff:ffff,US +2620:10:4000::,2620:10:4000:ffff:ffff:ffff:ffff:ffff,US +2620:10:8000::,2620:10:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:10:c000::,2620:10:c000:ffff:ffff:ffff:ffff:ffff,US +2620:11::,2620:11::ffff:ffff:ffff:ffff:ffff,US +2620:11:4000::,2620:11:4000:ffff:ffff:ffff:ffff:ffff,US +2620:11:8000::,2620:11:8000:ffff:ffff:ffff:ffff:ffff,US +2620:11:c000::,2620:11:c000:ffff:ffff:ffff:ffff:ffff,US +2620:12::,2620:12::ffff:ffff:ffff:ffff:ffff,US +2620:12:4000::,2620:12:4000:ffff:ffff:ffff:ffff:ffff,US +2620:12:8000::,2620:12:8000:ffff:ffff:ffff:ffff:ffff,US +2620:12:c000::,2620:12:c000:ffff:ffff:ffff:ffff:ffff,US +2620:13::,2620:13::ffff:ffff:ffff:ffff:ffff,CA +2620:13:4000::,2620:13:4000:ffff:ffff:ffff:ffff:ffff,US +2620:13:8000::,2620:13:8000:ffff:ffff:ffff:ffff:ffff,US +2620:13:c000::,2620:13:c000:ffff:ffff:ffff:ffff:ffff,US +2620:14::,2620:14::ffff:ffff:ffff:ffff:ffff,US +2620:14:4000::,2620:14:4000:ffff:ffff:ffff:ffff:ffff,US +2620:14:8000::,2620:14:8000:ffff:ffff:ffff:ffff:ffff,US +2620:14:c000::,2620:14:c000:ffff:ffff:ffff:ffff:ffff,CA +2620:15::,2620:15::ffff:ffff:ffff:ffff:ffff,US +2620:15:4000::,2620:15:4000:ffff:ffff:ffff:ffff:ffff,US +2620:15:8000::,2620:15:8000:ffff:ffff:ffff:ffff:ffff,US +2620:15:c000::,2620:15:c000:ffff:ffff:ffff:ffff:ffff,US +2620:16::,2620:16::ffff:ffff:ffff:ffff:ffff,CA +2620:16:4000::,2620:16:4000:ffff:ffff:ffff:ffff:ffff,US +2620:16:8000::,2620:16:8000:ffff:ffff:ffff:ffff:ffff,US +2620:16:c000::,2620:16:c000:ffff:ffff:ffff:ffff:ffff,US +2620:17::,2620:17::ffff:ffff:ffff:ffff:ffff,US +2620:17:4000::,2620:17:4000:ffff:ffff:ffff:ffff:ffff,US +2620:17:8000::,2620:17:800f:ffff:ffff:ffff:ffff:ffff,US +2620:17:c000::,2620:17:c000:ffff:ffff:ffff:ffff:ffff,US +2620:18::,2620:18::ffff:ffff:ffff:ffff:ffff,US +2620:18:4000::,2620:18:4000:ffff:ffff:ffff:ffff:ffff,US +2620:18:8000::,2620:18:8000:ffff:ffff:ffff:ffff:ffff,US +2620:18:c000::,2620:18:c000:ffff:ffff:ffff:ffff:ffff,KN +2620:19::,2620:19::ffff:ffff:ffff:ffff:ffff,US +2620:19:4000::,2620:19:4000:ffff:ffff:ffff:ffff:ffff,CA +2620:19:8000::,2620:19:8000:ffff:ffff:ffff:ffff:ffff,US +2620:19:c000::,2620:19:c000:ffff:ffff:ffff:ffff:ffff,US +2620:1a::,2620:1a::ffff:ffff:ffff:ffff:ffff,US +2620:1a:4000::,2620:1a:4000:ffff:ffff:ffff:ffff:ffff,US +2620:1a:8000::,2620:1a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:1a:c000::,2620:1a:c000:ffff:ffff:ffff:ffff:ffff,US +2620:1b::,2620:1b::ffff:ffff:ffff:ffff:ffff,US +2620:1b:4000::,2620:1b:4000:ffff:ffff:ffff:ffff:ffff,US +2620:1b:8000::,2620:1b:8000:ffff:ffff:ffff:ffff:ffff,US +2620:1b:c000::,2620:1b:c000:ffff:ffff:ffff:ffff:ffff,US +2620:1c::,2620:1c::ffff:ffff:ffff:ffff:ffff,US +2620:1c:4000::,2620:1c:4000:ffff:ffff:ffff:ffff:ffff,US +2620:1c:8000::,2620:1c:8000:ffff:ffff:ffff:ffff:ffff,US +2620:1c:c000::,2620:1c:c000:ffff:ffff:ffff:ffff:ffff,US +2620:1d::,2620:1d::ffff:ffff:ffff:ffff:ffff,US +2620:1d:4000::,2620:1d:4000:ffff:ffff:ffff:ffff:ffff,US +2620:1d:8000::,2620:1d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:1d:c000::,2620:1d:c000:ffff:ffff:ffff:ffff:ffff,CA +2620:1e::,2620:1e::ffff:ffff:ffff:ffff:ffff,US +2620:1e:4000::,2620:1e:4000:ffff:ffff:ffff:ffff:ffff,US +2620:1e:8000::,2620:1e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:1e:c000::,2620:1e:c000:ffff:ffff:ffff:ffff:ffff,US +2620:1f::,2620:1f::ffff:ffff:ffff:ffff:ffff,US +2620:1f:4000::,2620:1f:4000:ffff:ffff:ffff:ffff:ffff,CA +2620:1f:8000::,2620:1f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:1f:c000::,2620:1f:c000:ffff:ffff:ffff:ffff:ffff,US +2620:20::,2620:20::ffff:ffff:ffff:ffff:ffff,US +2620:20:4000::,2620:20:4000:ffff:ffff:ffff:ffff:ffff,US +2620:20:8000::,2620:20:8000:ffff:ffff:ffff:ffff:ffff,US +2620:20:c000::,2620:20:c000:ffff:ffff:ffff:ffff:ffff,US +2620:21::,2620:21::ffff:ffff:ffff:ffff:ffff,US +2620:21:4000::,2620:21:4000:ffff:ffff:ffff:ffff:ffff,US +2620:21:8000::,2620:21:8000:ffff:ffff:ffff:ffff:ffff,US +2620:21:c000::,2620:21:c000:ffff:ffff:ffff:ffff:ffff,CA +2620:22::,2620:22::ffff:ffff:ffff:ffff:ffff,US +2620:22:4000::,2620:22:4000:ffff:ffff:ffff:ffff:ffff,CA +2620:22:8000::,2620:22:8000:ffff:ffff:ffff:ffff:ffff,US +2620:22:c000::,2620:22:c000:ffff:ffff:ffff:ffff:ffff,US +2620:23::,2620:23::ffff:ffff:ffff:ffff:ffff,US +2620:23:4000::,2620:23:4000:ffff:ffff:ffff:ffff:ffff,US +2620:23:8000::,2620:23:8000:ffff:ffff:ffff:ffff:ffff,US +2620:23:c000::,2620:23:c000:ffff:ffff:ffff:ffff:ffff,US +2620:24::,2620:24:1f:ffff:ffff:ffff:ffff:ffff,US +2620:24:8080::,2620:24:8080:ffff:ffff:ffff:ffff:ffff,US +2620:25::,2620:25::ffff:ffff:ffff:ffff:ffff,US +2620:25:4000::,2620:25:4000:ffff:ffff:ffff:ffff:ffff,US +2620:25:8000::,2620:25:8000:ffff:ffff:ffff:ffff:ffff,US +2620:25:c000::,2620:25:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:26::,2620:26::ffff:ffff:ffff:ffff:ffff,US +2620:26:4000::,2620:26:400f:ffff:ffff:ffff:ffff:ffff,US +2620:26:8000::,2620:26:8000:ffff:ffff:ffff:ffff:ffff,US +2620:26:c000::,2620:26:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:27::,2620:27:f:ffff:ffff:ffff:ffff:ffff,US +2620:27:8080::,2620:27:8080:ffff:ffff:ffff:ffff:ffff,US +2620:28::,2620:28::ffff:ffff:ffff:ffff:ffff,US +2620:28:4000::,2620:28:400f:ffff:ffff:ffff:ffff:ffff,US +2620:28:8000::,2620:28:8000:ffff:ffff:ffff:ffff:ffff,US +2620:28:c000::,2620:28:c000:ffff:ffff:ffff:ffff:ffff,US +2620:29::,2620:29::ffff:ffff:ffff:ffff:ffff,US +2620:29:4000::,2620:29:4000:ffff:ffff:ffff:ffff:ffff,US +2620:29:8000::,2620:29:8000:ffff:ffff:ffff:ffff:ffff,US +2620:29:c000::,2620:29:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:2a::,2620:2a::ffff:ffff:ffff:ffff:ffff,US +2620:2a:4000::,2620:2a:400f:ffff:ffff:ffff:ffff:ffff,US +2620:2a:8000::,2620:2a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:2a:c000::,2620:2a:c000:ffff:ffff:ffff:ffff:ffff,US +2620:2b::,2620:2b::ffff:ffff:ffff:ffff:ffff,US +2620:2b:4000::,2620:2b:400f:ffff:ffff:ffff:ffff:ffff,US +2620:2b:8000::,2620:2b:8000:ffff:ffff:ffff:ffff:ffff,US +2620:2b:c000::,2620:2b:c000:ffff:ffff:ffff:ffff:ffff,US +2620:2c::,2620:2c:f:ffff:ffff:ffff:ffff:ffff,US +2620:2c:8080::,2620:2c:8080:ffff:ffff:ffff:ffff:ffff,US +2620:2d::,2620:2d::ffff:ffff:ffff:ffff:ffff,US +2620:2d:4000::,2620:2d:400f:ffff:ffff:ffff:ffff:ffff,US +2620:2d:8000::,2620:2d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:2d:c000::,2620:2d:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:2e::,2620:2e:3f:ffff:ffff:ffff:ffff:ffff,US +2620:2e:8080::,2620:2e:8080:ffff:ffff:ffff:ffff:ffff,US +2620:2f::,2620:2f::ffff:ffff:ffff:ffff:ffff,CA +2620:2f:4000::,2620:2f:4000:ffff:ffff:ffff:ffff:ffff,US +2620:2f:8000::,2620:2f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:2f:c000::,2620:2f:c000:ffff:ffff:ffff:ffff:ffff,US +2620:30::,2620:30::ffff:ffff:ffff:ffff:ffff,US +2620:30:4000::,2620:30:4000:ffff:ffff:ffff:ffff:ffff,US +2620:30:8000::,2620:30:8000:ffff:ffff:ffff:ffff:ffff,US +2620:30:c000::,2620:30:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:31::,2620:31::ffff:ffff:ffff:ffff:ffff,US +2620:31:4000::,2620:31:4000:ffff:ffff:ffff:ffff:ffff,US +2620:31:8000::,2620:31:8000:ffff:ffff:ffff:ffff:ffff,US +2620:31:c000::,2620:31:c000:ffff:ffff:ffff:ffff:ffff,US +2620:32::,2620:32::ffff:ffff:ffff:ffff:ffff,US +2620:32:4000::,2620:32:4000:ffff:ffff:ffff:ffff:ffff,CA +2620:32:8000::,2620:32:8000:ffff:ffff:ffff:ffff:ffff,US +2620:32:c000::,2620:32:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:33::,2620:33::ffff:ffff:ffff:ffff:ffff,US +2620:33:4000::,2620:33:400f:ffff:ffff:ffff:ffff:ffff,US +2620:33:8000::,2620:33:8000:ffff:ffff:ffff:ffff:ffff,US +2620:33:c000::,2620:33:c000:ffff:ffff:ffff:ffff:ffff,US +2620:34::,2620:34::ffff:ffff:ffff:ffff:ffff,US +2620:34:4000::,2620:34:4000:ffff:ffff:ffff:ffff:ffff,US +2620:34:8000::,2620:34:8000:ffff:ffff:ffff:ffff:ffff,US +2620:34:c000::,2620:34:c000:ffff:ffff:ffff:ffff:ffff,US +2620:35::,2620:35::ffff:ffff:ffff:ffff:ffff,US +2620:35:4000::,2620:35:400f:ffff:ffff:ffff:ffff:ffff,CA +2620:35:8000::,2620:35:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:35:c000::,2620:35:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:36::,2620:36::ffff:ffff:ffff:ffff:ffff,US +2620:36:4000::,2620:36:400f:ffff:ffff:ffff:ffff:ffff,CA +2620:36:8000::,2620:36:8000:ffff:ffff:ffff:ffff:ffff,US +2620:36:c000::,2620:36:c000:ffff:ffff:ffff:ffff:ffff,CA +2620:37::,2620:37::ffff:ffff:ffff:ffff:ffff,US +2620:37:4000::,2620:37:400f:ffff:ffff:ffff:ffff:ffff,US +2620:37:8000::,2620:37:8000:ffff:ffff:ffff:ffff:ffff,US +2620:37:c000::,2620:37:c000:ffff:ffff:ffff:ffff:ffff,US +2620:38::,2620:38::ffff:ffff:ffff:ffff:ffff,US +2620:38:4000::,2620:38:400f:ffff:ffff:ffff:ffff:ffff,US +2620:38:8000::,2620:38:8000:ffff:ffff:ffff:ffff:ffff,US +2620:38:c000::,2620:38:c000:ffff:ffff:ffff:ffff:ffff,US +2620:39::,2620:39::ffff:ffff:ffff:ffff:ffff,US +2620:39:4000::,2620:39:4000:ffff:ffff:ffff:ffff:ffff,US +2620:39:8000::,2620:39:8000:ffff:ffff:ffff:ffff:ffff,US +2620:39:c000::,2620:39:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:3a::,2620:3a::ffff:ffff:ffff:ffff:ffff,US +2620:3a:4000::,2620:3a:400f:ffff:ffff:ffff:ffff:ffff,US +2620:3a:8000::,2620:3a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:3a:c000::,2620:3a:c000:ffff:ffff:ffff:ffff:ffff,US +2620:3b::,2620:3b::ffff:ffff:ffff:ffff:ffff,US +2620:3b:4000::,2620:3b:4000:ffff:ffff:ffff:ffff:ffff,US +2620:3b:8000::,2620:3b:8000:ffff:ffff:ffff:ffff:ffff,US +2620:3b:c000::,2620:3b:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:3c::,2620:3c:3f:ffff:ffff:ffff:ffff:ffff,US +2620:3c:8080::,2620:3c:8080:ffff:ffff:ffff:ffff:ffff,US +2620:3d::,2620:3d::ffff:ffff:ffff:ffff:ffff,US +2620:3d:4000::,2620:3d:4000:ffff:ffff:ffff:ffff:ffff,US +2620:3d:8000::,2620:3d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:3e::,2620:3e::ffff:ffff:ffff:ffff:ffff,US +2620:3e:8000::,2620:3e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:3f::,2620:3f::ffff:ffff:ffff:ffff:ffff,US +2620:3f:8000::,2620:3f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:40::,2620:40::ffff:ffff:ffff:ffff:ffff,US +2620:40:8000::,2620:40:8000:ffff:ffff:ffff:ffff:ffff,US +2620:41::,2620:41::ffff:ffff:ffff:ffff:ffff,US +2620:41:8000::,2620:41:8000:ffff:ffff:ffff:ffff:ffff,US +2620:42::,2620:42::ffff:ffff:ffff:ffff:ffff,US +2620:42:8000::,2620:42:8000:ffff:ffff:ffff:ffff:ffff,US +2620:43::,2620:43::ffff:ffff:ffff:ffff:ffff,US +2620:43:8000::,2620:43:8000:ffff:ffff:ffff:ffff:ffff,US +2620:44::,2620:44:1:ffff:ffff:ffff:ffff:ffff,US +2620:44:8000::,2620:44:8000:ffff:ffff:ffff:ffff:ffff,US +2620:45::,2620:45::ffff:ffff:ffff:ffff:ffff,CA +2620:45:8000::,2620:45:8000:ffff:ffff:ffff:ffff:ffff,US +2620:46::,2620:46::ffff:ffff:ffff:ffff:ffff,US +2620:46:8000::,2620:46:8000:ffff:ffff:ffff:ffff:ffff,US +2620:47::,2620:47::ffff:ffff:ffff:ffff:ffff,US +2620:47:8000::,2620:47:8000:ffff:ffff:ffff:ffff:ffff,US +2620:48::,2620:48::ffff:ffff:ffff:ffff:ffff,US +2620:48:8000::,2620:48:8000:ffff:ffff:ffff:ffff:ffff,US +2620:49::,2620:49:f:ffff:ffff:ffff:ffff:ffff,CA +2620:49:8080::,2620:49:8080:ffff:ffff:ffff:ffff:ffff,US +2620:4a::,2620:4a::ffff:ffff:ffff:ffff:ffff,US +2620:4a:8000::,2620:4a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:4b::,2620:4b::ffff:ffff:ffff:ffff:ffff,US +2620:4b:8000::,2620:4b:800f:ffff:ffff:ffff:ffff:ffff,US +2620:4c::,2620:4c:1:ffff:ffff:ffff:ffff:ffff,US +2620:4c:8000::,2620:4c:8000:ffff:ffff:ffff:ffff:ffff,US +2620:4d::,2620:4d::ffff:ffff:ffff:ffff:ffff,US +2620:4d:8000::,2620:4d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:4e::,2620:4e::ffff:ffff:ffff:ffff:ffff,US +2620:4e:8000::,2620:4e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:4f::,2620:4f::ffff:ffff:ffff:ffff:ffff,US +2620:4f:8000::,2620:4f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:50::,2620:50:f:ffff:ffff:ffff:ffff:ffff,US +2620:50:8080::,2620:50:8080:ffff:ffff:ffff:ffff:ffff,US +2620:51::,2620:51::ffff:ffff:ffff:ffff:ffff,US +2620:51:8000::,2620:51:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:52::,2620:52:3:ffff:ffff:ffff:ffff:ffff,US +2620:52:8000::,2620:52:8000:ffff:ffff:ffff:ffff:ffff,US +2620:53::,2620:53::ffff:ffff:ffff:ffff:ffff,US +2620:53:8000::,2620:53:8000:ffff:ffff:ffff:ffff:ffff,US +2620:54::,2620:54::ffff:ffff:ffff:ffff:ffff,US +2620:54:8000::,2620:54:8000:ffff:ffff:ffff:ffff:ffff,US +2620:55::,2620:55::ffff:ffff:ffff:ffff:ffff,US +2620:55:8000::,2620:55:8000:ffff:ffff:ffff:ffff:ffff,US +2620:56::,2620:56::ffff:ffff:ffff:ffff:ffff,US +2620:56:8000::,2620:56:8000:ffff:ffff:ffff:ffff:ffff,US +2620:57::,2620:57::ffff:ffff:ffff:ffff:ffff,US +2620:57:8000::,2620:57:8000:ffff:ffff:ffff:ffff:ffff,US +2620:58::,2620:58:ff:ffff:ffff:ffff:ffff:ffff,US +2620:58:8800::,2620:58:8800:ffff:ffff:ffff:ffff:ffff,US +2620:59::,2620:59::ffff:ffff:ffff:ffff:ffff,US +2620:59:8000::,2620:59:8000:ffff:ffff:ffff:ffff:ffff,US +2620:5a::,2620:5a::ffff:ffff:ffff:ffff:ffff,US +2620:5a:8000::,2620:5a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:5b::,2620:5b::ffff:ffff:ffff:ffff:ffff,US +2620:5b:8000::,2620:5b:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:5c::,2620:5c::ffff:ffff:ffff:ffff:ffff,US +2620:5c:8000::,2620:5c:8000:ffff:ffff:ffff:ffff:ffff,US +2620:5d::,2620:5d::ffff:ffff:ffff:ffff:ffff,US +2620:5d:8000::,2620:5d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:5e::,2620:5e::ffff:ffff:ffff:ffff:ffff,US +2620:5e:8000::,2620:5e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:5f::,2620:5f::ffff:ffff:ffff:ffff:ffff,US +2620:5f:8000::,2620:5f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:60::,2620:60::ffff:ffff:ffff:ffff:ffff,US +2620:60:8000::,2620:60:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:61::,2620:61::ffff:ffff:ffff:ffff:ffff,CA +2620:61:8000::,2620:61:8000:ffff:ffff:ffff:ffff:ffff,US +2620:62::,2620:62::ffff:ffff:ffff:ffff:ffff,US +2620:62:8000::,2620:62:8000:ffff:ffff:ffff:ffff:ffff,US +2620:63::,2620:63::ffff:ffff:ffff:ffff:ffff,US +2620:63:8000::,2620:63:8000:ffff:ffff:ffff:ffff:ffff,US +2620:64::,2620:64::ffff:ffff:ffff:ffff:ffff,US +2620:64:8000::,2620:64:8000:ffff:ffff:ffff:ffff:ffff,TW +2620:65::,2620:65::ffff:ffff:ffff:ffff:ffff,US +2620:65:8000::,2620:65:8000:ffff:ffff:ffff:ffff:ffff,US +2620:66::,2620:66::ffff:ffff:ffff:ffff:ffff,CA +2620:66:8000::,2620:66:8000:ffff:ffff:ffff:ffff:ffff,US +2620:67::,2620:67::ffff:ffff:ffff:ffff:ffff,US +2620:67:8000::,2620:67:8000:ffff:ffff:ffff:ffff:ffff,US +2620:68::,2620:68::ffff:ffff:ffff:ffff:ffff,US +2620:68:8000::,2620:68:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:69::,2620:69::ffff:ffff:ffff:ffff:ffff,US +2620:69:8000::,2620:69:8000:ffff:ffff:ffff:ffff:ffff,US +2620:6a::,2620:6a::ffff:ffff:ffff:ffff:ffff,US +2620:6a:8000::,2620:6a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:6b::,2620:6b::ffff:ffff:ffff:ffff:ffff,US +2620:6b:8000::,2620:6b:8000:ffff:ffff:ffff:ffff:ffff,US +2620:6c::,2620:6c:3f:ffff:ffff:ffff:ffff:ffff,US +2620:6c:8080::,2620:6c:8080:ffff:ffff:ffff:ffff:ffff,US +2620:6d:40::,2620:6d:40:ffff:ffff:ffff:ffff:ffff,US +2620:6d:8000::,2620:6d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:6e::,2620:6e::ffff:ffff:ffff:ffff:ffff,US +2620:6e:8000::,2620:6e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:6f::,2620:6f::ffff:ffff:ffff:ffff:ffff,US +2620:6f:8000::,2620:6f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:70::,2620:70::ffff:ffff:ffff:ffff:ffff,US +2620:70:8000::,2620:70:8000:ffff:ffff:ffff:ffff:ffff,US +2620:71::,2620:71::ffff:ffff:ffff:ffff:ffff,US +2620:71:8000::,2620:71:8000:ffff:ffff:ffff:ffff:ffff,US +2620:72::,2620:72::ffff:ffff:ffff:ffff:ffff,US +2620:72:8000::,2620:72:8000:ffff:ffff:ffff:ffff:ffff,US +2620:73::,2620:73::ffff:ffff:ffff:ffff:ffff,US +2620:73:8000::,2620:73:8000:ffff:ffff:ffff:ffff:ffff,US +2620:74::,2620:74:1f:ffff:ffff:ffff:ffff:ffff,US +2620:74:8080::,2620:74:8080:ffff:ffff:ffff:ffff:ffff,US +2620:75::,2620:75::ffff:ffff:ffff:ffff:ffff,US +2620:75:8000::,2620:75:8000:ffff:ffff:ffff:ffff:ffff,US +2620:76::,2620:76::ffff:ffff:ffff:ffff:ffff,US +2620:76:8000::,2620:76:8000:ffff:ffff:ffff:ffff:ffff,US +2620:77::,2620:77::ffff:ffff:ffff:ffff:ffff,US +2620:77:8000::,2620:77:8000:ffff:ffff:ffff:ffff:ffff,US +2620:78::,2620:78::ffff:ffff:ffff:ffff:ffff,US +2620:78:8000::,2620:78:8000:ffff:ffff:ffff:ffff:ffff,US +2620:79::,2620:79::ffff:ffff:ffff:ffff:ffff,US +2620:79:8000::,2620:79:8000:ffff:ffff:ffff:ffff:ffff,US +2620:7a::,2620:7a::ffff:ffff:ffff:ffff:ffff,US +2620:7a:8000::,2620:7a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:7b::,2620:7b::ffff:ffff:ffff:ffff:ffff,US +2620:7b:8000::,2620:7b:8000:ffff:ffff:ffff:ffff:ffff,US +2620:7b:e000::,2620:7b:e000:ffff:ffff:ffff:ffff:ffff,US +2620:7c:4000::,2620:7c:4000:ffff:ffff:ffff:ffff:ffff,US +2620:7c:a000::,2620:7c:a000:ffff:ffff:ffff:ffff:ffff,US +2620:7d::,2620:7d::ffff:ffff:ffff:ffff:ffff,US +2620:7d:8000::,2620:7d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:7e::,2620:7e:f:ffff:ffff:ffff:ffff:ffff,US +2620:7e:60c0::,2620:7e:60c0:ffff:ffff:ffff:ffff:ffff,US +2620:7e:c080::,2620:7e:c080:ffff:ffff:ffff:ffff:ffff,US +2620:7f:2040::,2620:7f:2040:ffff:ffff:ffff:ffff:ffff,US +2620:7f:8000::,2620:7f:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:80::,2620:80::ffff:ffff:ffff:ffff:ffff,US +2620:80:8000::,2620:80:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:81::,2620:81::ffff:ffff:ffff:ffff:ffff,US +2620:81:8000::,2620:81:8000:ffff:ffff:ffff:ffff:ffff,US +2620:82::,2620:82::ffff:ffff:ffff:ffff:ffff,US +2620:82:8000::,2620:82:8000:ffff:ffff:ffff:ffff:ffff,US +2620:83::,2620:83::ffff:ffff:ffff:ffff:ffff,US +2620:83:8000::,2620:83:8000:ffff:ffff:ffff:ffff:ffff,US +2620:84::,2620:84:1:ffff:ffff:ffff:ffff:ffff,US +2620:84:8000::,2620:84:8000:ffff:ffff:ffff:ffff:ffff,US +2620:85::,2620:85::ffff:ffff:ffff:ffff:ffff,US +2620:85:8000::,2620:85:8000:ffff:ffff:ffff:ffff:ffff,US +2620:86::,2620:86::ffff:ffff:ffff:ffff:ffff,US +2620:86:8000::,2620:86:8000:ffff:ffff:ffff:ffff:ffff,US +2620:87::,2620:87::ffff:ffff:ffff:ffff:ffff,US +2620:87:8000::,2620:87:8000:ffff:ffff:ffff:ffff:ffff,US +2620:88::,2620:88::ffff:ffff:ffff:ffff:ffff,US +2620:88:8000::,2620:88:8000:ffff:ffff:ffff:ffff:ffff,US +2620:89::,2620:89::ffff:ffff:ffff:ffff:ffff,US +2620:89:8000::,2620:89:8000:ffff:ffff:ffff:ffff:ffff,US +2620:8a::,2620:8a::ffff:ffff:ffff:ffff:ffff,US +2620:8a:8000::,2620:8a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:8b::,2620:8b::ffff:ffff:ffff:ffff:ffff,US +2620:8b:8000::,2620:8b:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:8c::,2620:8c::ffff:ffff:ffff:ffff:ffff,US +2620:8c:8000::,2620:8c:8000:ffff:ffff:ffff:ffff:ffff,US +2620:8d::,2620:8d::ffff:ffff:ffff:ffff:ffff,US +2620:8d:8000::,2620:8d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:8e::,2620:8e::ffff:ffff:ffff:ffff:ffff,US +2620:8e:8000::,2620:8e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:8f::,2620:8f::ffff:ffff:ffff:ffff:ffff,US +2620:8f:8000::,2620:8f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:90::,2620:90::ffff:ffff:ffff:ffff:ffff,CA +2620:90:8000::,2620:90:8000:ffff:ffff:ffff:ffff:ffff,US +2620:91::,2620:91::ffff:ffff:ffff:ffff:ffff,US +2620:91:8000::,2620:91:8000:ffff:ffff:ffff:ffff:ffff,US +2620:92::,2620:92:f:ffff:ffff:ffff:ffff:ffff,US +2620:92:8000::,2620:92:8000:ffff:ffff:ffff:ffff:ffff,US +2620:93::,2620:93::ffff:ffff:ffff:ffff:ffff,US +2620:93:8000::,2620:93:8000:ffff:ffff:ffff:ffff:ffff,US +2620:94::,2620:94::ffff:ffff:ffff:ffff:ffff,US +2620:94:8000::,2620:94:8000:ffff:ffff:ffff:ffff:ffff,US +2620:95::,2620:95::ffff:ffff:ffff:ffff:ffff,US +2620:95:8000::,2620:95:8000:ffff:ffff:ffff:ffff:ffff,US +2620:96::,2620:96::ffff:ffff:ffff:ffff:ffff,US +2620:96:8000::,2620:96:8000:ffff:ffff:ffff:ffff:ffff,US +2620:97::,2620:97::ffff:ffff:ffff:ffff:ffff,US +2620:97:8000::,2620:97:8000:ffff:ffff:ffff:ffff:ffff,US +2620:98::,2620:98::ffff:ffff:ffff:ffff:ffff,US +2620:98:8000::,2620:98:8000:ffff:ffff:ffff:ffff:ffff,US +2620:99::,2620:99::ffff:ffff:ffff:ffff:ffff,US +2620:99:8000::,2620:99:8000:ffff:ffff:ffff:ffff:ffff,US +2620:9a::,2620:9a::ffff:ffff:ffff:ffff:ffff,CA +2620:9a:8000::,2620:9a:8000:ffff:ffff:ffff:ffff:ffff,US +2620:9b::,2620:9b::ffff:ffff:ffff:ffff:ffff,US +2620:9b:8000::,2620:9b:8000:ffff:ffff:ffff:ffff:ffff,US +2620:9c::,2620:9c::ffff:ffff:ffff:ffff:ffff,US +2620:9c:8000::,2620:9c:8000:ffff:ffff:ffff:ffff:ffff,US +2620:9d::,2620:9d::ffff:ffff:ffff:ffff:ffff,US +2620:9d:8000::,2620:9d:8000:ffff:ffff:ffff:ffff:ffff,US +2620:9e::,2620:9e::ffff:ffff:ffff:ffff:ffff,US +2620:9e:8000::,2620:9e:8000:ffff:ffff:ffff:ffff:ffff,US +2620:9f::,2620:9f:ff:ffff:ffff:ffff:ffff:ffff,US +2620:9f:8000::,2620:9f:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a0::,2620:a0::ffff:ffff:ffff:ffff:ffff,US +2620:a0:8000::,2620:a0:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a1::,2620:a1::ffff:ffff:ffff:ffff:ffff,US +2620:a1:8000::,2620:a1:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a2::,2620:a2::ffff:ffff:ffff:ffff:ffff,US +2620:a2:8000::,2620:a2:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a3::,2620:a3::ffff:ffff:ffff:ffff:ffff,US +2620:a3:8000::,2620:a3:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a4::,2620:a4:f:ffff:ffff:ffff:ffff:ffff,US +2620:a4:8080::,2620:a4:8080:ffff:ffff:ffff:ffff:ffff,US +2620:a5::,2620:a5::ffff:ffff:ffff:ffff:ffff,US +2620:a5:8000::,2620:a5:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a6::,2620:a6::ffff:ffff:ffff:ffff:ffff,US +2620:a6:8000::,2620:a6:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a7::,2620:a7::ffff:ffff:ffff:ffff:ffff,US +2620:a7:8000::,2620:a7:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a8::,2620:a8::ffff:ffff:ffff:ffff:ffff,US +2620:a8:8000::,2620:a8:8000:ffff:ffff:ffff:ffff:ffff,US +2620:a9::,2620:a9::ffff:ffff:ffff:ffff:ffff,US +2620:a9:8000::,2620:a9:8000:ffff:ffff:ffff:ffff:ffff,US +2620:aa::,2620:aa::ffff:ffff:ffff:ffff:ffff,US +2620:aa:8000::,2620:aa:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ab::,2620:ab::ffff:ffff:ffff:ffff:ffff,US +2620:ab:8000::,2620:ab:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ac::,2620:ac::ffff:ffff:ffff:ffff:ffff,US +2620:ac:8000::,2620:ac:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ad::,2620:ad::ffff:ffff:ffff:ffff:ffff,US +2620:ad:8000::,2620:ad:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ae::,2620:ae::ffff:ffff:ffff:ffff:ffff,CA +2620:ae:8000::,2620:ae:8000:ffff:ffff:ffff:ffff:ffff,US +2620:af::,2620:af::ffff:ffff:ffff:ffff:ffff,US +2620:af:8000::,2620:af:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b0::,2620:b0::ffff:ffff:ffff:ffff:ffff,CA +2620:b0:8000::,2620:b0:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b1::,2620:b1::ffff:ffff:ffff:ffff:ffff,US +2620:b1:8000::,2620:b1:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b2::,2620:b2::ffff:ffff:ffff:ffff:ffff,US +2620:b2:8000::,2620:b2:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b3::,2620:b3::ffff:ffff:ffff:ffff:ffff,US +2620:b3:8000::,2620:b3:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b4::,2620:b4::ffff:ffff:ffff:ffff:ffff,US +2620:b4:8000::,2620:b4:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:b5::,2620:b5::ffff:ffff:ffff:ffff:ffff,US +2620:b5:8000::,2620:b5:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b6::,2620:b6::ffff:ffff:ffff:ffff:ffff,US +2620:b6:8000::,2620:b6:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b7::,2620:b7::ffff:ffff:ffff:ffff:ffff,US +2620:b7:8000::,2620:b7:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:b8::,2620:b8::ffff:ffff:ffff:ffff:ffff,US +2620:b8:8000::,2620:b8:8000:ffff:ffff:ffff:ffff:ffff,US +2620:b9::,2620:b9::ffff:ffff:ffff:ffff:ffff,US +2620:b9:8000::,2620:b9:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ba::,2620:ba::ffff:ffff:ffff:ffff:ffff,US +2620:ba:8000::,2620:ba:8000:ffff:ffff:ffff:ffff:ffff,US +2620:bb::,2620:bb::ffff:ffff:ffff:ffff:ffff,US +2620:bb:8000::,2620:bb:8000:ffff:ffff:ffff:ffff:ffff,US +2620:bc::,2620:bc::ffff:ffff:ffff:ffff:ffff,US +2620:bc:8000::,2620:bc:8000:ffff:ffff:ffff:ffff:ffff,US +2620:bd::,2620:bd::ffff:ffff:ffff:ffff:ffff,CA +2620:bd:8000::,2620:bd:8000:ffff:ffff:ffff:ffff:ffff,US +2620:be::,2620:be::ffff:ffff:ffff:ffff:ffff,US +2620:be:8000::,2620:be:8000:ffff:ffff:ffff:ffff:ffff,US +2620:bf::,2620:bf::ffff:ffff:ffff:ffff:ffff,US +2620:bf:8000::,2620:bf:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c0::,2620:c0::ffff:ffff:ffff:ffff:ffff,US +2620:c0:8000::,2620:c0:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c1::,2620:c1::ffff:ffff:ffff:ffff:ffff,US +2620:c1:8000::,2620:c1:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c2::,2620:c2::ffff:ffff:ffff:ffff:ffff,CA +2620:c2:8000::,2620:c2:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c3::,2620:c3::ffff:ffff:ffff:ffff:ffff,US +2620:c3:8000::,2620:c3:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c4::,2620:c4::ffff:ffff:ffff:ffff:ffff,US +2620:c4:8000::,2620:c4:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c5::,2620:c5::ffff:ffff:ffff:ffff:ffff,US +2620:c5:8000::,2620:c5:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c6::,2620:c6::ffff:ffff:ffff:ffff:ffff,US +2620:c6:8000::,2620:c6:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c7::,2620:c7::ffff:ffff:ffff:ffff:ffff,US +2620:c7:8000::,2620:c7:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c8::,2620:c8::ffff:ffff:ffff:ffff:ffff,US +2620:c8:8000::,2620:c8:8000:ffff:ffff:ffff:ffff:ffff,US +2620:c9::,2620:c9::ffff:ffff:ffff:ffff:ffff,US +2620:c9:8000::,2620:c9:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ca::,2620:ca::ffff:ffff:ffff:ffff:ffff,US +2620:ca:8000::,2620:ca:8000:ffff:ffff:ffff:ffff:ffff,US +2620:cb::,2620:cb::ffff:ffff:ffff:ffff:ffff,US +2620:cb:8000::,2620:cb:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:cc::,2620:cc::ffff:ffff:ffff:ffff:ffff,US +2620:cc:8000::,2620:cc:8000:ffff:ffff:ffff:ffff:ffff,US +2620:cd::,2620:cd::ffff:ffff:ffff:ffff:ffff,US +2620:cd:8000::,2620:cd:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ce::,2620:ce::ffff:ffff:ffff:ffff:ffff,US +2620:ce:8000::,2620:ce:8000:ffff:ffff:ffff:ffff:ffff,US +2620:cf::,2620:cf::ffff:ffff:ffff:ffff:ffff,US +2620:cf:8000::,2620:cf:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d0::,2620:d0::ffff:ffff:ffff:ffff:ffff,US +2620:d0:8000::,2620:d0:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d1::,2620:d1::ffff:ffff:ffff:ffff:ffff,US +2620:d1:8000::,2620:d1:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d2::,2620:d2::ffff:ffff:ffff:ffff:ffff,US +2620:d2:8000::,2620:d2:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d3::,2620:d3::ffff:ffff:ffff:ffff:ffff,US +2620:d3:8000::,2620:d3:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d4::,2620:d4::ffff:ffff:ffff:ffff:ffff,US +2620:d4:8000::,2620:d4:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d5::,2620:d5::ffff:ffff:ffff:ffff:ffff,US +2620:d5:8000::,2620:d5:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d6::,2620:d6::ffff:ffff:ffff:ffff:ffff,US +2620:d6:8000::,2620:d6:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d7::,2620:d7::ffff:ffff:ffff:ffff:ffff,US +2620:d7:8000::,2620:d7:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d8::,2620:d8::ffff:ffff:ffff:ffff:ffff,US +2620:d8:8000::,2620:d8:8000:ffff:ffff:ffff:ffff:ffff,US +2620:d9::,2620:d9::ffff:ffff:ffff:ffff:ffff,US +2620:d9:8000::,2620:d9:8000:ffff:ffff:ffff:ffff:ffff,US +2620:da::,2620:da::ffff:ffff:ffff:ffff:ffff,US +2620:da:8000::,2620:da:8000:ffff:ffff:ffff:ffff:ffff,US +2620:db::,2620:db::ffff:ffff:ffff:ffff:ffff,US +2620:db:8000::,2620:db:8000:ffff:ffff:ffff:ffff:ffff,US +2620:dc::,2620:dc::ffff:ffff:ffff:ffff:ffff,US +2620:dc:8::,2620:dc:8:ffff:ffff:ffff:ffff:ffff,US +2620:dc:8000::,2620:dc:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:dd::,2620:dd::ffff:ffff:ffff:ffff:ffff,CA +2620:dd:8000::,2620:dd:8000:ffff:ffff:ffff:ffff:ffff,US +2620:de::,2620:de::ffff:ffff:ffff:ffff:ffff,US +2620:de:8000::,2620:de:8000:ffff:ffff:ffff:ffff:ffff,US +2620:df::,2620:df::ffff:ffff:ffff:ffff:ffff,US +2620:df:8000::,2620:df:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e0::,2620:e0::ffff:ffff:ffff:ffff:ffff,US +2620:e0:8000::,2620:e0:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e1::,2620:e1::ffff:ffff:ffff:ffff:ffff,US +2620:e1:8000::,2620:e1:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e2::,2620:e2::ffff:ffff:ffff:ffff:ffff,US +2620:e2:8000::,2620:e2:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e3::,2620:e3::ffff:ffff:ffff:ffff:ffff,US +2620:e3:8000::,2620:e3:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e4::,2620:e4::ffff:ffff:ffff:ffff:ffff,US +2620:e4:8000::,2620:e4:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e5::,2620:e5::ffff:ffff:ffff:ffff:ffff,US +2620:e5:8000::,2620:e5:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e6::,2620:e6::ffff:ffff:ffff:ffff:ffff,US +2620:e6:8000::,2620:e6:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e7::,2620:e7::ffff:ffff:ffff:ffff:ffff,US +2620:e7:8000::,2620:e7:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:e8::,2620:e8::ffff:ffff:ffff:ffff:ffff,US +2620:e8:8000::,2620:e8:8000:ffff:ffff:ffff:ffff:ffff,US +2620:e9::,2620:e9::ffff:ffff:ffff:ffff:ffff,US +2620:e9:8000::,2620:e9:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ea::,2620:ea:f:ffff:ffff:ffff:ffff:ffff,US +2620:ea:8000::,2620:ea:8000:ffff:ffff:ffff:ffff:ffff,US +2620:eb::,2620:eb::ffff:ffff:ffff:ffff:ffff,US +2620:eb:8000::,2620:eb:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ec::,2620:ec::ffff:ffff:ffff:ffff:ffff,US +2620:ec:8000::,2620:ec:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ed::,2620:ed::ffff:ffff:ffff:ffff:ffff,US +2620:ed:8000::,2620:ed:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ee::,2620:ee::ffff:ffff:ffff:ffff:ffff,US +2620:ee:8000::,2620:ee:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ef::,2620:ef::ffff:ffff:ffff:ffff:ffff,US +2620:ef:8000::,2620:ef:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f0::,2620:f0::ffff:ffff:ffff:ffff:ffff,US +2620:f0:8000::,2620:f0:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f1::,2620:f1::ffff:ffff:ffff:ffff:ffff,US +2620:f1:8000::,2620:f1:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f2::,2620:f2::ffff:ffff:ffff:ffff:ffff,CA +2620:f2:8000::,2620:f2:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f3::,2620:f3::ffff:ffff:ffff:ffff:ffff,US +2620:f3:8000::,2620:f3:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f4::,2620:f4::ffff:ffff:ffff:ffff:ffff,US +2620:f4:8000::,2620:f4:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:f5::,2620:f5::ffff:ffff:ffff:ffff:ffff,US +2620:f5:8000::,2620:f5:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f6::,2620:f6::ffff:ffff:ffff:ffff:ffff,CA +2620:f6:8000::,2620:f6:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f7::,2620:f7::ffff:ffff:ffff:ffff:ffff,US +2620:f7:8000::,2620:f7:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f8::,2620:f8::ffff:ffff:ffff:ffff:ffff,US +2620:f8:8000::,2620:f8:8000:ffff:ffff:ffff:ffff:ffff,US +2620:f9::,2620:f9:f:ffff:ffff:ffff:ffff:ffff,US +2620:f9:8000::,2620:f9:8000:ffff:ffff:ffff:ffff:ffff,US +2620:fa::,2620:fa::ffff:ffff:ffff:ffff:ffff,US +2620:fa:8000::,2620:fa:8000:ffff:ffff:ffff:ffff:ffff,CA +2620:fb::,2620:fb::ffff:ffff:ffff:ffff:ffff,US +2620:fb:8000::,2620:fb:8000:ffff:ffff:ffff:ffff:ffff,US +2620:fc::,2620:fc::ffff:ffff:ffff:ffff:ffff,CA +2620:fc:8000::,2620:fc:8000:ffff:ffff:ffff:ffff:ffff,US +2620:fd::,2620:fd::ffff:ffff:ffff:ffff:ffff,CA +2620:fd:8000::,2620:fd:8000:ffff:ffff:ffff:ffff:ffff,US +2620:fe::,2620:fe:ff:ffff:ffff:ffff:ffff:ffff,US +2620:fe:8000::,2620:fe:8000:ffff:ffff:ffff:ffff:ffff,US +2620:ff::,2620:ff::ffff:ffff:ffff:ffff:ffff,US +2620:100::,2620:100:f:ffff:ffff:ffff:ffff:ffff,US +2620:100:1000::,2620:100:1001:ffff:ffff:ffff:ffff:ffff,US +2620:100:3000::,2620:100:3007:ffff:ffff:ffff:ffff:ffff,US +2620:100:4000::,2620:100:403f:ffff:ffff:ffff:ffff:ffff,US +2620:100:5000::,2620:100:5007:ffff:ffff:ffff:ffff:ffff,US +2620:100:6000::,2620:100:600f:ffff:ffff:ffff:ffff:ffff,US +2620:100:7000::,2620:100:700f:ffff:ffff:ffff:ffff:ffff,US +2620:100:8000::,2620:100:8003:ffff:ffff:ffff:ffff:ffff,US +2620:100:9000::,2620:100:900f:ffff:ffff:ffff:ffff:ffff,US +2620:100:a000::,2620:100:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:100:c000::,2620:100:c03f:ffff:ffff:ffff:ffff:ffff,US +2620:100:d000::,2620:100:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:100:e000::,2620:100:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:100:f000::,2620:100:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:101::,2620:101:3:ffff:ffff:ffff:ffff:ffff,US +2620:101:1000::,2620:101:103f:ffff:ffff:ffff:ffff:ffff,US +2620:101:2000::,2620:101:201f:ffff:ffff:ffff:ffff:ffff,US +2620:101:3000::,2620:101:303f:ffff:ffff:ffff:ffff:ffff,US +2620:101:4000::,2620:101:403f:ffff:ffff:ffff:ffff:ffff,US +2620:101:5000::,2620:101:503f:ffff:ffff:ffff:ffff:ffff,US +2620:101:6000::,2620:101:6001:ffff:ffff:ffff:ffff:ffff,US +2620:101:7000::,2620:101:7001:ffff:ffff:ffff:ffff:ffff,US +2620:101:8000::,2620:101:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:101:9000::,2620:101:900f:ffff:ffff:ffff:ffff:ffff,US +2620:101:a000::,2620:101:a001:ffff:ffff:ffff:ffff:ffff,US +2620:101:b000::,2620:101:b07f:ffff:ffff:ffff:ffff:ffff,US +2620:101:c000::,2620:101:c00f:ffff:ffff:ffff:ffff:ffff,CA +2620:101:d000::,2620:101:d007:ffff:ffff:ffff:ffff:ffff,US +2620:101:e000::,2620:101:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:101:f000::,2620:101:f001:ffff:ffff:ffff:ffff:ffff,CA +2620:102::,2620:102:f:ffff:ffff:ffff:ffff:ffff,US +2620:102:2000::,2620:102:200f:ffff:ffff:ffff:ffff:ffff,US +2620:102:3000::,2620:102:300f:ffff:ffff:ffff:ffff:ffff,US +2620:102:4000::,2620:102:403f:ffff:ffff:ffff:ffff:ffff,US +2620:102:5000::,2620:102:501f:ffff:ffff:ffff:ffff:ffff,US +2620:102:6000::,2620:102:6003:ffff:ffff:ffff:ffff:ffff,US +2620:102:7000::,2620:102:700f:ffff:ffff:ffff:ffff:ffff,US +2620:102:8000::,2620:102:800f:ffff:ffff:ffff:ffff:ffff,US +2620:102:9000::,2620:102:90ff:ffff:ffff:ffff:ffff:ffff,US +2620:102:a000::,2620:102:a01f:ffff:ffff:ffff:ffff:ffff,US +2620:102:b000::,2620:102:b001:ffff:ffff:ffff:ffff:ffff,US +2620:102:c000::,2620:102:c007:ffff:ffff:ffff:ffff:ffff,US +2620:102:d000::,2620:102:d07f:ffff:ffff:ffff:ffff:ffff,US +2620:102:e000::,2620:102:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:102:f000::,2620:102:f003:ffff:ffff:ffff:ffff:ffff,US +2620:103::,2620:103:7:ffff:ffff:ffff:ffff:ffff,US +2620:103:1000::,2620:103:100f:ffff:ffff:ffff:ffff:ffff,US +2620:103:2000::,2620:103:200f:ffff:ffff:ffff:ffff:ffff,CA +2620:103:3000::,2620:103:30ff:ffff:ffff:ffff:ffff:ffff,US +2620:103:4000::,2620:103:400f:ffff:ffff:ffff:ffff:ffff,US +2620:103:5000::,2620:103:500f:ffff:ffff:ffff:ffff:ffff,US +2620:103:6000::,2620:103:600f:ffff:ffff:ffff:ffff:ffff,US +2620:103:7000::,2620:103:700f:ffff:ffff:ffff:ffff:ffff,US +2620:103:8000::,2620:103:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:103:9000::,2620:103:90ff:ffff:ffff:ffff:ffff:ffff,US +2620:103:a000::,2620:103:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:103:b000::,2620:103:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:103:c000::,2620:103:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:103:d000::,2620:103:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:103:e000::,2620:103:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:103:f000::,2620:103:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:104::,2620:104:ff:ffff:ffff:ffff:ffff:ffff,US +2620:104:1000::,2620:104:100f:ffff:ffff:ffff:ffff:ffff,US +2620:104:2000::,2620:104:20ff:ffff:ffff:ffff:ffff:ffff,US +2620:104:3000::,2620:104:300f:ffff:ffff:ffff:ffff:ffff,US +2620:104:4000::,2620:104:400f:ffff:ffff:ffff:ffff:ffff,US +2620:104:5000::,2620:104:500f:ffff:ffff:ffff:ffff:ffff,US +2620:104:6000::,2620:104:600f:ffff:ffff:ffff:ffff:ffff,US +2620:104:7000::,2620:104:70ff:ffff:ffff:ffff:ffff:ffff,US +2620:104:8000::,2620:104:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:104:9000::,2620:104:900f:ffff:ffff:ffff:ffff:ffff,US +2620:104:a000::,2620:104:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:104:b000::,2620:104:b01f:ffff:ffff:ffff:ffff:ffff,US +2620:104:c000::,2620:104:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:104:d000::,2620:104:d0ff:ffff:ffff:ffff:ffff:ffff,US +2620:104:e000::,2620:104:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:104:f000::,2620:104:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:105::,2620:105:f:ffff:ffff:ffff:ffff:ffff,CA +2620:105:1000::,2620:105:100f:ffff:ffff:ffff:ffff:ffff,US +2620:105:2000::,2620:105:20ff:ffff:ffff:ffff:ffff:ffff,US +2620:105:3000::,2620:105:300f:ffff:ffff:ffff:ffff:ffff,US +2620:105:4000::,2620:105:400f:ffff:ffff:ffff:ffff:ffff,US +2620:105:5000::,2620:105:500f:ffff:ffff:ffff:ffff:ffff,US +2620:105:6000::,2620:105:600f:ffff:ffff:ffff:ffff:ffff,US +2620:105:7000::,2620:105:700f:ffff:ffff:ffff:ffff:ffff,US +2620:105:8000::,2620:105:800f:ffff:ffff:ffff:ffff:ffff,US +2620:105:9000::,2620:105:90ff:ffff:ffff:ffff:ffff:ffff,US +2620:105:a000::,2620:105:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:105:b000::,2620:105:b0ff:ffff:ffff:ffff:ffff:ffff,US +2620:105:c000::,2620:105:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:105:d000::,2620:105:d0ff:ffff:ffff:ffff:ffff:ffff,US +2620:105:e000::,2620:105:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:105:f000::,2620:105:f0ff:ffff:ffff:ffff:ffff:ffff,US +2620:106::,2620:106:f:ffff:ffff:ffff:ffff:ffff,US +2620:106:1000::,2620:106:10ff:ffff:ffff:ffff:ffff:ffff,US +2620:106:2000::,2620:106:20ff:ffff:ffff:ffff:ffff:ffff,US +2620:106:3000::,2620:106:30ff:ffff:ffff:ffff:ffff:ffff,US +2620:106:4000::,2620:106:400f:ffff:ffff:ffff:ffff:ffff,US +2620:106:5000::,2620:106:50ff:ffff:ffff:ffff:ffff:ffff,US +2620:106:6000::,2620:106:600f:ffff:ffff:ffff:ffff:ffff,US +2620:106:7000::,2620:106:70ff:ffff:ffff:ffff:ffff:ffff,US +2620:106:8000::,2620:106:800f:ffff:ffff:ffff:ffff:ffff,US +2620:106:9000::,2620:106:900f:ffff:ffff:ffff:ffff:ffff,US +2620:106:a000::,2620:106:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:106:b000::,2620:106:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:106:c000::,2620:106:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:106:d000::,2620:106:d0ff:ffff:ffff:ffff:ffff:ffff,US +2620:106:e000::,2620:106:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:106:f000::,2620:106:f00f:ffff:ffff:ffff:ffff:ffff,CA +2620:107::,2620:107:ff:ffff:ffff:ffff:ffff:ffff,US +2620:107:1000::,2620:107:100f:ffff:ffff:ffff:ffff:ffff,US +2620:107:2000::,2620:107:200f:ffff:ffff:ffff:ffff:ffff,US +2620:107:3000::,2620:107:300f:ffff:ffff:ffff:ffff:ffff,US +2620:107:4000::,2620:107:400f:ffff:ffff:ffff:ffff:ffff,US +2620:107:5000::,2620:107:500f:ffff:ffff:ffff:ffff:ffff,US +2620:107:6000::,2620:107:600f:ffff:ffff:ffff:ffff:ffff,US +2620:107:7000::,2620:107:700f:ffff:ffff:ffff:ffff:ffff,US +2620:107:8000::,2620:107:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:107:9000::,2620:107:90ff:ffff:ffff:ffff:ffff:ffff,US +2620:107:a000::,2620:107:a0ff:ffff:ffff:ffff:ffff:ffff,US +2620:107:c000::,2620:107:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:107:d000::,2620:107:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:107:e000::,2620:107:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:107:f000::,2620:107:f0ff:ffff:ffff:ffff:ffff:ffff,US +2620:108::,2620:108:ff:ffff:ffff:ffff:ffff:ffff,US +2620:108:1000::,2620:108:10ff:ffff:ffff:ffff:ffff:ffff,US +2620:108:2000::,2620:108:200f:ffff:ffff:ffff:ffff:ffff,US +2620:108:3000::,2620:108:300f:ffff:ffff:ffff:ffff:ffff,US +2620:108:4000::,2620:108:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:108:5000::,2620:108:500f:ffff:ffff:ffff:ffff:ffff,US +2620:108:6000::,2620:108:60ff:ffff:ffff:ffff:ffff:ffff,US +2620:108:7000::,2620:108:700f:ffff:ffff:ffff:ffff:ffff,US +2620:108:8000::,2620:108:800f:ffff:ffff:ffff:ffff:ffff,US +2620:108:9000::,2620:108:900f:ffff:ffff:ffff:ffff:ffff,US +2620:108:a000::,2620:108:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:108:b000::,2620:108:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:108:c000::,2620:108:c0ff:ffff:ffff:ffff:ffff:ffff,US +2620:108:d000::,2620:108:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:108:e000::,2620:108:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:108:f000::,2620:108:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:109::,2620:109:ff:ffff:ffff:ffff:ffff:ffff,US +2620:109:1000::,2620:109:10ff:ffff:ffff:ffff:ffff:ffff,US +2620:109:2000::,2620:109:200f:ffff:ffff:ffff:ffff:ffff,US +2620:109:3000::,2620:109:300f:ffff:ffff:ffff:ffff:ffff,US +2620:109:4000::,2620:109:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:109:5000::,2620:109:500f:ffff:ffff:ffff:ffff:ffff,US +2620:109:6000::,2620:109:600f:ffff:ffff:ffff:ffff:ffff,US +2620:109:7000::,2620:109:70ff:ffff:ffff:ffff:ffff:ffff,US +2620:109:8000::,2620:109:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:109:9000::,2620:109:90ff:ffff:ffff:ffff:ffff:ffff,US +2620:109:a000::,2620:109:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:109:b000::,2620:109:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:109:c000::,2620:109:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:109:d000::,2620:109:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:109:e000::,2620:109:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:109:f000::,2620:109:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:10a::,2620:10a:f:ffff:ffff:ffff:ffff:ffff,US +2620:10a:1000::,2620:10a:100f:ffff:ffff:ffff:ffff:ffff,US +2620:10a:2000::,2620:10a:200f:ffff:ffff:ffff:ffff:ffff,US +2620:10a:3000::,2620:10a:30ff:ffff:ffff:ffff:ffff:ffff,US +2620:10a:4000::,2620:10a:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:10a:5000::,2620:10a:50ff:ffff:ffff:ffff:ffff:ffff,US +2620:10a:6000::,2620:10a:600f:ffff:ffff:ffff:ffff:ffff,US +2620:10a:7000::,2620:10a:700f:ffff:ffff:ffff:ffff:ffff,CA +2620:10a:8000::,2620:10a:800f:ffff:ffff:ffff:ffff:ffff,CA +2620:10a:9000::,2620:10a:90ff:ffff:ffff:ffff:ffff:ffff,US +2620:10a:a000::,2620:10a:a0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10a:b000::,2620:10a:b0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10a:c000::,2620:10a:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:10a:d000::,2620:10a:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:10a:e000::,2620:10a:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10a:f000::,2620:10a:f0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10b::,2620:10b:f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:1000::,2620:10b:10ff:ffff:ffff:ffff:ffff:ffff,US +2620:10b:2000::,2620:10b:200f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:3000::,2620:10b:30ff:ffff:ffff:ffff:ffff:ffff,CA +2620:10b:4000::,2620:10b:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:10b:5000::,2620:10b:500f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:6000::,2620:10b:60ff:ffff:ffff:ffff:ffff:ffff,US +2620:10b:7000::,2620:10b:700f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:8000::,2620:10b:800f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:9000::,2620:10b:900f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:a000::,2620:10b:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:b000::,2620:10b:b00f:ffff:ffff:ffff:ffff:ffff,CA +2620:10b:c000::,2620:10b:c0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10b:d000::,2620:10b:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:10b:e000::,2620:10b:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10b:f000::,2620:10b:f0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10c::,2620:10c:f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:1000::,2620:10c:10ff:ffff:ffff:ffff:ffff:ffff,US +2620:10c:2000::,2620:10c:200f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:3000::,2620:10c:300f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:4000::,2620:10c:400f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:5000::,2620:10c:500f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:6000::,2620:10c:600f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:7000::,2620:10c:700f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:8000::,2620:10c:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:10c:9000::,2620:10c:90ff:ffff:ffff:ffff:ffff:ffff,US +2620:10c:a000::,2620:10c:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:b000::,2620:10c:b0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10c:c000::,2620:10c:c0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10c:d000::,2620:10c:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:10c:e000::,2620:10c:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10c:f000::,2620:10c:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:10d::,2620:10d:f:ffff:ffff:ffff:ffff:ffff,US +2620:10d:1000::,2620:10d:100f:ffff:ffff:ffff:ffff:ffff,US +2620:10d:2000::,2620:10d:20ff:ffff:ffff:ffff:ffff:ffff,US +2620:10d:3000::,2620:10d:300f:ffff:ffff:ffff:ffff:ffff,US +2620:10d:4000::,2620:10d:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:10d:5000::,2620:10d:50ff:ffff:ffff:ffff:ffff:ffff,US +2620:10d:6000::,2620:10d:600f:ffff:ffff:ffff:ffff:ffff,US +2620:10d:7000::,2620:10d:70ff:ffff:ffff:ffff:ffff:ffff,US +2620:10d:8000::,2620:10d:800f:ffff:ffff:ffff:ffff:ffff,US +2620:10d:9000::,2620:10d:900f:ffff:ffff:ffff:ffff:ffff,US +2620:10d:a000::,2620:10d:a0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10d:b000::,2620:10d:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:10d:c000::,2620:10d:c0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10d:d000::,2620:10d:d00f:ffff:ffff:ffff:ffff:ffff,CA +2620:10d:e000::,2620:10d:e00f:ffff:ffff:ffff:ffff:ffff,CA +2620:10d:f000::,2620:10d:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:10e::,2620:10e:f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:1000::,2620:10e:100f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:2000::,2620:10e:200f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:3000::,2620:10e:30ff:ffff:ffff:ffff:ffff:ffff,US +2620:10e:4000::,2620:10e:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:10e:5000::,2620:10e:500f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:6000::,2620:10e:60ff:ffff:ffff:ffff:ffff:ffff,US +2620:10e:7000::,2620:10e:70ff:ffff:ffff:ffff:ffff:ffff,US +2620:10e:8000::,2620:10e:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:10e:9000::,2620:10e:900f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:a000::,2620:10e:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:b000::,2620:10e:b0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10e:c000::,2620:10e:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:d000::,2620:10e:d00f:ffff:ffff:ffff:ffff:ffff,BL +2620:10e:e000::,2620:10e:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:10e:f000::,2620:10e:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:10f::,2620:10f:f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:1000::,2620:10f:100f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:2000::,2620:10f:200f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:3000::,2620:10f:30ff:ffff:ffff:ffff:ffff:ffff,US +2620:10f:4000::,2620:10f:400f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:5000::,2620:10f:50ff:ffff:ffff:ffff:ffff:ffff,US +2620:10f:6000::,2620:10f:60ff:ffff:ffff:ffff:ffff:ffff,US +2620:10f:7000::,2620:10f:700f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:8000::,2620:10f:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:10f:9000::,2620:10f:900f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:a000::,2620:10f:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:b000::,2620:10f:b0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10f:c000::,2620:10f:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:d000::,2620:10f:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:10f:e000::,2620:10f:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:10f:f000::,2620:10f:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:110::,2620:110:f:ffff:ffff:ffff:ffff:ffff,US +2620:110:1000::,2620:110:100f:ffff:ffff:ffff:ffff:ffff,US +2620:110:2000::,2620:110:20ff:ffff:ffff:ffff:ffff:ffff,US +2620:110:3000::,2620:110:30ff:ffff:ffff:ffff:ffff:ffff,US +2620:110:4000::,2620:110:400f:ffff:ffff:ffff:ffff:ffff,US +2620:110:5000::,2620:110:500f:ffff:ffff:ffff:ffff:ffff,US +2620:110:6000::,2620:110:600f:ffff:ffff:ffff:ffff:ffff,US +2620:110:7000::,2620:110:700f:ffff:ffff:ffff:ffff:ffff,US +2620:110:8000::,2620:110:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:110:9000::,2620:110:900f:ffff:ffff:ffff:ffff:ffff,US +2620:110:a000::,2620:110:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:110:b000::,2620:110:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:110:c000::,2620:110:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:110:d000::,2620:110:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:110:e000::,2620:110:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:110:f000::,2620:110:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:111::,2620:111:ff:ffff:ffff:ffff:ffff:ffff,US +2620:111:1000::,2620:111:100f:ffff:ffff:ffff:ffff:ffff,US +2620:111:2000::,2620:111:200f:ffff:ffff:ffff:ffff:ffff,US +2620:111:3000::,2620:111:300f:ffff:ffff:ffff:ffff:ffff,US +2620:111:4000::,2620:111:400f:ffff:ffff:ffff:ffff:ffff,US +2620:111:5000::,2620:111:500f:ffff:ffff:ffff:ffff:ffff,US +2620:111:6000::,2620:111:600f:ffff:ffff:ffff:ffff:ffff,US +2620:111:7000::,2620:111:700f:ffff:ffff:ffff:ffff:ffff,US +2620:111:8000::,2620:111:800f:ffff:ffff:ffff:ffff:ffff,US +2620:111:9000::,2620:111:900f:ffff:ffff:ffff:ffff:ffff,US +2620:111:a000::,2620:111:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:111:b000::,2620:111:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:111:c000::,2620:111:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:111:d000::,2620:111:d0ff:ffff:ffff:ffff:ffff:ffff,US +2620:111:e000::,2620:111:e00f:ffff:ffff:ffff:ffff:ffff,CA +2620:111:f000::,2620:111:f0ff:ffff:ffff:ffff:ffff:ffff,US +2620:112::,2620:112:f:ffff:ffff:ffff:ffff:ffff,US +2620:112:1000::,2620:112:107f:ffff:ffff:ffff:ffff:ffff,US +2620:112:2000::,2620:112:200f:ffff:ffff:ffff:ffff:ffff,US +2620:112:3000::,2620:112:300f:ffff:ffff:ffff:ffff:ffff,US +2620:112:4000::,2620:112:400f:ffff:ffff:ffff:ffff:ffff,US +2620:112:5000::,2620:112:500f:ffff:ffff:ffff:ffff:ffff,US +2620:112:6000::,2620:112:600f:ffff:ffff:ffff:ffff:ffff,US +2620:112:7000::,2620:112:700f:ffff:ffff:ffff:ffff:ffff,US +2620:112:8000::,2620:112:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:112:9000::,2620:112:900f:ffff:ffff:ffff:ffff:ffff,CA +2620:112:a000::,2620:112:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:112:b000::,2620:112:b0ff:ffff:ffff:ffff:ffff:ffff,US +2620:112:c000::,2620:112:c0ff:ffff:ffff:ffff:ffff:ffff,US +2620:112:d000::,2620:112:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:112:e000::,2620:112:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:112:f000::,2620:112:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:113::,2620:113:f:ffff:ffff:ffff:ffff:ffff,US +2620:113:1000::,2620:113:100f:ffff:ffff:ffff:ffff:ffff,US +2620:113:2000::,2620:113:200f:ffff:ffff:ffff:ffff:ffff,CA +2620:113:3000::,2620:113:300f:ffff:ffff:ffff:ffff:ffff,CA +2620:113:4000::,2620:113:400f:ffff:ffff:ffff:ffff:ffff,US +2620:113:5000::,2620:113:500f:ffff:ffff:ffff:ffff:ffff,US +2620:113:6000::,2620:113:600f:ffff:ffff:ffff:ffff:ffff,US +2620:113:7000::,2620:113:700f:ffff:ffff:ffff:ffff:ffff,US +2620:113:8000::,2620:113:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:113:9000::,2620:113:900f:ffff:ffff:ffff:ffff:ffff,US +2620:113:a000::,2620:113:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:113:b000::,2620:113:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:113:c000::,2620:113:c0ff:ffff:ffff:ffff:ffff:ffff,US +2620:113:d000::,2620:113:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:113:e000::,2620:113:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:113:f000::,2620:113:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:114::,2620:114:f:ffff:ffff:ffff:ffff:ffff,US +2620:114:1000::,2620:114:100f:ffff:ffff:ffff:ffff:ffff,US +2620:114:2000::,2620:114:20ff:ffff:ffff:ffff:ffff:ffff,US +2620:114:3000::,2620:114:300f:ffff:ffff:ffff:ffff:ffff,US +2620:114:4000::,2620:114:400f:ffff:ffff:ffff:ffff:ffff,US +2620:114:5000::,2620:114:50ff:ffff:ffff:ffff:ffff:ffff,US +2620:114:6000::,2620:114:600f:ffff:ffff:ffff:ffff:ffff,US +2620:114:7000::,2620:114:700f:ffff:ffff:ffff:ffff:ffff,US +2620:114:8000::,2620:114:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:114:9000::,2620:114:900f:ffff:ffff:ffff:ffff:ffff,US +2620:114:a000::,2620:114:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:114:b000::,2620:114:b0ff:ffff:ffff:ffff:ffff:ffff,US +2620:114:c000::,2620:114:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:114:d000::,2620:114:d00f:ffff:ffff:ffff:ffff:ffff,US +2620:114:e000::,2620:114:e0ff:ffff:ffff:ffff:ffff:ffff,US +2620:114:f000::,2620:114:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:115::,2620:115:f:ffff:ffff:ffff:ffff:ffff,US +2620:115:1000::,2620:115:100f:ffff:ffff:ffff:ffff:ffff,US +2620:115:2000::,2620:115:200f:ffff:ffff:ffff:ffff:ffff,US +2620:115:3000::,2620:115:300f:ffff:ffff:ffff:ffff:ffff,KY +2620:115:4000::,2620:115:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:115:5000::,2620:115:500f:ffff:ffff:ffff:ffff:ffff,US +2620:115:6000::,2620:115:600f:ffff:ffff:ffff:ffff:ffff,US +2620:115:7000::,2620:115:70ff:ffff:ffff:ffff:ffff:ffff,US +2620:115:8000::,2620:115:800f:ffff:ffff:ffff:ffff:ffff,US +2620:115:9000::,2620:115:900f:ffff:ffff:ffff:ffff:ffff,US +2620:115:a000::,2620:115:a00f:ffff:ffff:ffff:ffff:ffff,US +2620:115:b000::,2620:115:b00f:ffff:ffff:ffff:ffff:ffff,US +2620:115:c000::,2620:115:c00f:ffff:ffff:ffff:ffff:ffff,US +2620:115:d000::,2620:115:d0ff:ffff:ffff:ffff:ffff:ffff,US +2620:115:e000::,2620:115:e00f:ffff:ffff:ffff:ffff:ffff,US +2620:115:f000::,2620:115:f00f:ffff:ffff:ffff:ffff:ffff,US +2620:116::,2620:116:f:ffff:ffff:ffff:ffff:ffff,US +2620:116:1000::,2620:116:10ff:ffff:ffff:ffff:ffff:ffff,US +2620:116:2000::,2620:116:200f:ffff:ffff:ffff:ffff:ffff,US +2620:116:3000::,2620:116:300f:ffff:ffff:ffff:ffff:ffff,US +2620:116:4000::,2620:116:40ff:ffff:ffff:ffff:ffff:ffff,US +2620:116:5000::,2620:116:50ff:ffff:ffff:ffff:ffff:ffff,US +2620:116:6000::,2620:116:600f:ffff:ffff:ffff:ffff:ffff,US +2620:116:7000::,2620:116:700f:ffff:ffff:ffff:ffff:ffff,US +2620:116:8000::,2620:116:80ff:ffff:ffff:ffff:ffff:ffff,US +2620:140::,2620:140:3ff:ffff:ffff:ffff:ffff:ffff,US +2620:141::,2620:141:fff:ffff:ffff:ffff:ffff:ffff,US +2620:143::,2620:143:7ff:ffff:ffff:ffff:ffff:ffff,US +2620:144::,2620:145:fff:ffff:ffff:ffff:ffff:ffff,US +2620:146::,2620:146:fff:ffff:ffff:ffff:ffff:ffff,US +2620:147::,2620:147:fff:ffff:ffff:ffff:ffff:ffff,US +2620:148::,2620:148:fff:ffff:ffff:ffff:ffff:ffff,US +2620:149::,2620:149:fff:ffff:ffff:ffff:ffff:ffff,US +2620:14a::,2620:14a:fff:ffff:ffff:ffff:ffff:ffff,US +2620:14b::,2620:14b:fff:ffff:ffff:ffff:ffff:ffff,US +2620:14c::,2620:14c:fff:ffff:ffff:ffff:ffff:ffff,US +2620:14d::,2620:14d:fff:ffff:ffff:ffff:ffff:ffff,US +2620:14e::,2620:14e:fff:ffff:ffff:ffff:ffff:ffff,US +2620:14f::,2620:14f:fff:ffff:ffff:ffff:ffff:ffff,US +2620:150::,2620:150:fff:ffff:ffff:ffff:ffff:ffff,US +2620:151::,2620:151:fff:ffff:ffff:ffff:ffff:ffff,US +2620:152::,2620:152:fff:ffff:ffff:ffff:ffff:ffff,US +2620:153::,2620:153:fff:ffff:ffff:ffff:ffff:ffff,US +2620:154::,2620:154:fff:ffff:ffff:ffff:ffff:ffff,US +2620:155::,2620:155:fff:ffff:ffff:ffff:ffff:ffff,US +2620:156::,2620:156:fff:ffff:ffff:ffff:ffff:ffff,US +2620:157::,2620:157:fff:ffff:ffff:ffff:ffff:ffff,US +2620:158::,2620:158:fff:ffff:ffff:ffff:ffff:ffff,US +2620:159::,2620:159:fff:ffff:ffff:ffff:ffff:ffff,US +2620:15a::,2620:15a:fff:ffff:ffff:ffff:ffff:ffff,US +2620:15b::,2620:15b:fff:ffff:ffff:ffff:ffff:ffff,US +2620:15c::,2620:15c:fff:ffff:ffff:ffff:ffff:ffff,US +2620:15d::,2620:15e:fff:ffff:ffff:ffff:ffff:ffff,US +2620:15f::,2620:15f:fff:ffff:ffff:ffff:ffff:ffff,US +2620:160::,2620:160:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:162::,2620:162:fff:ffff:ffff:ffff:ffff:ffff,US +2620:163::,2620:163:fff:ffff:ffff:ffff:ffff:ffff,US +2620:164::,2620:164:fff:ffff:ffff:ffff:ffff:ffff,US +2620:165::,2620:165:fff:ffff:ffff:ffff:ffff:ffff,US +2620:166::,2620:166:fff:ffff:ffff:ffff:ffff:ffff,US +2620:167::,2620:167:fff:ffff:ffff:ffff:ffff:ffff,US +2620:168::,2620:169:fff:ffff:ffff:ffff:ffff:ffff,US +2620:16a::,2620:16a:fff:ffff:ffff:ffff:ffff:ffff,US +2620:16b::,2620:16c:fff:ffff:ffff:ffff:ffff:ffff,US +2620:16d::,2620:16f:fff:ffff:ffff:ffff:ffff:ffff,US +2620:170::,2620:170:fff:ffff:ffff:ffff:ffff:ffff,US +2620:171::,2620:171:fff:ffff:ffff:ffff:ffff:ffff,US +2620:172::,2620:172:fff:ffff:ffff:ffff:ffff:ffff,US +2620:173::,2620:173:fff:ffff:ffff:ffff:ffff:ffff,US +2620:174::,2620:174:fff:ffff:ffff:ffff:ffff:ffff,US +2620:175::,2620:175:fff:ffff:ffff:ffff:ffff:ffff,CA +2620:176::,2620:177:fff:ffff:ffff:ffff:ffff:ffff,US +2620:178::,2620:178:fff:ffff:ffff:ffff:ffff:ffff,US +2620:179::,2620:179:fff:ffff:ffff:ffff:ffff:ffff,US +2620:17a::,2620:17a:fff:ffff:ffff:ffff:ffff:ffff,US +2620:17b::,2620:17b:fff:ffff:ffff:ffff:ffff:ffff,US +2620:17c::,2620:17c:fff:ffff:ffff:ffff:ffff:ffff,US +2620:180::,2620:180:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:190::,2620:190:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:1a0::,2620:1a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:1b0::,2620:1b0:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:1c0::,2620:1c0:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:1d0::,2620:1d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:1e0::,2620:1e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2620:1f0::,2620:1f0:ffff:ffff:ffff:ffff:ffff:ffff,US +2800:8::,2800:8:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:10::,2800:10:ffff:ffff:ffff:ffff:ffff:ffff,NI +2800:18::,2800:18:ffff:ffff:ffff:ffff:ffff:ffff,PE +2800:20::,2800:30:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:38::,2800:38:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:40::,2800:40:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:48::,2800:48:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:68::,2800:68:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:70::,2800:70:ffff:ffff:ffff:ffff:ffff:ffff,TT +2800:78::,2800:78:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:80::,2800:80:ffff:ffff:ffff:ffff:ffff:ffff,CW +2800:88::,2800:88:ffff:ffff:ffff:ffff:ffff:ffff,BO +2800:90::,2800:90:ffff:ffff:ffff:ffff:ffff:ffff,SV +2800:98::,2800:98:ffff:ffff:ffff:ffff:ffff:ffff,GT +2800:a0::,2800:af:ffff:ffff:ffff:ffff:ffff:ffff,UY +2800:e0::,2800:ef:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:f0::,2800:f0:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:100::,2800:100:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:110::,2800:110:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:120::,2800:120:ffff:ffff:ffff:ffff:ffff:ffff,PE +2800:130::,2800:130:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:140::,2800:140:ffff:ffff:ffff:ffff:ffff:ffff,PA +2800:150::,2800:150:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:160::,2800:160:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:170::,2800:170:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:180::,2800:180:ffff:ffff:ffff:ffff:ffff:ffff,TT +2800:190::,2800:190:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:1a0::,2800:1a0:ffff:ffff:ffff:ffff:ffff:ffff,GT +2800:1b0::,2800:1b0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:1c0::,2800:1c0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:1d0::,2800:1d0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:1e0::,2800:1e0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:1f0::,2800:1f0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:200::,2800:200:ffff:ffff:ffff:ffff:ffff:ffff,PE +2800:220::,2800:220:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:230::,2800:230:ffff:ffff:ffff:ffff:ffff:ffff,CU +2800:240::,2800:240:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:250::,2800:250:ffff:ffff:ffff:ffff:ffff:ffff,UY +2800:260::,2800:26f:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:270::,2800:270:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:280::,2800:280:ffff:ffff:ffff:ffff:ffff:ffff,SX +2800:290::,2800:290:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:2a0::,2800:2a0:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:2b0::,2800:2b0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:2d0::,2800:2d0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:2e0::,2800:2e0:ffff:ffff:ffff:ffff:ffff:ffff,CW +2800:2f0::,2800:2f0:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:300::,2800:300:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:310::,2800:310:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:320::,2800:320:ffff:ffff:ffff:ffff:ffff:ffff,BO +2800:330::,2800:330:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:340::,2800:340:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:350::,2800:350:ffff:ffff:ffff:ffff:ffff:ffff,PA +2800:360::,2800:360:ffff:ffff:ffff:ffff:ffff:ffff,CU +2800:370::,2800:370:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:380::,2800:381:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:390::,2800:390:ffff:ffff:ffff:ffff:ffff:ffff,BO +2800:3a0::,2800:3a0:ffff:ffff:ffff:ffff:ffff:ffff,PY +2800:3b0::,2800:3b0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:3c0::,2800:3c0:ffff:ffff:ffff:ffff:ffff:ffff,GY +2800:3d0::,2800:3d0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:3e0::,2800:3e0:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:3f0::,2800:3f0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:400::,2800:400:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:410::,2800:410:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2800:420::,2800:423:ffff:ffff:ffff:ffff:ffff:ffff,TT +2800:430::,2800:430:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:440::,2800:440:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:450::,2800:450:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:460::,2800:460:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:470::,2800:470:ffff:ffff:ffff:ffff:ffff:ffff,SX +2800:480::,2800:480:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:490::,2800:490:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:4b0::,2800:4b0:ffff:ffff:ffff:ffff:ffff:ffff,PE +2800:4c0::,2800:4c0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:4d0::,2800:4d0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:4e0::,2800:4e0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:4f0::,2800:4f0:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:500::,2800:500:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:510::,2800:510:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:520::,2800:520:ffff:ffff:ffff:ffff:ffff:ffff,TT +2800:530::,2800:530:ffff:ffff:ffff:ffff:ffff:ffff,CW +2800:540::,2800:540:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:550::,2800:550:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:560::,2800:560:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:570::,2800:570:ffff:ffff:ffff:ffff:ffff:ffff,HT +2800:580::,2800:580:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:590::,2800:590:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:5a0::,2800:5a0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:5b0::,2800:5b0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:5c0::,2800:5c0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:5d0::,2800:5d0:ffff:ffff:ffff:ffff:ffff:ffff,PA +2800:5e0::,2800:5e0:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:5f0::,2800:5f0:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:600::,2800:600:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:610::,2800:610:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:620::,2800:620:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:630::,2800:630:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:640::,2800:640:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:650::,2800:650:ffff:ffff:ffff:ffff:ffff:ffff,PE +2800:660::,2800:660:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:670::,2800:670:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:680::,2800:680:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:690::,2800:690:ffff:ffff:ffff:ffff:ffff:ffff,PE +2800:6a0::,2800:6a0:ffff:ffff:ffff:ffff:ffff:ffff,HN +2800:6b0::,2800:6b0:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:6c0::,2800:6c0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:6d0::,2800:6d0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:6e0::,2800:6e0:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:6f0::,2800:6f0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:700::,2800:700:ffff:ffff:ffff:ffff:ffff:ffff,UY +2800:800::,2800:800:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:810::,2800:810:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:820::,2800:820:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:830::,2800:831:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:840::,2800:840:ffff:ffff:ffff:ffff:ffff:ffff,UY +2800:850::,2800:850:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:860::,2800:860:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:870::,2800:870:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:880::,2800:883:ffff:ffff:ffff:ffff:ffff:ffff,SV +2800:890::,2800:890:ffff:ffff:ffff:ffff:ffff:ffff,GT +2800:8a0::,2800:8a0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:8b0::,2800:8b0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:8c0::,2800:8c0:ffff:ffff:ffff:ffff:ffff:ffff,NI +2800:8d0::,2800:8d0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:8e0::,2800:8e0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:8f0::,2800:8f0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:900::,2800:900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:910::,2800:910:ffff:ffff:ffff:ffff:ffff:ffff,CU +2800:920::,2800:920:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:930::,2800:930:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:940::,2800:940:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:950::,2800:950:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:960::,2800:960:ffff:ffff:ffff:ffff:ffff:ffff,PY +2800:970::,2800:970:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:980::,2800:980:ffff:ffff:ffff:ffff:ffff:ffff,PA +2800:990::,2800:990:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:9a0::,2800:9a7:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:9b0::,2800:9b0:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:9c0::,2800:9c0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:9d0::,2800:9d0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:9e0::,2800:9e0:ffff:ffff:ffff:ffff:ffff:ffff,CW +2800:9f0::,2800:9f0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:a00::,2800:a00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:a10::,2800:a10:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:a20::,2800:a20:ffff:ffff:ffff:ffff:ffff:ffff,CW +2800:a30::,2800:a30:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:a40::,2800:a40:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:a50::,2800:a50:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:a60::,2800:a60:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:a70::,2800:a70:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:a80::,2800:a80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:a90::,2800:a90:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:aa0::,2800:aa0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:ab0::,2800:ab0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:ac0::,2800:ac0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:ad0::,2800:ad0:ffff:ffff:ffff:ffff:ffff:ffff,AW +2800:ae0::,2800:ae0:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:af0::,2800:af0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:b00::,2800:b00:ffff:ffff:ffff:ffff:ffff:ffff,BQ +2800:b10::,2800:b10:ffff:ffff:ffff:ffff:ffff:ffff,HN +2800:b20::,2800:b23:ffff:ffff:ffff:ffff:ffff:ffff,SV +2800:b30::,2800:b31:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:b40::,2800:b40:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:b60::,2800:b60:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:b70::,2800:b70:ffff:ffff:ffff:ffff:ffff:ffff,CO +2800:b80::,2800:b80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:b90::,2800:b90:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:ba0::,2800:ba0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:bb0::,2800:bbf:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:bc0::,2800:bc0:ffff:ffff:ffff:ffff:ffff:ffff,US +2800:bd0::,2800:bd0:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:be0::,2800:be0:ffff:ffff:ffff:ffff:ffff:ffff,CL +2800:bf0::,2800:bf0:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:c00::,2800:c00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:c10::,2800:c10:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:c20::,2800:c20:ffff:ffff:ffff:ffff:ffff:ffff,CR +2800:c30::,2800:c30:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:c40::,2800:c40:ffff:ffff:ffff:ffff:ffff:ffff,EC +2800:c50::,2800:c50:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:c70::,2800:c70:ffff:ffff:ffff:ffff:ffff:ffff,PY +2800:c80::,2800:c80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:c90::,2800:c90:ffff:ffff:ffff:ffff:ffff:ffff,DO +2800:ca0::,2800:ca0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:cb0::,2800:cb0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:cc0::,2800:cc0:ffff:ffff:ffff:ffff:ffff:ffff,PE +2800:cd0::,2800:cd0:ffff:ffff:ffff:ffff:ffff:ffff,BO +2800:ce0::,2800:ce0:ffff:ffff:ffff:ffff:ffff:ffff,PA +2800:cf0::,2800:cf0:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:d00::,2800:d00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:d10::,2800:d10:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:d20::,2800:d20:ffff:ffff:ffff:ffff:ffff:ffff,DO +2800:1000::,2800:10ff:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:2000::,2800:2fff:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:a000::,2800:a000:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:a008::,2800:a008:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:a010::,2800:a010:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:a018::,2800:a018:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:a020::,2800:a020:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:a028::,2800:a028:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:a030::,2800:a030:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:a038::,2800:a038:ffff:ffff:ffff:ffff:ffff:ffff,VE +2800:b000::,2800:b000:ffff:ffff:ffff:ffff:ffff:ffff,AR +2800:d300::,2800:d307:ffff:ffff:ffff:ffff:ffff:ffff,CR +2801::,2801::ffff:ffff:ffff:ffff:ffff,UY +2801:0:10::,2801::10:ffff:ffff:ffff:ffff:ffff,CL +2801:0:20::,2801::20:ffff:ffff:ffff:ffff:ffff,EC +2801:0:30::,2801::30:ffff:ffff:ffff:ffff:ffff,HN +2801:0:40::,2801::40:ffff:ffff:ffff:ffff:ffff,TT +2801:0:50::,2801::50:ffff:ffff:ffff:ffff:ffff,CL +2801:0:60::,2801::63:ffff:ffff:ffff:ffff:ffff,EC +2801:0:70::,2801::70:ffff:ffff:ffff:ffff:ffff,CO +2801:0:80::,2801::80:ffff:ffff:ffff:ffff:ffff,DO +2801:0:90::,2801::90:ffff:ffff:ffff:ffff:ffff,AR +2801:0:a0::,2801::a0:ffff:ffff:ffff:ffff:ffff,AR +2801:0:b0::,2801::b7:ffff:ffff:ffff:ffff:ffff,CL +2801:0:c0::,2801::df:ffff:ffff:ffff:ffff:ffff,CR +2801:0:100::,2801::100:ffff:ffff:ffff:ffff:ffff,CO +2801:0:110::,2801::110:ffff:ffff:ffff:ffff:ffff,GT +2801:0:120::,2801::120:ffff:ffff:ffff:ffff:ffff,CL +2801:0:130::,2801::130:ffff:ffff:ffff:ffff:ffff,PY +2801:0:140::,2801::140:ffff:ffff:ffff:ffff:ffff,AR +2801:0:150::,2801::150:ffff:ffff:ffff:ffff:ffff,CL +2801:0:160::,2801::160:ffff:ffff:ffff:ffff:ffff,AR +2801:0:170::,2801::170:ffff:ffff:ffff:ffff:ffff,BO +2801:0:180::,2801::180:ffff:ffff:ffff:ffff:ffff,CO +2801:0:190::,2801::190:ffff:ffff:ffff:ffff:ffff,AR +2801:0:1a0::,2801::1a0:ffff:ffff:ffff:ffff:ffff,HN +2801:0:1b0::,2801::1b0:ffff:ffff:ffff:ffff:ffff,AR +2801:0:1c0::,2801::1c7:ffff:ffff:ffff:ffff:ffff,CO +2801:0:1d0::,2801::1d7:ffff:ffff:ffff:ffff:ffff,AR +2801:0:1e0::,2801::1e0:ffff:ffff:ffff:ffff:ffff,CO +2801:0:1f0::,2801::1f0:ffff:ffff:ffff:ffff:ffff,PY +2801:0:200::,2801::200:ffff:ffff:ffff:ffff:ffff,VE +2801:0:210::,2801::210:ffff:ffff:ffff:ffff:ffff,CO +2801:0:220::,2801::22f:ffff:ffff:ffff:ffff:ffff,AR +2801:0:240::,2801::240:ffff:ffff:ffff:ffff:ffff,PA +2801:0:250::,2801::250:ffff:ffff:ffff:ffff:ffff,AR +2801:0:260::,2801::260:ffff:ffff:ffff:ffff:ffff,AR +2801:0:270::,2801::270:ffff:ffff:ffff:ffff:ffff,EC +2801:0:280::,2801::280:ffff:ffff:ffff:ffff:ffff,CO +2801:0:290::,2801::290:ffff:ffff:ffff:ffff:ffff,AR +2801:0:2a0::,2801::2a0:ffff:ffff:ffff:ffff:ffff,CR +2801:0:2b0::,2801::2b0:ffff:ffff:ffff:ffff:ffff,PA +2801:0:2c0::,2801::2c0:ffff:ffff:ffff:ffff:ffff,HN +2801:0:2d0::,2801::2d0:ffff:ffff:ffff:ffff:ffff,PA +2801:0:2e0::,2801::2e0:ffff:ffff:ffff:ffff:ffff,CO +2801:0:2f0::,2801::2f0:ffff:ffff:ffff:ffff:ffff,AR +2801:0:300::,2801::300:ffff:ffff:ffff:ffff:ffff,CO +2801:0:310::,2801::310:ffff:ffff:ffff:ffff:ffff,CW +2801:0:320::,2801::320:ffff:ffff:ffff:ffff:ffff,CO +2801:0:330::,2801::330:ffff:ffff:ffff:ffff:ffff,HT +2801:0:340::,2801::340:ffff:ffff:ffff:ffff:ffff,CO +2801:0:350::,2801::350:ffff:ffff:ffff:ffff:ffff,AR +2801:0:360::,2801::360:ffff:ffff:ffff:ffff:ffff,CO +2801:0:370::,2801::370:ffff:ffff:ffff:ffff:ffff,CO +2801:0:380::,2801::380:ffff:ffff:ffff:ffff:ffff,CL +2801:0:390::,2801::390:ffff:ffff:ffff:ffff:ffff,CO +2801:0:3b0::,2801::3b0:ffff:ffff:ffff:ffff:ffff,CO +2801:0:3c0::,2801::3c0:ffff:ffff:ffff:ffff:ffff,CO +2801:0:3d0::,2801::3d0:ffff:ffff:ffff:ffff:ffff,CO +2801:0:3e0::,2801::3e0:ffff:ffff:ffff:ffff:ffff,AR +2801:0:3f0::,2801::3f0:ffff:ffff:ffff:ffff:ffff,AR +2801:0:400::,2801::400:ffff:ffff:ffff:ffff:ffff,CL +2801:0:410::,2801::410:ffff:ffff:ffff:ffff:ffff,EC +2801:0:420::,2801::420:ffff:ffff:ffff:ffff:ffff,EC +2801:0:440::,2801::440:ffff:ffff:ffff:ffff:ffff,AR +2801:0:480::,2801::480:ffff:ffff:ffff:ffff:ffff,CO +2801:0:490::,2801::490:ffff:ffff:ffff:ffff:ffff,PA +2801:0:4a0::,2801::4a0:ffff:ffff:ffff:ffff:ffff,CR +2801:0:4c0::,2801::4c0:ffff:ffff:ffff:ffff:ffff,CO +2801:0:4d0::,2801::4d0:ffff:ffff:ffff:ffff:ffff,EC +2801:0:4e0::,2801::4e0:ffff:ffff:ffff:ffff:ffff,CL +2801:0:4f0::,2801::4f0:ffff:ffff:ffff:ffff:ffff,CO +2801:0:2000::,2801::2fff:ffff:ffff:ffff:ffff:ffff,UY +2801:1::,2801:1:ffff:ffff:ffff:ffff:ffff:ffff,CR +2801:2::,2801:2:ffff:ffff:ffff:ffff:ffff:ffff,CL +2801:10::,2801:10:7:ffff:ffff:ffff:ffff:ffff,AR +2801:10:2000::,2801:10:2000:ffff:ffff:ffff:ffff:ffff,AR +2801:10:4000::,2801:10:4000:ffff:ffff:ffff:ffff:ffff,AR +2801:10:8000::,2801:10:8000:ffff:ffff:ffff:ffff:ffff,AR +2801:10:c000::,2801:10:c000:ffff:ffff:ffff:ffff:ffff,CO +2801:11::,2801:11::ffff:ffff:ffff:ffff:ffff,AR +2801:11:2000::,2801:11:2000:ffff:ffff:ffff:ffff:ffff,AR +2801:11:4000::,2801:11:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:11:8000::,2801:11:8000:ffff:ffff:ffff:ffff:ffff,CO +2801:11:c000::,2801:11:c000:ffff:ffff:ffff:ffff:ffff,AR +2801:12::,2801:12::ffff:ffff:ffff:ffff:ffff,PY +2801:12:2000::,2801:12:2000:ffff:ffff:ffff:ffff:ffff,HN +2801:12:4000::,2801:12:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:12:8000::,2801:12:8000:ffff:ffff:ffff:ffff:ffff,AR +2801:12:c000::,2801:12:c000:ffff:ffff:ffff:ffff:ffff,AR +2801:13::,2801:13::ffff:ffff:ffff:ffff:ffff,VE +2801:13:4000::,2801:13:4000:ffff:ffff:ffff:ffff:ffff,CL +2801:13:8000::,2801:13:8000:ffff:ffff:ffff:ffff:ffff,SV +2801:13:c000::,2801:13:c000:ffff:ffff:ffff:ffff:ffff,TT +2801:14::,2801:14::ffff:ffff:ffff:ffff:ffff,CO +2801:14:2000::,2801:14:2000:ffff:ffff:ffff:ffff:ffff,AR +2801:14:4000::,2801:14:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:14:c000::,2801:14:c000:ffff:ffff:ffff:ffff:ffff,BO +2801:15::,2801:15::ffff:ffff:ffff:ffff:ffff,EC +2801:15:4000::,2801:15:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:15:8000::,2801:15:8000:ffff:ffff:ffff:ffff:ffff,CR +2801:15:c000::,2801:15:c000:ffff:ffff:ffff:ffff:ffff,GT +2801:16::,2801:16::ffff:ffff:ffff:ffff:ffff,CW +2801:16:2000::,2801:16:2000:ffff:ffff:ffff:ffff:ffff,HN +2801:16:4000::,2801:16:4000:ffff:ffff:ffff:ffff:ffff,AR +2801:16:8000::,2801:16:8000:ffff:ffff:ffff:ffff:ffff,CO +2801:16:c000::,2801:16:c000:ffff:ffff:ffff:ffff:ffff,AR +2801:17::,2801:17::ffff:ffff:ffff:ffff:ffff,CL +2801:17:4000::,2801:17:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:17:8000::,2801:17:8000:ffff:ffff:ffff:ffff:ffff,CR +2801:17:c000::,2801:17:c000:ffff:ffff:ffff:ffff:ffff,PA +2801:18::,2801:18::ffff:ffff:ffff:ffff:ffff,CR +2801:18:2000::,2801:18:2000:ffff:ffff:ffff:ffff:ffff,CO +2801:18:4000::,2801:18:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:18:8000::,2801:18:8000:ffff:ffff:ffff:ffff:ffff,AR +2801:18:c000::,2801:18:c000:ffff:ffff:ffff:ffff:ffff,AR +2801:19::,2801:19::ffff:ffff:ffff:ffff:ffff,AR +2801:19:2000::,2801:19:2000:ffff:ffff:ffff:ffff:ffff,CL +2801:19:4000::,2801:19:4000:ffff:ffff:ffff:ffff:ffff,PY +2801:19:8000::,2801:19:8000:ffff:ffff:ffff:ffff:ffff,EC +2801:19:c000::,2801:19:c000:ffff:ffff:ffff:ffff:ffff,AR +2801:1a::,2801:1a::ffff:ffff:ffff:ffff:ffff,CO +2801:1a:2000::,2801:1a:2000:ffff:ffff:ffff:ffff:ffff,AR +2801:1a:4000::,2801:1a:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:1a:8000::,2801:1a:8000:ffff:ffff:ffff:ffff:ffff,CL +2801:1a:c000::,2801:1a:c000:ffff:ffff:ffff:ffff:ffff,CO +2801:1b::,2801:1b::ffff:ffff:ffff:ffff:ffff,CR +2801:1b:4000::,2801:1b:4000:ffff:ffff:ffff:ffff:ffff,CL +2801:1b:8000::,2801:1b:8000:ffff:ffff:ffff:ffff:ffff,CL +2801:1b:c000::,2801:1b:c000:ffff:ffff:ffff:ffff:ffff,PA +2801:1c::,2801:1c::ffff:ffff:ffff:ffff:ffff,PY +2801:1c:2000::,2801:1c:2000:ffff:ffff:ffff:ffff:ffff,PE +2801:1c:4000::,2801:1c:4000:ffff:ffff:ffff:ffff:ffff,CO +2801:1c:8000::,2801:1c:8000:ffff:ffff:ffff:ffff:ffff,EC +2801:1c:c000::,2801:1c:c000:ffff:ffff:ffff:ffff:ffff,HN +2801:1d::,2801:1d::ffff:ffff:ffff:ffff:ffff,PY +2801:1d:4000::,2801:1d:4000:ffff:ffff:ffff:ffff:ffff,TT +2801:1d:8000::,2801:1d:8000:ffff:ffff:ffff:ffff:ffff,AR +2801:1d:c000::,2801:1d:c000:ffff:ffff:ffff:ffff:ffff,AR +2801:1e::,2801:1e::ffff:ffff:ffff:ffff:ffff,EC +2801:1e:2000::,2801:1e:2000:ffff:ffff:ffff:ffff:ffff,AR +2801:1e:4000::,2801:1e:4007:ffff:ffff:ffff:ffff:ffff,AR +2801:1e:8000::,2801:1e:8000:ffff:ffff:ffff:ffff:ffff,CR +2801:1e:c000::,2801:1e:c000:ffff:ffff:ffff:ffff:ffff,AR +2801:1f::,2801:1f::ffff:ffff:ffff:ffff:ffff,AR +2801:1f:4000::,2801:1f:4000:ffff:ffff:ffff:ffff:ffff,CR +2801:1f:8000::,2801:1f:8000:ffff:ffff:ffff:ffff:ffff,AR +2801:1f:c000::,2801:1f:c000:ffff:ffff:ffff:ffff:ffff,CR +2801:80::,2801:80::ffff:ffff:ffff:ffff:ffff,BR +2801:80:10::,2801:80:10:ffff:ffff:ffff:ffff:ffff,BR +2801:80:20::,2801:80:30:ffff:ffff:ffff:ffff:ffff,BR +2801:80:40::,2801:80:40:ffff:ffff:ffff:ffff:ffff,BR +2801:80:50::,2801:80:50:ffff:ffff:ffff:ffff:ffff,BR +2801:80:60::,2801:80:60:ffff:ffff:ffff:ffff:ffff,BR +2801:80:70::,2801:80:70:ffff:ffff:ffff:ffff:ffff,BR +2801:80:80::,2801:80:80:ffff:ffff:ffff:ffff:ffff,BR +2801:80:90::,2801:80:90:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a0::,2801:80:a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:b0::,2801:80:b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:c0::,2801:80:c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:d0::,2801:80:d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:e0::,2801:80:e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:f0::,2801:80:f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:100::,2801:80:100:ffff:ffff:ffff:ffff:ffff,BR +2801:80:110::,2801:80:110:ffff:ffff:ffff:ffff:ffff,BR +2801:80:120::,2801:80:120:ffff:ffff:ffff:ffff:ffff,BR +2801:80:130::,2801:80:130:ffff:ffff:ffff:ffff:ffff,BR +2801:80:140::,2801:80:140:ffff:ffff:ffff:ffff:ffff,BR +2801:80:150::,2801:80:150:ffff:ffff:ffff:ffff:ffff,BR +2801:80:160::,2801:80:160:ffff:ffff:ffff:ffff:ffff,BR +2801:80:170::,2801:80:170:ffff:ffff:ffff:ffff:ffff,BR +2801:80:180::,2801:80:180:ffff:ffff:ffff:ffff:ffff,BR +2801:80:190::,2801:80:190:ffff:ffff:ffff:ffff:ffff,BR +2801:80:1a0::,2801:80:1a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:1b0::,2801:80:1b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:1c0::,2801:80:1c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:1d0::,2801:80:1d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:1e0::,2801:80:1e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:1f0::,2801:80:1f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:200::,2801:80:200:ffff:ffff:ffff:ffff:ffff,BR +2801:80:210::,2801:80:210:ffff:ffff:ffff:ffff:ffff,BR +2801:80:220::,2801:80:220:ffff:ffff:ffff:ffff:ffff,BR +2801:80:230::,2801:80:230:ffff:ffff:ffff:ffff:ffff,BR +2801:80:240::,2801:80:240:ffff:ffff:ffff:ffff:ffff,BR +2801:80:250::,2801:80:250:ffff:ffff:ffff:ffff:ffff,BR +2801:80:260::,2801:80:260:ffff:ffff:ffff:ffff:ffff,BR +2801:80:270::,2801:80:270:ffff:ffff:ffff:ffff:ffff,BR +2801:80:280::,2801:80:280:ffff:ffff:ffff:ffff:ffff,BR +2801:80:290::,2801:80:290:ffff:ffff:ffff:ffff:ffff,BR +2801:80:2a0::,2801:80:2a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:2b0::,2801:80:2b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:2c0::,2801:80:2c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:2d0::,2801:80:2d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:2e0::,2801:80:2e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:2f0::,2801:80:2f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:300::,2801:80:300:ffff:ffff:ffff:ffff:ffff,BR +2801:80:320::,2801:80:320:ffff:ffff:ffff:ffff:ffff,BR +2801:80:330::,2801:80:330:ffff:ffff:ffff:ffff:ffff,BR +2801:80:340::,2801:80:340:ffff:ffff:ffff:ffff:ffff,BR +2801:80:350::,2801:80:350:ffff:ffff:ffff:ffff:ffff,BR +2801:80:360::,2801:80:360:ffff:ffff:ffff:ffff:ffff,BR +2801:80:370::,2801:80:370:ffff:ffff:ffff:ffff:ffff,BR +2801:80:380::,2801:80:380:ffff:ffff:ffff:ffff:ffff,BR +2801:80:390::,2801:80:390:ffff:ffff:ffff:ffff:ffff,BR +2801:80:3a0::,2801:80:3a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:3b0::,2801:80:3b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:3c0::,2801:80:3c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:3d0::,2801:80:3d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:3e0::,2801:80:3e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:3f0::,2801:80:3f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:400::,2801:80:400:ffff:ffff:ffff:ffff:ffff,BR +2801:80:410::,2801:80:410:ffff:ffff:ffff:ffff:ffff,BR +2801:80:420::,2801:80:420:ffff:ffff:ffff:ffff:ffff,BR +2801:80:430::,2801:80:430:ffff:ffff:ffff:ffff:ffff,BR +2801:80:440::,2801:80:440:ffff:ffff:ffff:ffff:ffff,BR +2801:80:450::,2801:80:450:ffff:ffff:ffff:ffff:ffff,BR +2801:80:460::,2801:80:460:ffff:ffff:ffff:ffff:ffff,BR +2801:80:470::,2801:80:470:ffff:ffff:ffff:ffff:ffff,BR +2801:80:480::,2801:80:480:ffff:ffff:ffff:ffff:ffff,BR +2801:80:490::,2801:80:490:ffff:ffff:ffff:ffff:ffff,BR +2801:80:4a0::,2801:80:4a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:4b0::,2801:80:4b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:4c0::,2801:80:4c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:4d0::,2801:80:4d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:4e0::,2801:80:4e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:4f0::,2801:80:4f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:500::,2801:80:500:ffff:ffff:ffff:ffff:ffff,BR +2801:80:510::,2801:80:510:ffff:ffff:ffff:ffff:ffff,BR +2801:80:520::,2801:80:520:ffff:ffff:ffff:ffff:ffff,BR +2801:80:530::,2801:80:530:ffff:ffff:ffff:ffff:ffff,BR +2801:80:540::,2801:80:540:ffff:ffff:ffff:ffff:ffff,BR +2801:80:550::,2801:80:550:ffff:ffff:ffff:ffff:ffff,BR +2801:80:560::,2801:80:560:ffff:ffff:ffff:ffff:ffff,BR +2801:80:570::,2801:80:570:ffff:ffff:ffff:ffff:ffff,BR +2801:80:580::,2801:80:580:ffff:ffff:ffff:ffff:ffff,BR +2801:80:590::,2801:80:590:ffff:ffff:ffff:ffff:ffff,BR +2801:80:5a0::,2801:80:5a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:5b0::,2801:80:5b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:5c0::,2801:80:5c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:5d0::,2801:80:5d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:5e0::,2801:80:5e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:5f0::,2801:80:5f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:600::,2801:80:600:ffff:ffff:ffff:ffff:ffff,BR +2801:80:610::,2801:80:610:ffff:ffff:ffff:ffff:ffff,BR +2801:80:620::,2801:80:620:ffff:ffff:ffff:ffff:ffff,BR +2801:80:630::,2801:80:630:ffff:ffff:ffff:ffff:ffff,BR +2801:80:640::,2801:80:640:ffff:ffff:ffff:ffff:ffff,BR +2801:80:650::,2801:80:650:ffff:ffff:ffff:ffff:ffff,BR +2801:80:660::,2801:80:660:ffff:ffff:ffff:ffff:ffff,BR +2801:80:670::,2801:80:670:ffff:ffff:ffff:ffff:ffff,BR +2801:80:680::,2801:80:680:ffff:ffff:ffff:ffff:ffff,BR +2801:80:690::,2801:80:690:ffff:ffff:ffff:ffff:ffff,BR +2801:80:6a0::,2801:80:6a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:6b0::,2801:80:6b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:6c0::,2801:80:6c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:6d0::,2801:80:6d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:6e0::,2801:80:6ef:ffff:ffff:ffff:ffff:ffff,BR +2801:80:700::,2801:80:700:ffff:ffff:ffff:ffff:ffff,BR +2801:80:710::,2801:80:710:ffff:ffff:ffff:ffff:ffff,BR +2801:80:720::,2801:80:720:ffff:ffff:ffff:ffff:ffff,BR +2801:80:730::,2801:80:730:ffff:ffff:ffff:ffff:ffff,BR +2801:80:740::,2801:80:740:ffff:ffff:ffff:ffff:ffff,BR +2801:80:750::,2801:80:750:ffff:ffff:ffff:ffff:ffff,BR +2801:80:760::,2801:80:760:ffff:ffff:ffff:ffff:ffff,BR +2801:80:770::,2801:80:770:ffff:ffff:ffff:ffff:ffff,BR +2801:80:780::,2801:80:780:ffff:ffff:ffff:ffff:ffff,BR +2801:80:790::,2801:80:790:ffff:ffff:ffff:ffff:ffff,BR +2801:80:7a0::,2801:80:7a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:7b0::,2801:80:7b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:7c0::,2801:80:7c3:ffff:ffff:ffff:ffff:ffff,BR +2801:80:7d0::,2801:80:7d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:7e0::,2801:80:7e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:7f0::,2801:80:7f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:800::,2801:80:800:ffff:ffff:ffff:ffff:ffff,BR +2801:80:810::,2801:80:810:ffff:ffff:ffff:ffff:ffff,BR +2801:80:820::,2801:80:820:ffff:ffff:ffff:ffff:ffff,BR +2801:80:830::,2801:80:830:ffff:ffff:ffff:ffff:ffff,BR +2801:80:840::,2801:80:840:ffff:ffff:ffff:ffff:ffff,BR +2801:80:850::,2801:80:850:ffff:ffff:ffff:ffff:ffff,BR +2801:80:860::,2801:80:860:ffff:ffff:ffff:ffff:ffff,BR +2801:80:870::,2801:80:870:ffff:ffff:ffff:ffff:ffff,BR +2801:80:880::,2801:80:880:ffff:ffff:ffff:ffff:ffff,BR +2801:80:890::,2801:80:890:ffff:ffff:ffff:ffff:ffff,BR +2801:80:8a0::,2801:80:8a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:8b0::,2801:80:8b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:8c0::,2801:80:8c1:ffff:ffff:ffff:ffff:ffff,BR +2801:80:8d0::,2801:80:8d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:8e0::,2801:80:8e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:8f0::,2801:80:8f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:900::,2801:80:900:ffff:ffff:ffff:ffff:ffff,BR +2801:80:910::,2801:80:910:ffff:ffff:ffff:ffff:ffff,BR +2801:80:920::,2801:80:920:ffff:ffff:ffff:ffff:ffff,BR +2801:80:930::,2801:80:930:ffff:ffff:ffff:ffff:ffff,BR +2801:80:940::,2801:80:940:ffff:ffff:ffff:ffff:ffff,BR +2801:80:950::,2801:80:950:ffff:ffff:ffff:ffff:ffff,BR +2801:80:960::,2801:80:960:ffff:ffff:ffff:ffff:ffff,BR +2801:80:970::,2801:80:970:ffff:ffff:ffff:ffff:ffff,BR +2801:80:980::,2801:80:980:ffff:ffff:ffff:ffff:ffff,BR +2801:80:990::,2801:80:990:ffff:ffff:ffff:ffff:ffff,BR +2801:80:9a0::,2801:80:9a0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:9b0::,2801:80:9b0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:9c0::,2801:80:9c0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:9d0::,2801:80:9d0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:9e0::,2801:80:9e0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:9f0::,2801:80:9f0:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a00::,2801:80:a00:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a10::,2801:80:a10:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a20::,2801:80:a20:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a30::,2801:80:a30:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a40::,2801:80:a40:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a50::,2801:80:a50:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a60::,2801:80:a61:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a70::,2801:80:a70:ffff:ffff:ffff:ffff:ffff,BR +2801:80:a80::,2801:80:a8f:ffff:ffff:ffff:ffff:ffff,BR +2801:82::,2801:82:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:84::,2801:84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:86::,2801:86:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:88::,2801:88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:8a::,2801:8a:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:8c::,2801:8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:8e::,2801:8e:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:90::,2801:90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:92::,2801:92:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:94::,2801:94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:96::,2801:96:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:98::,2801:98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:9a::,2801:9a:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:9c::,2801:9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:9e::,2801:9e:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:a0::,2801:a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:a2::,2801:a2:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:a4::,2801:a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:a6::,2801:a6:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:a8::,2801:a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:aa::,2801:aa:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:ac::,2801:ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:ae::,2801:ae:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:b0::,2801:b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:b2::,2801:b2:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:b4::,2801:b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:b6::,2801:b6:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:b8::,2801:b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:ba::,2801:ba:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:bc::,2801:bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:be::,2801:be:ffff:ffff:ffff:ffff:ffff:ffff,BR +2801:c0::,2801:c0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2801:c4::,2801:c4::ffff:ffff:ffff:ffff:ffff,MX +2801:c4:10::,2801:c4:10:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:20::,2801:c4:20:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:30::,2801:c4:30:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:40::,2801:c4:40:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:50::,2801:c4:50:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:60::,2801:c4:60:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:80::,2801:c4:80:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:90::,2801:c4:90:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:a0::,2801:c4:a0:ffff:ffff:ffff:ffff:ffff,MX +2801:c4:b0::,2801:c4:b3:ffff:ffff:ffff:ffff:ffff,MX +2801:d0::,2801:d0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2801:f0::,2801:f0::ffff:ffff:ffff:ffff:ffff,MX +2801:f0:16::,2801:f0:16:ffff:ffff:ffff:ffff:ffff,MX +2801:f0:20::,2801:f0:20:ffff:ffff:ffff:ffff:ffff,MX +2801:f0:28::,2801:f0:28:ffff:ffff:ffff:ffff:ffff,MX +2801:100::,2801:100:ff:ffff:ffff:ffff:ffff:ffff,AR +2801:110::,2801:110:1fff:ffff:ffff:ffff:ffff:ffff,CO +2801:120::,2801:120:ffff:ffff:ffff:ffff:ffff:ffff,AR +2801:130::,2801:130:fff:ffff:ffff:ffff:ffff:ffff,CO +2801:140::,2801:140:ffff:ffff:ffff:ffff:ffff:ffff,AR +2801:150::,2801:150:ffff:ffff:ffff:ffff:ffff:ffff,PE +2801:160::,2801:160:ff:ffff:ffff:ffff:ffff:ffff,CO +2801:180::,2801:180:f:ffff:ffff:ffff:ffff:ffff,PA +2801:190::,2801:190:fff:ffff:ffff:ffff:ffff:ffff,CO +2801:1a0::,2801:1a0:3f:ffff:ffff:ffff:ffff:ffff,CO +2801:1c0::,2801:1c0:1ff:ffff:ffff:ffff:ffff:ffff,AR +2801:1d0::,2801:1d0:f:ffff:ffff:ffff:ffff:ffff,CO +2801:1e0::,2801:1e0:7f:ffff:ffff:ffff:ffff:ffff,AR +2802::,2802:3:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803::,2803::ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:80::,2803:80:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:100::,2803:100:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:180::,2803:180:ffff:ffff:ffff:ffff:ffff:ffff,NI +2803:200::,2803:200:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:280::,2803:280:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:300::,2803:300:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:400::,2803:400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:480::,2803:480:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:500::,2803:500:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:600::,2803:600:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:680::,2803:680:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:700::,2803:700:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:800::,2803:800:ffff:ffff:ffff:ffff:ffff:ffff,NI +2803:880::,2803:880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:900::,2803:900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a00::,2803:a00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a80::,2803:a80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:b00::,2803:b00:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:c00::,2803:c00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:c80::,2803:c80:ffff:ffff:ffff:ffff:ffff:ffff,PY +2803:d00::,2803:d00:ffff:ffff:ffff:ffff:ffff:ffff,GY +2803:e00::,2803:e00:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:e80::,2803:e80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:f00::,2803:f00:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:1000::,2803:1000:ffff:ffff:ffff:ffff:ffff:ffff,SV +2803:1080::,2803:1080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1100::,2803:1100:ffff:ffff:ffff:ffff:ffff:ffff,CW +2803:1180::,2803:1180:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:1200::,2803:1200:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:1280::,2803:1280:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:1300::,2803:1300:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:1400::,2803:1400:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:1480::,2803:1480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1500::,2803:1500:ffff:ffff:ffff:ffff:ffff:ffff,TT +2803:1600::,2803:1600:ffff:ffff:ffff:ffff:ffff:ffff,BQ +2803:1680::,2803:1680:ffff:ffff:ffff:ffff:ffff:ffff,GF +2803:1700::,2803:1700:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1800::,2803:1800:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:1880::,2803:1880:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:1900::,2803:1900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1a00::,2803:1a00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:1a80::,2803:1a80:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:1b00::,2803:1b00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1c00::,2803:1c00:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:1c80::,2803:1c80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1d00::,2803:1d00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1e00::,2803:1e00:ffff:ffff:ffff:ffff:ffff:ffff,NI +2803:1e80::,2803:1e80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:1f00::,2803:1f00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2000::,2803:2000:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2080::,2803:2080:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:2100::,2803:2100:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:2180::,2803:2180:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:2200::,2803:2200:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:2280::,2803:2280:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:2300::,2803:2300:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2400::,2803:2400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2480::,2803:2480:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:2500::,2803:2500:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:2600::,2803:2600:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2680::,2803:2680:ffff:ffff:ffff:ffff:ffff:ffff,UY +2803:2700::,2803:2700:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2800::,2803:2800:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:2880::,2803:2880:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:2900::,2803:2900:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:2a00::,2803:2a00:ffff:ffff:ffff:ffff:ffff:ffff,PY +2803:2a80::,2803:2a80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:2b00::,2803:2b00:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:2c00::,2803:2c00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2c80::,2803:2c80:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:2d00::,2803:2d00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2e00::,2803:2e00:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:2e80::,2803:2e80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:2f00::,2803:2f00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:3000::,2803:3000:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:3080::,2803:3080:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:3100::,2803:3100:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:3200::,2803:3200:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:3280::,2803:3280:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:3300::,2803:3300:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:3400::,2803:3400:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:3480::,2803:3480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:3500::,2803:3500:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:3600::,2803:3600:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:3680::,2803:3680:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:3700::,2803:3700:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:3800::,2803:3800:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:3880::,2803:3880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:3900::,2803:3900:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:3a00::,2803:3a00:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:3a80::,2803:3a80:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:3b00::,2803:3b00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:3c00::,2803:3c00:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:3c80::,2803:3c80:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:3d00::,2803:3d00:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:3e00::,2803:3e00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:3e80::,2803:3e80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:3f00::,2803:3f00:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:4000::,2803:4000:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4080::,2803:4080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4100::,2803:4100:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4180::,2803:4180:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:4200::,2803:4200:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:4280::,2803:4280:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4300::,2803:4300:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:4400::,2803:4400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4480::,2803:4480:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:4500::,2803:4500:ffff:ffff:ffff:ffff:ffff:ffff,CW +2803:4600::,2803:4600:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:4680::,2803:4680:ffff:ffff:ffff:ffff:ffff:ffff,TT +2803:4700::,2803:4700:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4800::,2803:4800:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:4880::,2803:4880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4900::,2803:4900:ffff:ffff:ffff:ffff:ffff:ffff,BQ +2803:4a00::,2803:4a00:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:4a80::,2803:4a80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4b00::,2803:4b00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4c00::,2803:4c00:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:4c80::,2803:4c80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:4d00::,2803:4d00:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:4e00::,2803:4e00:ffff:ffff:ffff:ffff:ffff:ffff,UY +2803:4e80::,2803:4e80:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:4f00::,2803:4f00:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:5000::,2803:5000:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5080::,2803:5080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5100::,2803:5100:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:5200::,2803:5200:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:5280::,2803:5280:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:5300::,2803:5300:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:5400::,2803:5400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5480::,2803:5480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5500::,2803:5500:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5600::,2803:5600:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:5680::,2803:5680:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:5700::,2803:5700:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:5880::,2803:5880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5900::,2803:5900:ffff:ffff:ffff:ffff:ffff:ffff,GY +2803:5a00::,2803:5a00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5a80::,2803:5a80:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:5b00::,2803:5b00:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:5c00::,2803:5c00:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:5c80::,2803:5c80:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:5d00::,2803:5d00:ffff:ffff:ffff:ffff:ffff:ffff,SV +2803:5e00::,2803:5e00:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:5e80::,2803:5e80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:5f00::,2803:5f00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6000::,2803:6000:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:6080::,2803:6080:ffff:ffff:ffff:ffff:ffff:ffff,US +2803:6100::,2803:6100:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6180::,2803:6180:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:6200::,2803:6200:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:6280::,2803:6280:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:6300::,2803:6300:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:6400::,2803:6400:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:6480::,2803:6480:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:6500::,2803:6500:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:6600::,2803:6600:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6680::,2803:6680:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:6700::,2803:6700:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:6800::,2803:6800:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6880::,2803:6880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6900::,2803:6900:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:6a00::,2803:6a00:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:6a80::,2803:6a80:ffff:ffff:ffff:ffff:ffff:ffff,NI +2803:6b00::,2803:6b00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6c00::,2803:6c00:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:6c80::,2803:6c80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6d00::,2803:6d00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:6e00::,2803:6e00:ffff:ffff:ffff:ffff:ffff:ffff,SR +2803:6e80::,2803:6e80:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:6f00::,2803:6f00:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:7000::,2803:7000:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:7080::,2803:7080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7100::,2803:7100:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7200::,2803:7200:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:7280::,2803:7280:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:7300::,2803:7300:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7400::,2803:7400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7480::,2803:7480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7500::,2803:7500:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:7600::,2803:7600:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7680::,2803:7680:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:7700::,2803:7700:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7800::,2803:7800:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:7880::,2803:7880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7900::,2803:7900:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:7a00::,2803:7a00:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:7a80::,2803:7a80:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:7b00::,2803:7b00:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:7c00::,2803:7c00:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:7c80::,2803:7c80:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:7d00::,2803:7d00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7e00::,2803:7e00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7e80::,2803:7e80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:7f00::,2803:7f00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:8000::,2803:8000:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8080::,2803:8080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8100::,2803:8100:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:8180::,2803:8180:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:8200::,2803:8200:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:8280::,2803:8280:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:8300::,2803:8300:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:8400::,2803:8400:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:8480::,2803:8480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8500::,2803:8500:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8600::,2803:8600:ffff:ffff:ffff:ffff:ffff:ffff,HT +2803:8680::,2803:8680:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8700::,2803:8700:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:8800::,2803:8800:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:8880::,2803:8880:ffff:ffff:ffff:ffff:ffff:ffff,NI +2803:8900::,2803:8900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8a00::,2803:8a00:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:8a80::,2803:8a80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8b00::,2803:8b00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:8c00::,2803:8c00:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:8c80::,2803:8c80:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:8d00::,2803:8d00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:8e00::,2803:8e00:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:8e80::,2803:8e80:ffff:ffff:ffff:ffff:ffff:ffff,PY +2803:8f00::,2803:8f00:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:9000::,2803:9000:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9080::,2803:9080:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:9100::,2803:9100:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9180::,2803:9180:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:9200::,2803:9200:ffff:ffff:ffff:ffff:ffff:ffff,SV +2803:9280::,2803:9280:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9300::,2803:9300:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9400::,2803:9400:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:9480::,2803:9480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9500::,2803:9500:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9600::,2803:9600:ffff:ffff:ffff:ffff:ffff:ffff,CW +2803:9680::,2803:9680:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9700::,2803:9700:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:9800::,2803:9800:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9880::,2803:9880:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:9900::,2803:9900:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:9a00::,2803:9a00:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:9a80::,2803:9a80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:9b00::,2803:9b00:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:9c00::,2803:9c00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9c80::,2803:9c80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9d00::,2803:9d00:ffff:ffff:ffff:ffff:ffff:ffff,SV +2803:9e00::,2803:9e00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:9e80::,2803:9e80:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:9f00::,2803:9f00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a000::,2803:a000:ffff:ffff:ffff:ffff:ffff:ffff,BQ +2803:a080::,2803:a080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a100::,2803:a100:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:a180::,2803:a180:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:a200::,2803:a200:ffff:ffff:ffff:ffff:ffff:ffff,SR +2803:a280::,2803:a280:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:a300::,2803:a300:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:a400::,2803:a400:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:a480::,2803:a480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a500::,2803:a500:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a600::,2803:a600:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a680::,2803:a680:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a700::,2803:a700:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:a800::,2803:a800:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:a880::,2803:a880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:a900::,2803:a900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:aa00::,2803:aa00:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:aa80::,2803:aa80:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:ab00::,2803:ab00:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:ac00::,2803:ac00:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:ac80::,2803:ac80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:ad00::,2803:ad00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ae00::,2803:ae00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ae80::,2803:ae80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:af00::,2803:af00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:b000::,2803:b000:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:b080::,2803:b080:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:b100::,2803:b100:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:b200::,2803:b200:ffff:ffff:ffff:ffff:ffff:ffff,UY +2803:b280::,2803:b280:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:b300::,2803:b300:ffff:ffff:ffff:ffff:ffff:ffff,PY +2803:b400::,2803:b400:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:b480::,2803:b480:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:b500::,2803:b500:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:b600::,2803:b600:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:b680::,2803:b680:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:b700::,2803:b700:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:b800::,2803:b800:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:b880::,2803:b880:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:b900::,2803:b900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ba00::,2803:ba00:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:ba80::,2803:ba80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:bb00::,2803:bb00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:bc00::,2803:bc00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:bc80::,2803:bc80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:bd00::,2803:bd00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:be00::,2803:be00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:be80::,2803:be80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:bf00::,2803:bf00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:c000::,2803:c000:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:c080::,2803:c080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:c100::,2803:c100:ffff:ffff:ffff:ffff:ffff:ffff,PY +2803:c180::,2803:c180:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:c200::,2803:c200:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:c280::,2803:c280:ffff:ffff:ffff:ffff:ffff:ffff,EC +2803:c300::,2803:c300:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:c400::,2803:c400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:c480::,2803:c480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:c500::,2803:c500:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:c600::,2803:c600:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:c680::,2803:c680:ffff:ffff:ffff:ffff:ffff:ffff,HT +2803:c700::,2803:c700:ffff:ffff:ffff:ffff:ffff:ffff,GF +2803:c800::,2803:c800:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:c880::,2803:c880:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:c900::,2803:c900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ca00::,2803:ca00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ca80::,2803:ca80:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:cb00::,2803:cb00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:cc00::,2803:cc00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:cc80::,2803:cc80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:cd00::,2803:cd00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ce00::,2803:ce00:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:ce80::,2803:ce80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:cf00::,2803:cf00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:d000::,2803:d000:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:d080::,2803:d080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:d100::,2803:d100:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:d200::,2803:d200:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:d280::,2803:d280:ffff:ffff:ffff:ffff:ffff:ffff,PY +2803:d300::,2803:d300:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:d400::,2803:d400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:d480::,2803:d480:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:d500::,2803:d500:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:d600::,2803:d600:ffff:ffff:ffff:ffff:ffff:ffff,UY +2803:d680::,2803:d680:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:d700::,2803:d700:ffff:ffff:ffff:ffff:ffff:ffff,VE +2803:d800::,2803:d800:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:d880::,2803:d880:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:d900::,2803:d900:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:da00::,2803:da00:ffff:ffff:ffff:ffff:ffff:ffff,GY +2803:da80::,2803:da80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:db00::,2803:db00:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:dc00::,2803:dc00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:dc80::,2803:dc80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:dd00::,2803:dd00:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:de00::,2803:de00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:de80::,2803:de80:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:df00::,2803:df00:ffff:ffff:ffff:ffff:ffff:ffff,SV +2803:e000::,2803:e000:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:e080::,2803:e080:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:e100::,2803:e100:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:e180::,2803:e180:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:e200::,2803:e200:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:e280::,2803:e280:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:e300::,2803:e300:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:e400::,2803:e400:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:e480::,2803:e480:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:e500::,2803:e500:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:e600::,2803:e600:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:e680::,2803:e680:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:e700::,2803:e700:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:e800::,2803:e800:ffff:ffff:ffff:ffff:ffff:ffff,CL +2803:e880::,2803:e880:ffff:ffff:ffff:ffff:ffff:ffff,GT +2803:e900::,2803:e900:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ea00::,2803:ea00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ea80::,2803:ea80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:eb00::,2803:eb00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ec00::,2803:ec00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ec80::,2803:ec80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ed00::,2803:ed00:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:ee00::,2803:ee00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ee80::,2803:ee80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:ef00::,2803:ef00:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:f000::,2803:f000:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:f080::,2803:f080:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:f100::,2803:f100:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:f200::,2803:f200:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:f280::,2803:f280:ffff:ffff:ffff:ffff:ffff:ffff,DO +2803:f300::,2803:f300:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:f400::,2803:f400:ffff:ffff:ffff:ffff:ffff:ffff,HN +2803:f480::,2803:f480:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:f500::,2803:f500:ffff:ffff:ffff:ffff:ffff:ffff,CW +2803:f600::,2803:f600:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:f680::,2803:f680:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:f700::,2803:f700:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:f800::,2803:f800:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:f880::,2803:f880:ffff:ffff:ffff:ffff:ffff:ffff,CR +2803:f900::,2803:f900:ffff:ffff:ffff:ffff:ffff:ffff,BZ +2803:fa00::,2803:fa00:ffff:ffff:ffff:ffff:ffff:ffff,BO +2803:fa80::,2803:fa80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:fb00::,2803:fb00:ffff:ffff:ffff:ffff:ffff:ffff,PA +2803:fc80::,2803:fc80:ffff:ffff:ffff:ffff:ffff:ffff,AR +2803:fd00::,2803:fd00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:fe00::,2803:fe00:ffff:ffff:ffff:ffff:ffff:ffff,CO +2803:fe80::,2803:fe80:ffff:ffff:ffff:ffff:ffff:ffff,PE +2803:ff00::,2803:ff00:ffff:ffff:ffff:ffff:ffff:ffff,AR +2804::,2804::ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4::,2804:4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8::,2804:c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10::,2804:10:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14::,2804:14:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:18::,2804:18:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1c::,2804:1c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:20::,2804:20:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:24::,2804:24:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:28::,2804:28:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2c::,2804:2c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:30::,2804:30:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:34::,2804:34:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:38::,2804:38:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3c::,2804:3c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:40::,2804:40:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:44::,2804:44:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:48::,2804:48:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4c::,2804:4c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:50::,2804:50:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:54::,2804:54:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:58::,2804:58:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5c::,2804:5c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:60::,2804:60:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:64::,2804:64:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:68::,2804:68:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6c::,2804:6c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:70::,2804:70:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:74::,2804:74:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:78::,2804:78:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7c::,2804:7c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:80::,2804:80:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:84::,2804:84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:88::,2804:88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8c::,2804:8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:90::,2804:90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:94::,2804:94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:98::,2804:98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9c::,2804:9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a0::,2804:a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a4::,2804:a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a8::,2804:a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ac::,2804:ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b0::,2804:b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b4::,2804:b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b8::,2804:b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c0::,2804:c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c4::,2804:c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c8::,2804:c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cc::,2804:cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d0::,2804:d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d4::,2804:d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d8::,2804:d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dc::,2804:dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e0::,2804:e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e4::,2804:e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e8::,2804:e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ec::,2804:ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f0::,2804:f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f4::,2804:f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f8::,2804:f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fc::,2804:fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:100::,2804:100:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:104::,2804:104:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:108::,2804:108:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10c::,2804:10c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:110::,2804:110:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:114::,2804:114:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:118::,2804:118:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11c::,2804:11c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:120::,2804:120:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:124::,2804:124:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:128::,2804:128:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12c::,2804:12c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:130::,2804:130:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:134::,2804:134:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:138::,2804:138:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13c::,2804:13c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:140::,2804:140:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:144::,2804:144:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:148::,2804:148:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14c::,2804:14d:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:150::,2804:154:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:158::,2804:158:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15c::,2804:15c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:160::,2804:160:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:164::,2804:164:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:168::,2804:168:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16c::,2804:16c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:170::,2804:170:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:174::,2804:174:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:178::,2804:178:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17c::,2804:17c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:180::,2804:180:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:184::,2804:184:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:188::,2804:188:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:18c::,2804:18c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:190::,2804:190:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:194::,2804:194:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:198::,2804:198:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:19c::,2804:19c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1a0::,2804:1a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1a4::,2804:1a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1a8::,2804:1a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1ac::,2804:1ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1b0::,2804:1b1:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1b8::,2804:1b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1bc::,2804:1bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1c0::,2804:1c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1c4::,2804:1c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1c8::,2804:1c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1cc::,2804:1cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1d0::,2804:1d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1d4::,2804:1d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1d8::,2804:1d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1dc::,2804:1dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1e0::,2804:1e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1e4::,2804:1e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1e8::,2804:1e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1ec::,2804:1ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f0::,2804:1f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f4::,2804:1f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f8::,2804:1f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1fc::,2804:1fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:200::,2804:200:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:204::,2804:204:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:208::,2804:208:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:20c::,2804:20c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:210::,2804:210:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:214::,2804:214:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:218::,2804:218:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:220::,2804:220:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:224::,2804:224:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:228::,2804:228:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:22c::,2804:22c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:230::,2804:230:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:234::,2804:234:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:238::,2804:238:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:23c::,2804:23c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:240::,2804:240:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:244::,2804:244:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:248::,2804:248:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:24c::,2804:24c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:250::,2804:250:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:254::,2804:254:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:258::,2804:258:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:25c::,2804:25c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:260::,2804:260:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:268::,2804:268:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:26c::,2804:26c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:270::,2804:270:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:274::,2804:274:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:27c::,2804:27c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:280::,2804:280:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:284::,2804:284:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:288::,2804:288:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:28c::,2804:28c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:290::,2804:290:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:294::,2804:294:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:298::,2804:298:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:29c::,2804:29c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2a0::,2804:2a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2a4::,2804:2a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2a8::,2804:2a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2ac::,2804:2ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2b0::,2804:2b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2b4::,2804:2b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2b8::,2804:2b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2bc::,2804:2bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2c0::,2804:2c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2c4::,2804:2c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2c8::,2804:2c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2cc::,2804:2cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2d0::,2804:2d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2d4::,2804:2d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2d8::,2804:2d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2dc::,2804:2dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2e0::,2804:2e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2e4::,2804:2e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2e8::,2804:2e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2ec::,2804:2ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2f0::,2804:2f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2f4::,2804:2f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2f8::,2804:2f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:2fc::,2804:2fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:300::,2804:303:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:308::,2804:308:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:30c::,2804:30c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:310::,2804:310:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:314::,2804:314:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:318::,2804:318:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:31c::,2804:31c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:320::,2804:320:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:324::,2804:324:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:328::,2804:328:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:32c::,2804:32c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:330::,2804:330:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:334::,2804:334:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:338::,2804:338:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:33c::,2804:33c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:340::,2804:340:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:344::,2804:344:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:348::,2804:348:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:350::,2804:350:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:354::,2804:354:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:358::,2804:358:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:35c::,2804:35c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:360::,2804:360:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:364::,2804:364:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:368::,2804:368:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:36c::,2804:36c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:370::,2804:370:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:374::,2804:374:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:378::,2804:378:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:37c::,2804:37c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:380::,2804:380:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:384::,2804:384:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:388::,2804:38b:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:390::,2804:390:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:394::,2804:394:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:398::,2804:398:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:39c::,2804:39c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3a0::,2804:3a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3a4::,2804:3a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3a8::,2804:3a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3ac::,2804:3ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3b0::,2804:3b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3b4::,2804:3b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3b8::,2804:3b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3bc::,2804:3bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3c0::,2804:3c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3c4::,2804:3c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3c8::,2804:3c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3cc::,2804:3cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3d0::,2804:3d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3d4::,2804:3d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3d8::,2804:3d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3dc::,2804:3dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3e0::,2804:3e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3e4::,2804:3e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3e8::,2804:3e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3ec::,2804:3ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3f0::,2804:3f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3f4::,2804:3f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3f8::,2804:3f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:3fc::,2804:3fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:400::,2804:400:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:404::,2804:404:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:40c::,2804:40c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:410::,2804:410:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:414::,2804:414:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:418::,2804:418:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:41c::,2804:41c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:420::,2804:420:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:424::,2804:424:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:428::,2804:428:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:430::,2804:431:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:438::,2804:438:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:43c::,2804:43c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:440::,2804:440:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:444::,2804:444:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:448::,2804:448:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:44c::,2804:44c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:450::,2804:450:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:454::,2804:454:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:458::,2804:458:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:45c::,2804:45c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:460::,2804:460:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:464::,2804:464:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:468::,2804:468:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:46c::,2804:46c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:470::,2804:470:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:474::,2804:474:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:478::,2804:478:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:47c::,2804:47c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:480::,2804:480:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:484::,2804:484:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:488::,2804:488:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:48c::,2804:48c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:490::,2804:490:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:494::,2804:494:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:498::,2804:498:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:49c::,2804:49c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4a0::,2804:4a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4a4::,2804:4a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4a8::,2804:4a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4ac::,2804:4ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4b0::,2804:4b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4b4::,2804:4b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4b8::,2804:4b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4bc::,2804:4bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4c0::,2804:4c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4c4::,2804:4c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4c8::,2804:4c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4cc::,2804:4cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4d0::,2804:4d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4d4::,2804:4d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4d8::,2804:4d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4dc::,2804:4dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4e0::,2804:4e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4e4::,2804:4e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4e8::,2804:4e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4ec::,2804:4ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4f0::,2804:4f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4f4::,2804:4f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4f8::,2804:4f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:4fc::,2804:4fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:500::,2804:500:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:504::,2804:504:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:508::,2804:508:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:50c::,2804:50c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:510::,2804:510:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:514::,2804:514:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:518::,2804:518:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:51c::,2804:51c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:520::,2804:520:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:528::,2804:528:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:52c::,2804:52c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:530::,2804:530:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:534::,2804:534:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:538::,2804:538:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:53c::,2804:53c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:540::,2804:540:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:544::,2804:544:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:548::,2804:548:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:54c::,2804:54c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:550::,2804:550:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:554::,2804:554:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:558::,2804:558:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:55c::,2804:55c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:560::,2804:560:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:564::,2804:564:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:568::,2804:568:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:56c::,2804:56c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:570::,2804:570:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:574::,2804:574:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:578::,2804:578:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:57c::,2804:57c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:580::,2804:580:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:584::,2804:584:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:588::,2804:588:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:58c::,2804:58c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:590::,2804:590:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:594::,2804:594:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:598::,2804:598:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:59c::,2804:59c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5a0::,2804:5a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5a4::,2804:5a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5a8::,2804:5a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5ac::,2804:5ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5b0::,2804:5b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5b4::,2804:5b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5b8::,2804:5b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5bc::,2804:5bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5c0::,2804:5c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5c4::,2804:5c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5c8::,2804:5c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5cc::,2804:5cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5d0::,2804:5d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5d4::,2804:5d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5d8::,2804:5d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5dc::,2804:5dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5e0::,2804:5e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5e4::,2804:5e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5e8::,2804:5e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5ec::,2804:5ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5f0::,2804:5f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5f4::,2804:5f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5f8::,2804:5f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:5fc::,2804:5fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:600::,2804:600:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:604::,2804:604:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:608::,2804:608:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:60c::,2804:60c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:610::,2804:610:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:614::,2804:614:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:618::,2804:618:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:61c::,2804:61c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:620::,2804:620:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:624::,2804:624:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:628::,2804:628:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:62c::,2804:62c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:630::,2804:630:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:634::,2804:634:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:638::,2804:638:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:63c::,2804:63c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:640::,2804:640:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:644::,2804:644:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:648::,2804:648:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:64c::,2804:64c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:650::,2804:650:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:654::,2804:654:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:658::,2804:658:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:65c::,2804:65c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:660::,2804:660:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:664::,2804:664:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:668::,2804:668:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:66c::,2804:66c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:670::,2804:670:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:674::,2804:674:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:678::,2804:678:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:67c::,2804:67c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:680::,2804:680:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:684::,2804:684:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:688::,2804:688:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:68c::,2804:68c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:690::,2804:690:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:694::,2804:694:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:698::,2804:698:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:69c::,2804:69c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6a0::,2804:6a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6a4::,2804:6a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6a8::,2804:6a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6ac::,2804:6ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6b0::,2804:6b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6b4::,2804:6b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6b8::,2804:6b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6bc::,2804:6bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6c0::,2804:6c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6c4::,2804:6c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6c8::,2804:6c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6cc::,2804:6cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6d0::,2804:6d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6d4::,2804:6d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6d8::,2804:6d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6dc::,2804:6dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6e0::,2804:6e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6e4::,2804:6e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6e8::,2804:6e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6ec::,2804:6ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6f0::,2804:6f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6f4::,2804:6f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6f8::,2804:6f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:6fc::,2804:6fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:700::,2804:700:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:704::,2804:704:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:708::,2804:708:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:70c::,2804:70c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:710::,2804:710:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:714::,2804:714:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:718::,2804:718:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:71c::,2804:71c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:720::,2804:720:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:724::,2804:724:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:728::,2804:728:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:72c::,2804:72c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:730::,2804:730:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:734::,2804:734:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:738::,2804:738:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:73c::,2804:73c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:740::,2804:740:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:744::,2804:744:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:748::,2804:748:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:74c::,2804:74c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:750::,2804:750:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:754::,2804:754:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:758::,2804:758:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:75c::,2804:75c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:760::,2804:760:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:764::,2804:764:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:768::,2804:768:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:76c::,2804:76c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:770::,2804:770:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:774::,2804:774:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:778::,2804:778:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:77c::,2804:77c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:780::,2804:780:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:784::,2804:784:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:788::,2804:788:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:78c::,2804:78c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:790::,2804:790:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:794::,2804:794:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:798::,2804:798:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:79c::,2804:79c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7a0::,2804:7a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7a4::,2804:7a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7a8::,2804:7a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7ac::,2804:7ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7b0::,2804:7b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7b4::,2804:7b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7b8::,2804:7b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7bc::,2804:7bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7c0::,2804:7c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7c4::,2804:7c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7c8::,2804:7c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7cc::,2804:7cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7d0::,2804:7d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7d4::,2804:7d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7dc::,2804:7dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7e0::,2804:7e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7e4::,2804:7e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7e8::,2804:7e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7ec::,2804:7ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:7f0::,2804:7f7:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:800::,2804:800:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:804::,2804:804:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:808::,2804:808:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:80c::,2804:80c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:810::,2804:810:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:814::,2804:814:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:818::,2804:818:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:81c::,2804:81c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:820::,2804:820:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:824::,2804:824:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:828::,2804:828:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:82c::,2804:82c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:830::,2804:830:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:834::,2804:834:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:838::,2804:838:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:83c::,2804:83c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:840::,2804:840:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:844::,2804:844:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:848::,2804:848:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:84c::,2804:84c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:850::,2804:850:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:854::,2804:854:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:858::,2804:858:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:85c::,2804:85c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:860::,2804:860:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:864::,2804:864:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:868::,2804:868:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:86c::,2804:86c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:870::,2804:870:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:874::,2804:874:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:878::,2804:878:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:87c::,2804:87c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:880::,2804:880:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:884::,2804:884:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:888::,2804:888:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:88c::,2804:88c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:890::,2804:890:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:894::,2804:894:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:898::,2804:898:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:89c::,2804:89c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8a0::,2804:8a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8a4::,2804:8a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8a8::,2804:8a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8ac::,2804:8ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8b0::,2804:8b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8b4::,2804:8b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8bc::,2804:8bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8c0::,2804:8c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8c4::,2804:8c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8c8::,2804:8c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8cc::,2804:8cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8d0::,2804:8d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8d4::,2804:8d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8d8::,2804:8d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8dc::,2804:8dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8e0::,2804:8e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8e4::,2804:8e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8e8::,2804:8e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8ec::,2804:8ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8f0::,2804:8f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8f4::,2804:8f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8f8::,2804:8f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:8fc::,2804:8fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:904::,2804:904:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:908::,2804:908:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:90c::,2804:90c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:910::,2804:910:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:914::,2804:914:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:918::,2804:918:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:91c::,2804:91c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:920::,2804:920:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:924::,2804:924:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:928::,2804:928:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:92c::,2804:92c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:930::,2804:930:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:934::,2804:934:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:938::,2804:938:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:93c::,2804:93c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:940::,2804:940:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:944::,2804:944:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:948::,2804:948:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:94c::,2804:94c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:950::,2804:950:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:954::,2804:954:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:958::,2804:958:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:95c::,2804:95c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:960::,2804:960:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:964::,2804:964:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:968::,2804:968:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:96c::,2804:96c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:970::,2804:970:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:974::,2804:974:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:978::,2804:978:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:97c::,2804:97c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:980::,2804:980:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:984::,2804:984:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:988::,2804:988:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:98c::,2804:98c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:990::,2804:990:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:994::,2804:994:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:998::,2804:998:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:99c::,2804:99c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9a0::,2804:9a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9a4::,2804:9a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9a8::,2804:9a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9ac::,2804:9ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9b0::,2804:9b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9b4::,2804:9b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9b8::,2804:9b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9bc::,2804:9bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9c0::,2804:9c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9c4::,2804:9c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9c8::,2804:9c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9cc::,2804:9cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9d0::,2804:9d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9d4::,2804:9d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9d8::,2804:9d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9dc::,2804:9dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9e0::,2804:9e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9e4::,2804:9e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9e8::,2804:9e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9ec::,2804:9ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9f0::,2804:9f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9f4::,2804:9f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9f8::,2804:9f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:9fc::,2804:9fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a00::,2804:a00:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a04::,2804:a04:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a08::,2804:a08:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a0c::,2804:a0c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a10::,2804:a10:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a14::,2804:a14:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a18::,2804:a18:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a1c::,2804:a1c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a20::,2804:a20:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a24::,2804:a24:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a28::,2804:a28:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a2c::,2804:a2c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a30::,2804:a30:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a34::,2804:a34:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a38::,2804:a38:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a3c::,2804:a3c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a40::,2804:a40:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a44::,2804:a44:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a48::,2804:a48:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a4c::,2804:a4c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a50::,2804:a50:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a54::,2804:a54:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a58::,2804:a58:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a5c::,2804:a5c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a60::,2804:a60:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a64::,2804:a64:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a68::,2804:a68:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a6c::,2804:a6c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a70::,2804:a70:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a74::,2804:a74:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a78::,2804:a78:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a7c::,2804:a7c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a80::,2804:a80:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a84::,2804:a84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a88::,2804:a88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a8c::,2804:a8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a90::,2804:a90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a94::,2804:a94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a98::,2804:a98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:a9c::,2804:a9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:aa0::,2804:aa0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:aa4::,2804:aa4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:aa8::,2804:aa8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:aac::,2804:aac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ab0::,2804:ab0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ab4::,2804:ab4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ab8::,2804:ab8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:abc::,2804:abc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ac0::,2804:ac0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ac4::,2804:ac4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ac8::,2804:ac8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:acc::,2804:acc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ad0::,2804:ad0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ad4::,2804:ad4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ad8::,2804:ad8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:adc::,2804:adc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ae0::,2804:ae0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ae4::,2804:ae4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ae8::,2804:ae8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:aec::,2804:aec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:af0::,2804:af0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:af4::,2804:af4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:af8::,2804:af8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:afc::,2804:afc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b00::,2804:b00:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b04::,2804:b04:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b08::,2804:b08:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b0c::,2804:b0c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b10::,2804:b10:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b14::,2804:b14:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b18::,2804:b18:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b1c::,2804:b1c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b20::,2804:b20:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b24::,2804:b24:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b28::,2804:b28:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b2c::,2804:b2c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b30::,2804:b30:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b34::,2804:b34:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b38::,2804:b38:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b3c::,2804:b3c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b40::,2804:b40:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b44::,2804:b44:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b48::,2804:b48:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b4c::,2804:b4c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b50::,2804:b50:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b54::,2804:b54:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b58::,2804:b58:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b5c::,2804:b5c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b60::,2804:b60:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b64::,2804:b64:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b68::,2804:b68:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b6c::,2804:b6c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b70::,2804:b70:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b74::,2804:b74:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b78::,2804:b78:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b7c::,2804:b7c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b80::,2804:b80:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b84::,2804:b84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b88::,2804:b88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b8c::,2804:b8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b90::,2804:b90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b94::,2804:b94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b98::,2804:b98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:b9c::,2804:b9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ba0::,2804:ba0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ba4::,2804:ba5:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ba8::,2804:ba8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bac::,2804:bac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bb0::,2804:bb0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bb4::,2804:bb4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bb8::,2804:bb8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bbc::,2804:bbc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bc0::,2804:bc0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bc4::,2804:bc4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bc8::,2804:bc8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bcc::,2804:bcc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bd0::,2804:bd0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bd4::,2804:bd4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bd8::,2804:bd8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bdc::,2804:bdc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:be0::,2804:be0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:be4::,2804:be4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:be8::,2804:be8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bec::,2804:bec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bf0::,2804:bf0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bf4::,2804:bf4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bf8::,2804:bf8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:bfc::,2804:bfc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c00::,2804:c00:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c04::,2804:c04:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c08::,2804:c08:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c0c::,2804:c0c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c10::,2804:c10:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c14::,2804:c14:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c18::,2804:c18:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c1c::,2804:c1c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c20::,2804:c20:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c24::,2804:c24:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c28::,2804:c28:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c2c::,2804:c2c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c30::,2804:c30:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c34::,2804:c34:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c38::,2804:c38:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c3c::,2804:c3c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c40::,2804:c40:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c44::,2804:c44:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c48::,2804:c48:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c4c::,2804:c4c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c50::,2804:c50:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c54::,2804:c54:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c58::,2804:c58:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c5c::,2804:c5c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c60::,2804:c60:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c64::,2804:c64:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c68::,2804:c68:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c6c::,2804:c6c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c70::,2804:c70:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c74::,2804:c74:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c78::,2804:c78:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c7c::,2804:c7c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c80::,2804:c80:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c84::,2804:c84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c88::,2804:c88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c8c::,2804:c8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c90::,2804:c90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c94::,2804:c94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c98::,2804:c98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:c9c::,2804:c9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ca0::,2804:ca0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ca4::,2804:ca4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ca8::,2804:ca8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cac::,2804:cac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cb0::,2804:cb0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cb4::,2804:cb4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cb8::,2804:cb8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cbc::,2804:cbc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cc0::,2804:cc0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cc4::,2804:cc4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cc8::,2804:cc8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ccc::,2804:ccc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cd0::,2804:cd0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cd4::,2804:cd4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cd8::,2804:cd8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cdc::,2804:cdc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ce0::,2804:ce0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ce4::,2804:ce4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ce8::,2804:ce8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cec::,2804:cec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cf0::,2804:cf0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cf4::,2804:cf4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cf8::,2804:cf8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:cfc::,2804:cfc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d00::,2804:d00:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d04::,2804:d04:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d08::,2804:d08:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d0c::,2804:d0c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d10::,2804:d10:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d14::,2804:d14:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d18::,2804:d18:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d1c::,2804:d1c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d20::,2804:d20:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d24::,2804:d24:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d28::,2804:d28:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d2c::,2804:d2c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d30::,2804:d30:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d34::,2804:d34:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d38::,2804:d38:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d3c::,2804:d3c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d40::,2804:d60:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d64::,2804:d64:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d68::,2804:d68:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d6c::,2804:d6c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d70::,2804:d70:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d74::,2804:d74:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d78::,2804:d78:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d7c::,2804:d7c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d80::,2804:d80:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d84::,2804:d84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d88::,2804:d88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d8c::,2804:d8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d90::,2804:d90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d94::,2804:d94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d98::,2804:d98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:d9c::,2804:d9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:da0::,2804:da0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:da4::,2804:da4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:da8::,2804:da8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dac::,2804:dac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:db0::,2804:db0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:db4::,2804:db4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:db8::,2804:db8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dbc::,2804:dbc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dc0::,2804:dc0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dc4::,2804:dc4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dc8::,2804:dc8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dcc::,2804:dcc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dd0::,2804:dd0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dd4::,2804:dd4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dd8::,2804:dd8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ddc::,2804:ddc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:de0::,2804:de0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:de4::,2804:de4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:de8::,2804:de8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dec::,2804:dec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:df0::,2804:df0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:df4::,2804:df4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:df8::,2804:df8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:dfc::,2804:dfc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e00::,2804:e00:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e04::,2804:e04:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e08::,2804:e08:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e0c::,2804:e0c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e10::,2804:e10:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e14::,2804:e14:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e18::,2804:e18:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e1c::,2804:e1c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e20::,2804:e20:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e24::,2804:e24:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e28::,2804:e28:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e2c::,2804:e2c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e30::,2804:e30:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e34::,2804:e34:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e38::,2804:e38:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e3c::,2804:e3c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e40::,2804:e40:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e44::,2804:e44:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e48::,2804:e48:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e4c::,2804:e4c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e50::,2804:e50:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e54::,2804:e54:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e58::,2804:e58:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e5c::,2804:e5c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e60::,2804:e60:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e64::,2804:e64:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e68::,2804:e68:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e6c::,2804:e6c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e70::,2804:e70:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e74::,2804:e74:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e78::,2804:e78:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e7c::,2804:e7c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e80::,2804:e80:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e84::,2804:e84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e88::,2804:e88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e8c::,2804:e8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e90::,2804:e90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e94::,2804:e94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e98::,2804:e98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:e9c::,2804:e9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ea0::,2804:ea0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ea4::,2804:ea4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ea8::,2804:ea8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:eac::,2804:eac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:eb0::,2804:eb0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:eb4::,2804:eb4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:eb8::,2804:eb8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ebc::,2804:ebc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ec0::,2804:ec0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ec4::,2804:ec4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ec8::,2804:ec8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ecc::,2804:ecc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ed0::,2804:ed0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ed4::,2804:ed4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ed8::,2804:ed8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:edc::,2804:edc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ee0::,2804:ee0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ee4::,2804:ee4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ee8::,2804:ee8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:eec::,2804:eec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ef0::,2804:ef0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ef4::,2804:ef4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ef8::,2804:ef8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:efc::,2804:efc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f00::,2804:f00:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f04::,2804:f04:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f08::,2804:f08:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f0c::,2804:f0c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f10::,2804:f10:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f14::,2804:f14:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f18::,2804:f18:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f1c::,2804:f1c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f20::,2804:f20:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f24::,2804:f24:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f28::,2804:f28:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f2c::,2804:f2c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f30::,2804:f30:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f34::,2804:f34:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f38::,2804:f38:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f3c::,2804:f3c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f40::,2804:f40:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f44::,2804:f44:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f48::,2804:f48:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f4c::,2804:f4c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f50::,2804:f50:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f54::,2804:f54:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f58::,2804:f58:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f5c::,2804:f5c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f60::,2804:f60:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f64::,2804:f64:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f68::,2804:f68:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f6c::,2804:f6c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f70::,2804:f70:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f74::,2804:f74:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f78::,2804:f78:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f7c::,2804:f7c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f80::,2804:f80:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f84::,2804:f84:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f88::,2804:f88:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f8c::,2804:f8c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f90::,2804:f90:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f94::,2804:f94:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f98::,2804:f98:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:f9c::,2804:f9c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fa0::,2804:fa0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fa4::,2804:fa4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fa8::,2804:fa8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fac::,2804:fac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fb0::,2804:fb0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fb4::,2804:fb4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fb8::,2804:fb8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fbc::,2804:fbc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fc0::,2804:fc0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fc4::,2804:fc4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fc8::,2804:fc8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fcc::,2804:fcc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fd0::,2804:fd0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fd4::,2804:fd4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fd8::,2804:fd8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fdc::,2804:fdc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fe0::,2804:fe0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fe4::,2804:fe4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fe8::,2804:fe8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:fec::,2804:fec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ff0::,2804:ff0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ff4::,2804:ff4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ff8::,2804:ff8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:ffc::,2804:ffc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1000::,2804:1000:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1004::,2804:1004:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1008::,2804:1008:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:100c::,2804:100c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1010::,2804:1010:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1014::,2804:1014:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1018::,2804:1018:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:101c::,2804:101c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1020::,2804:1020:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1024::,2804:1024:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1028::,2804:1028:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:102c::,2804:102c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1030::,2804:1030:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1034::,2804:1034:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1038::,2804:1038:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:103c::,2804:103c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1040::,2804:1040:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1044::,2804:1044:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1048::,2804:1048:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:104c::,2804:104c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1050::,2804:1050:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1054::,2804:1054:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1058::,2804:1058:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:105c::,2804:105c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1060::,2804:1060:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1064::,2804:1064:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1068::,2804:1068:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:106c::,2804:106c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1070::,2804:1070:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1074::,2804:1074:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1078::,2804:1078:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:107c::,2804:107c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1080::,2804:1080:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1084::,2804:1084:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1088::,2804:1088:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:108c::,2804:108c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1090::,2804:1090:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1094::,2804:1094:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1098::,2804:1098:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:109c::,2804:109c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10a0::,2804:10a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10a4::,2804:10a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10a8::,2804:10a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10ac::,2804:10ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10b0::,2804:10b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10b4::,2804:10b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10b8::,2804:10b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10bc::,2804:10bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10c0::,2804:10c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10c4::,2804:10c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10c8::,2804:10c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10cc::,2804:10cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10d0::,2804:10d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10d4::,2804:10d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10d8::,2804:10d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10dc::,2804:10dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10e0::,2804:10e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10e4::,2804:10e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10e8::,2804:10e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10ec::,2804:10ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10f0::,2804:10f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10f4::,2804:10f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10f8::,2804:10f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:10fc::,2804:10fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1100::,2804:1100:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1104::,2804:1104:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1108::,2804:1108:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:110c::,2804:110c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1110::,2804:1110:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1114::,2804:1114:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1118::,2804:1118:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:111c::,2804:111c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1120::,2804:1120:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1124::,2804:1124:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1128::,2804:1128:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:112c::,2804:112c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1130::,2804:1130:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1134::,2804:1134:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1138::,2804:1138:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:113c::,2804:113c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1140::,2804:1140:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1144::,2804:1144:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1148::,2804:1148:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:114c::,2804:114c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1150::,2804:1150:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1154::,2804:1154:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1158::,2804:1158:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:115c::,2804:115c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1160::,2804:1160:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1164::,2804:1164:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1168::,2804:1168:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:116c::,2804:116c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1170::,2804:1170:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1174::,2804:1174:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1178::,2804:1178:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:117c::,2804:117c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1180::,2804:1180:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1184::,2804:1184:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1188::,2804:1188:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:118c::,2804:118c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1190::,2804:1190:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1194::,2804:1194:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1198::,2804:1198:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:119c::,2804:119c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11a0::,2804:11a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11a4::,2804:11a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11a8::,2804:11a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11ac::,2804:11ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11b0::,2804:11b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11b4::,2804:11b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11b8::,2804:11b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11bc::,2804:11bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11c0::,2804:11c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11c4::,2804:11c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11c8::,2804:11c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11cc::,2804:11cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11d0::,2804:11d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11d4::,2804:11d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11d8::,2804:11d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11dc::,2804:11dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11e0::,2804:11e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11e4::,2804:11e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11e8::,2804:11e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11ec::,2804:11ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11f0::,2804:11f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11f4::,2804:11f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11f8::,2804:11f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:11fc::,2804:11fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1200::,2804:1200:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1204::,2804:1204:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1208::,2804:1208:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:120c::,2804:120c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1210::,2804:1210:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1214::,2804:1214:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1218::,2804:1218:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:121c::,2804:121c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1220::,2804:1220:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1224::,2804:1224:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1228::,2804:1228:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:122c::,2804:122c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1230::,2804:1230:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1234::,2804:1234:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1238::,2804:1238:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:123c::,2804:123c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1240::,2804:1240:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1244::,2804:1244:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1248::,2804:1248:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:124c::,2804:124c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1250::,2804:1250:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1254::,2804:1254:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1258::,2804:1258:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:125c::,2804:125c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1260::,2804:1260:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1264::,2804:1264:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1268::,2804:1268:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:126c::,2804:126c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1270::,2804:1270:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1274::,2804:1274:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1278::,2804:1278:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:127c::,2804:127c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1280::,2804:1280:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1284::,2804:1284:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1288::,2804:1288:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:128c::,2804:128c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1290::,2804:1290:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1294::,2804:1294:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1298::,2804:1298:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:129c::,2804:129c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12a0::,2804:12a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12a4::,2804:12a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12a8::,2804:12a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12ac::,2804:12ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12b0::,2804:12b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12b4::,2804:12b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12b8::,2804:12b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12bc::,2804:12bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12c0::,2804:12c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12c4::,2804:12c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12c8::,2804:12c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12cc::,2804:12cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12d0::,2804:12d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12d4::,2804:12d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12d8::,2804:12d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12dc::,2804:12dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12e0::,2804:12e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12e4::,2804:12e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12e8::,2804:12e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12ec::,2804:12ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12f0::,2804:12f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12f4::,2804:12f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12f8::,2804:12f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:12fc::,2804:12fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1300::,2804:1300:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1304::,2804:1304:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1308::,2804:1308:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:130c::,2804:130c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1310::,2804:1310:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1314::,2804:1314:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1318::,2804:1318:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:131c::,2804:131c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1320::,2804:1320:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1324::,2804:1324:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1328::,2804:1328:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:132c::,2804:132c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1330::,2804:1330:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1334::,2804:1334:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1338::,2804:1338:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:133c::,2804:133c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1340::,2804:1340:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1344::,2804:1344:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1348::,2804:1348:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:134c::,2804:134c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1350::,2804:1350:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1354::,2804:1354:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1358::,2804:1358:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:135c::,2804:135c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1360::,2804:1360:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1364::,2804:1364:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1368::,2804:1368:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:136c::,2804:136c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1370::,2804:1370:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1374::,2804:1374:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1378::,2804:1378:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:137c::,2804:137c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1380::,2804:1380:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1384::,2804:1384:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1388::,2804:138b:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1390::,2804:1390:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1394::,2804:1394:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1398::,2804:1398:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:139c::,2804:139c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13a0::,2804:13a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13a4::,2804:13a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13a8::,2804:13a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13ac::,2804:13ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13b0::,2804:13b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13b4::,2804:13b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13b8::,2804:13b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13bc::,2804:13bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13c0::,2804:13c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13c4::,2804:13c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13c8::,2804:13c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13cc::,2804:13cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13d0::,2804:13d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13d4::,2804:13d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13d8::,2804:13d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13dc::,2804:13dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13e0::,2804:13e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13e4::,2804:13e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13e8::,2804:13e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13ec::,2804:13ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13f0::,2804:13f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13f4::,2804:13f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13f8::,2804:13f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:13fc::,2804:13fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1400::,2804:1400:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1404::,2804:1404:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1408::,2804:1408:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:140c::,2804:140c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1410::,2804:1410:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1414::,2804:1414:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1418::,2804:1418:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:141c::,2804:141c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1420::,2804:1420:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1424::,2804:1424:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1428::,2804:1428:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:142c::,2804:142c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1430::,2804:1430:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1434::,2804:1434:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1438::,2804:1438:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:143c::,2804:143c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1440::,2804:1440:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1444::,2804:1444:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1448::,2804:1448:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:144c::,2804:144c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1450::,2804:1450:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1454::,2804:1454:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1458::,2804:1458:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:145c::,2804:145c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1460::,2804:1460:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1464::,2804:1464:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1468::,2804:1468:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:146c::,2804:146c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1470::,2804:1470:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1474::,2804:1474:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1478::,2804:1478:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:147c::,2804:147c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1480::,2804:1480:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1484::,2804:1484:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1488::,2804:1488:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:148c::,2804:148c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1490::,2804:1490:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1494::,2804:1494:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1498::,2804:1498:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:149c::,2804:149c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14a0::,2804:14a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14a4::,2804:14a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14a8::,2804:14a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14ac::,2804:14ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14b0::,2804:14b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14b4::,2804:14b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14b8::,2804:14b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14bc::,2804:14bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14c0::,2804:14c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14c4::,2804:14c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14c8::,2804:14c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14cc::,2804:14cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14d0::,2804:14d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14d4::,2804:14d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14d8::,2804:14d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14dc::,2804:14dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14e0::,2804:14e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14e4::,2804:14e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14e8::,2804:14e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14ec::,2804:14ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14f0::,2804:14f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14f4::,2804:14f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14f8::,2804:14f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:14fc::,2804:14fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1500::,2804:1500:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1504::,2804:1504:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1508::,2804:1508:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:150c::,2804:150c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1510::,2804:1510:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1514::,2804:1514:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1518::,2804:1518:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:151c::,2804:151c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1520::,2804:1520:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1524::,2804:1524:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1528::,2804:1528:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:152c::,2804:152c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1530::,2804:1530:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1534::,2804:1534:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1538::,2804:1538:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:153c::,2804:153c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1540::,2804:1540:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1544::,2804:1544:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1548::,2804:1548:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:154c::,2804:154c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1550::,2804:1550:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1554::,2804:1554:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1558::,2804:1558:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:155c::,2804:155c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1560::,2804:1560:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1564::,2804:1564:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1568::,2804:1568:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:156c::,2804:156c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1570::,2804:1570:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1574::,2804:1574:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1578::,2804:1578:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:157c::,2804:157c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1580::,2804:1580:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1584::,2804:1584:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1588::,2804:1588:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:158c::,2804:158c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1590::,2804:1590:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1594::,2804:1594:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1598::,2804:1598:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:159c::,2804:159c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15a0::,2804:15a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15a4::,2804:15a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15a8::,2804:15a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15ac::,2804:15ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15b0::,2804:15b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15b4::,2804:15b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15b8::,2804:15b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15bc::,2804:15bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15c0::,2804:15c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15c4::,2804:15c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15c8::,2804:15c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15cc::,2804:15cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15d0::,2804:15d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15d4::,2804:15d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15d8::,2804:15d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15dc::,2804:15dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15e0::,2804:15e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15e4::,2804:15e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15e8::,2804:15e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15ec::,2804:15ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15f0::,2804:15f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15f4::,2804:15f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15f8::,2804:15f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:15fc::,2804:15fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1600::,2804:1600:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1604::,2804:1604:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1608::,2804:1608:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:160c::,2804:160c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1610::,2804:1610:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1614::,2804:1614:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1618::,2804:1618:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:161c::,2804:161c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1620::,2804:1620:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1624::,2804:1624:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1628::,2804:1628:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:162c::,2804:162c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1630::,2804:1630:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1634::,2804:1634:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1638::,2804:1638:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:163c::,2804:163c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1640::,2804:1640:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1644::,2804:1644:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1648::,2804:1648:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:164c::,2804:164c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1650::,2804:1650:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1654::,2804:1654:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1658::,2804:1658:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:165c::,2804:165c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1660::,2804:1660:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1664::,2804:1664:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1668::,2804:1668:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:166c::,2804:166c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1670::,2804:1670:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1674::,2804:1674:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1678::,2804:1678:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:167c::,2804:167c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1680::,2804:1680:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1684::,2804:1684:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1688::,2804:1688:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:168c::,2804:168c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1690::,2804:1690:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1694::,2804:1694:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1698::,2804:1698:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:169c::,2804:169c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16a0::,2804:16a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16a4::,2804:16a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16a8::,2804:16a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16ac::,2804:16ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16b0::,2804:16b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16b4::,2804:16b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16b8::,2804:16b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16bc::,2804:16bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16c0::,2804:16c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16c4::,2804:16c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16c8::,2804:16c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16cc::,2804:16cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16d0::,2804:16d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16d4::,2804:16d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16d8::,2804:16d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16dc::,2804:16dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16e0::,2804:16e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16e4::,2804:16e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16e8::,2804:16e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16ec::,2804:16ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16f0::,2804:16f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16f4::,2804:16f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16f8::,2804:16f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:16fc::,2804:16fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1700::,2804:1700:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1704::,2804:1704:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1708::,2804:1708:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:170c::,2804:170c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1710::,2804:1710:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1714::,2804:1714:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1718::,2804:1718:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:171c::,2804:171c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1720::,2804:1720:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1724::,2804:1724:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1728::,2804:1728:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:172c::,2804:172c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1730::,2804:1730:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1734::,2804:1734:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1738::,2804:1738:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:173c::,2804:173c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1740::,2804:1740:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1744::,2804:1744:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1748::,2804:1748:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:174c::,2804:174c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1750::,2804:1750:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1754::,2804:1754:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1758::,2804:1758:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:175c::,2804:175c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1760::,2804:1760:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1764::,2804:1764:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1768::,2804:1768:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:176c::,2804:176c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1770::,2804:1770:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1774::,2804:1774:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1778::,2804:1778:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:177c::,2804:177c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1780::,2804:1780:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1784::,2804:1784:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1788::,2804:1788:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:178c::,2804:178c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1790::,2804:1790:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1794::,2804:1794:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1798::,2804:1798:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:179c::,2804:179c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17a0::,2804:17a0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17a4::,2804:17a4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17a8::,2804:17a8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17ac::,2804:17ac:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17b0::,2804:17b0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17b4::,2804:17b4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17b8::,2804:17b8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17bc::,2804:17bc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17c0::,2804:17c0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17c4::,2804:17c4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17c8::,2804:17c8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17cc::,2804:17cc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17d0::,2804:17d0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17d4::,2804:17d4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17d8::,2804:17d8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17dc::,2804:17dc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17e0::,2804:17e0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17e4::,2804:17e4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17e8::,2804:17e8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17ec::,2804:17ec:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17f0::,2804:17f0:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17f4::,2804:17f4:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17f8::,2804:17f8:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:17fc::,2804:17fc:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1800::,2804:1800:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1804::,2804:1804:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1808::,2804:1808:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:180c::,2804:180c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1810::,2804:1810:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1814::,2804:1814:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1818::,2804:1818:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:181c::,2804:181c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1820::,2804:1820:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1824::,2804:1824:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1828::,2804:1828:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:182c::,2804:182c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1830::,2804:1830:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1834::,2804:1834:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1838::,2804:1838:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:183c::,2804:183c:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1840::,2804:1840:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1844::,2804:1844:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f00::,2804:1f00:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f02::,2804:1f02:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f04::,2804:1f04:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f06::,2804:1f06:ffff:ffff:ffff:ffff:ffff:ffff,BR +2804:1f08::,2804:1f08:ffff:ffff:ffff:ffff:ffff:ffff,BR +2806::,2806:f:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:200::,2806:200:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:210::,2806:214:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:220::,2806:220:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:230::,2806:230:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:238::,2806:238::ffff:ffff:ffff:ffff:ffff,MX +2806:238:10::,2806:238:10:ffff:ffff:ffff:ffff:ffff,MX +2806:239::,2806:239:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:240::,2806:240:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:250::,2806:250:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:260::,2806:260:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:270::,2806:270:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:280::,2806:280:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:290::,2806:290:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:2a0::,2806:2a0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:2b0::,2806:2b0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:2c0::,2806:2c0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:2d0::,2806:2d0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:2e0::,2806:2e0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:2f0::,2806:2f0:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:300::,2806:300:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:310::,2806:310:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:320::,2806:320:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:330::,2806:330:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:340::,2806:340:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:350::,2806:350:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:360::,2806:360:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:370::,2806:370:ffff:ffff:ffff:ffff:ffff:ffff,MX +2806:1000::,2806:10ff:ffff:ffff:ffff:ffff:ffff:ffff,MX +2a00::,2a00:3ff:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:800::,2a00:87f:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:c00::,2a00:c00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:c08::,2a00:c08:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c10::,2a00:c10:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:c18::,2a00:c18:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:c20::,2a00:c20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c28::,2a00:c28:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:c30::,2a00:c37:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a00:c38::,2a00:c38:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:c40::,2a00:c40:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:c50::,2a00:c50:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:c58::,2a00:c58:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c60::,2a00:c60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c68::,2a00:c68:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:c70::,2a00:c70:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:c78::,2a00:c78:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:c80::,2a00:c80:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:c88::,2a00:c88:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:c90::,2a00:c90:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:c98::,2a00:c98:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:ca0::,2a00:ca0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:ca8::,2a00:ca8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:cb0::,2a00:cb0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:cb8::,2a00:cb8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:cc0::,2a00:cc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:cc8::,2a00:cc8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:cd0::,2a00:cd0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:cd8::,2a00:cd8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:ce0::,2a00:ce0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ce8::,2a00:ce8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:cf8::,2a00:cf8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:d00::,2a00:d07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d08::,2a00:d08:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d10::,2a00:d10:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d18::,2a00:d18:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:d20::,2a00:d20:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:d28::,2a00:d28:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d30::,2a00:d30:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a00:d40::,2a00:d40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:d50::,2a00:d50:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d58::,2a00:d58:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:d60::,2a00:d60:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:d68::,2a00:d68:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d70::,2a00:d70:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d78::,2a00:d78:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d80::,2a00:d80:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d88::,2a00:d88:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:d90::,2a00:d90:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:d98::,2a00:d98:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:da8::,2a00:da9:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:db0::,2a00:db0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:db8::,2a00:db8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:dc0::,2a00:dc0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:dc8::,2a00:dc8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:dd0::,2a00:dd0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:dd8::,2a00:dd8:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a00:de8::,2a00:de8:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:df0::,2a00:df0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:df8::,2a00:df8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:e00::,2a00:e00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:e08::,2a00:e0f:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:e10::,2a00:e10:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e18::,2a00:e18:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:e20::,2a00:e20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e28::,2a00:e28:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e30::,2a00:e30:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e38::,2a00:e38:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:e40::,2a00:e40:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:e48::,2a00:e48:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:e50::,2a00:e58:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e60::,2a00:e60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e68::,2a00:e68:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e70::,2a00:e70:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:e78::,2a00:e7b:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e80::,2a00:e80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:e88::,2a00:e88:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e90::,2a00:e90:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:e98::,2a00:e98:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:ea0::,2a00:ea0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:ea8::,2a00:eaf:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:eb0::,2a00:eb0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:eb8::,2a00:eb8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ec0::,2a00:ec0:ffff:ffff:ffff:ffff:ffff:ffff,LI +2a00:ec8::,2a00:ec8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:ed0::,2a00:ed0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ed8::,2a00:ed8:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:ee0::,2a00:ee7:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:ee8::,2a00:ee8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:ef0::,2a00:ef0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:ef8::,2a00:ef8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:f00::,2a00:f00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f08::,2a00:f08:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f10::,2a00:f10:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:f18::,2a00:f18:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f20::,2a00:f20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:f28::,2a00:f2f:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a00:f30::,2a00:f30:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f38::,2a00:f38:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a00:f40::,2a00:f47:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:f48::,2a00:f4f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f50::,2a00:f50:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:f58::,2a00:f58:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:f60::,2a00:f60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:f68::,2a00:f68:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:f70::,2a00:f70:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f78::,2a00:f78:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:f80::,2a00:f80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:f88::,2a00:f88:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f90::,2a00:f90:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:f98::,2a00:f98:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:fa0::,2a00:fa0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:fa8::,2a00:fa8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fb8::,2a00:fb8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fc0::,2a00:fc0:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:fc8::,2a00:fc8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:fd0::,2a00:fd0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:fd8::,2a00:fd8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:fe0::,2a00:fe0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fe8::,2a00:fe8:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:ff0::,2a00:ff0:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:ff8::,2a00:fff:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:1000::,2a00:1000:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1008::,2a00:1008:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1010::,2a00:1010:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1018::,2a00:1018:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1020::,2a00:1020:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1028::,2a00:1028:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1030::,2a00:1030:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1038::,2a00:1038:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:1040::,2a00:1040:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1048::,2a00:1048:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1050::,2a00:1050:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1058::,2a00:1058:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1060::,2a00:1060:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a00:1068::,2a00:1068:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1070::,2a00:1070:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1078::,2a00:1078:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1080::,2a00:1080:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1088::,2a00:1088:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1098::,2a00:1098:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:10a0::,2a00:10a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:10a8::,2a00:10a8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:10b0::,2a00:10b7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:10b8::,2a00:10b8:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:10c0::,2a00:10c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:10c8::,2a00:10c8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:10d0::,2a00:10d0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:10d8::,2a00:10d8:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:10e0::,2a00:10e0:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a00:10e8::,2a00:10f0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:10f8::,2a00:10f8:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:1100::,2a00:1107:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1108::,2a00:1108:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:1110::,2a00:1117:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:1118::,2a00:1118:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:1120::,2a00:1120:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1128::,2a00:1128:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:1130::,2a00:1130:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1138::,2a00:1138:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1140::,2a00:1140:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1148::,2a00:1148:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1150::,2a00:1150:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a00:1158::,2a00:1158:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1160::,2a00:1160:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1168::,2a00:1168:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1170::,2a00:1170:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:1178::,2a00:1178:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1180::,2a00:1180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1188::,2a00:1188:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1190::,2a00:1190:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1198::,2a00:1198:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:11a8::,2a00:11a8:ffff:ffff:ffff:ffff:ffff:ffff,OM +2a00:11b0::,2a00:11b0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:11b8::,2a00:11b8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:11c0::,2a00:11c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:11c8::,2a00:11c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:11d0::,2a00:11d0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:11d8::,2a00:11d8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:11e0::,2a00:11e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:11e8::,2a00:11e8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:11f0::,2a00:11f0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:11f8::,2a00:11f8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1200::,2a00:1200:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1208::,2a00:1208:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1210::,2a00:1210:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1218::,2a00:1218:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a00:1220::,2a00:1220:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1228::,2a00:1228:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1230::,2a00:1237:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1238::,2a00:1238:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1240::,2a00:1240:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1248::,2a00:1248:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1258::,2a00:1258:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1260::,2a00:1260:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1268::,2a00:1268:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1270::,2a00:1270:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a00:1278::,2a00:1278:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1280::,2a00:1280:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1288::,2a00:1288:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1290::,2a00:1290:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1298::,2a00:1298:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:12a0::,2a00:12a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:12a8::,2a00:12a8:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:12b0::,2a00:12b0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:12b8::,2a00:12b8:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:12c0::,2a00:12c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:12c8::,2a00:12c8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:12d0::,2a00:12d0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:12d8::,2a00:12d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:12e0::,2a00:12e0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:12e8::,2a00:12e8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:12f0::,2a00:12f0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:12f8::,2a00:12f8:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a00:1300::,2a00:1300:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1308::,2a00:1308:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1318::,2a00:1318:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1320::,2a00:1320:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1328::,2a00:1328:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1338::,2a00:1338:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1340::,2a00:1340:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1348::,2a00:1348:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1350::,2a00:1350:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1358::,2a00:135b:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a00:1360::,2a00:1360:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1368::,2a00:1368:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:1370::,2a00:1370:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1378::,2a00:1378:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1380::,2a00:1380:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:1388::,2a00:1388:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1390::,2a00:1390:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1398::,2a00:1398:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:13a0::,2a00:13a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:13a8::,2a00:13a8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:13b0::,2a00:13b0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:13b8::,2a00:13b8:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:13c0::,2a00:13c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:13c8::,2a00:13c8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:13d0::,2a00:13d0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:13d8::,2a00:13df:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:13e0::,2a00:13e0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:13e8::,2a00:13e8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:13f0::,2a00:13f0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:13f8::,2a00:13f8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1400::,2a00:1400:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1408::,2a00:1408:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1410::,2a00:1410:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1418::,2a00:1418:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1420::,2a00:1420:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:1428::,2a00:1428:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:1430::,2a00:1430:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1440::,2a00:1440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1448::,2a00:1448:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:1450::,2a00:1457:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:1458::,2a00:1458:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1460::,2a00:1460:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1468::,2a00:1468:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1470::,2a00:1470:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1478::,2a00:1478:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1480::,2a00:1480:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:1488::,2a00:1488:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1490::,2a00:1490:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1498::,2a00:1498:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:14a0::,2a00:14a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:14a8::,2a00:14a8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:14b0::,2a00:14b0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:14b8::,2a00:14b8:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:14c0::,2a00:14c0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:14c8::,2a00:14c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:14d0::,2a00:14d0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:14d8::,2a00:14d8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:14e0::,2a00:14e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:14e8::,2a00:14ef:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:14f0::,2a00:14f0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:14f8::,2a00:14f8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1500::,2a00:1500:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a00:1508::,2a00:1508:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:1510::,2a00:1510:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1518::,2a00:1518:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1520::,2a00:1520:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1528::,2a00:1528:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1530::,2a00:1531:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:1538::,2a00:1538:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1540::,2a00:1540:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1548::,2a00:1548:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1550::,2a00:1550:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1558::,2a00:1558:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1560::,2a00:1560:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:1568::,2a00:1568:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1570::,2a00:1570:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:1578::,2a00:1578:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1580::,2a00:1580:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:1588::,2a00:1588:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1590::,2a00:1590:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:1598::,2a00:159f:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:15a0::,2a00:15a0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:15a8::,2a00:15a8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:15b0::,2a00:15b0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:15b8::,2a00:15b8:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:15c0::,2a00:15c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:15c8::,2a00:15c8:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:15d0::,2a00:15d0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:15e0::,2a00:15e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:15e8::,2a00:15e8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:15f0::,2a00:15f0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:15f8::,2a00:15f8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1600::,2a00:1607:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:1610::,2a00:1610:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1618::,2a00:1618:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1620::,2a00:1620:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1628::,2a00:1628:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1630::,2a00:1637:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1638::,2a00:1638:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1640::,2a00:1640:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1648::,2a00:1648:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1650::,2a00:1650:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a00:1660::,2a00:1660:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:1668::,2a00:1668:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1670::,2a00:1670:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1678::,2a00:1678:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1680::,2a00:1680:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1688::,2a00:1688:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1690::,2a00:1690:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1698::,2a00:1698:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:16a0::,2a00:16a0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:16a8::,2a00:16a8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:16b0::,2a00:16b0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:16c8::,2a00:16c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:16d0::,2a00:16d0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:16d8::,2a00:16d8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:16e0::,2a00:16e0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a00:16e8::,2a00:16e8:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:16f0::,2a00:16f0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:16f8::,2a00:16f8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1700::,2a00:1700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1708::,2a00:1708:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1710::,2a00:1710:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:1718::,2a00:1718:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1720::,2a00:1720:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1728::,2a00:1728:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:1730::,2a00:1730:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1748::,2a00:1748:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1750::,2a00:1750:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1758::,2a00:1758:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:1760::,2a00:1760:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a00:1768::,2a00:1768:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1778::,2a00:1778:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1780::,2a00:1780:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:1788::,2a00:1788:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1790::,2a00:1790:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1798::,2a00:1798:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:17a0::,2a00:17a0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:17a8::,2a00:17a8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:17b0::,2a00:17b0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:17b8::,2a00:17b8:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:17c0::,2a00:17c0:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:17c8::,2a00:17c8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:17d0::,2a00:17d0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:17d8::,2a00:17d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:17e0::,2a00:17e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:17e8::,2a00:17e8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:17f0::,2a00:17f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:17f8::,2a00:17f8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1800::,2a00:1800:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1808::,2a00:1808:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1818::,2a00:1818:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1828::,2a00:1828:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1830::,2a00:1830:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1838::,2a00:1838:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1840::,2a00:1840:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:1848::,2a00:1848:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1850::,2a00:1850:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a00:1858::,2a00:1858:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a00:1860::,2a00:1860:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1868::,2a00:1868:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1878::,2a00:1878:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:1880::,2a00:1880:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:1888::,2a00:1888:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1890::,2a00:1890:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1898::,2a00:1898:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:18a0::,2a00:18a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:18a8::,2a00:18a8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:18b0::,2a00:18b0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:18b8::,2a00:18b8:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:18c0::,2a00:18c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:18c8::,2a00:18c8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:18d0::,2a00:18d0:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a00:18d8::,2a00:18d8:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a00:18e0::,2a00:18e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:18e8::,2a00:18e8:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:18f0::,2a00:18f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:18f8::,2a00:18f8:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:1900::,2a00:1900:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1908::,2a00:1908:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1910::,2a00:1910:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1918::,2a00:191f:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:1920::,2a00:1920:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1928::,2a00:1928:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1930::,2a00:1930:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1938::,2a00:1938:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1940::,2a00:1940:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1948::,2a00:1948:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1950::,2a00:1950:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1958::,2a00:1958:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1960::,2a00:1960:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1968::,2a00:1968:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1970::,2a00:1970:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1978::,2a00:1978:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1980::,2a00:1980:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1988::,2a00:1988:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1990::,2a00:1990:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1998::,2a00:1998:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:19a0::,2a00:19a0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:19a8::,2a00:19a8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:19b0::,2a00:19b0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:19b8::,2a00:19b8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:19c0::,2a00:19c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:19c8::,2a00:19c8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:19d0::,2a00:19d0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:19d8::,2a00:19d8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:19e0::,2a00:19e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:19e8::,2a00:19e8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:19f0::,2a00:19f0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:19f8::,2a00:19f8:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1a00::,2a00:1a00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1a08::,2a00:1a08:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a00:1a10::,2a00:1a10:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1a18::,2a00:1a18:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1a20::,2a00:1a20:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:1a28::,2a00:1a28:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1a30::,2a00:1a30:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1a38::,2a00:1a38:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1a40::,2a00:1a40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1a48::,2a00:1a48:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1a50::,2a00:1a50:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1a58::,2a00:1a58:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1a60::,2a00:1a60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1a68::,2a00:1a68:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1a70::,2a00:1a70:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1a78::,2a00:1a78:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1a80::,2a00:1a80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1a88::,2a00:1a88:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:1a90::,2a00:1a90:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1a98::,2a00:1a98:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:1aa0::,2a00:1aa0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1aa8::,2a00:1aa8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1ab0::,2a00:1ab0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1ab8::,2a00:1ab8:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1ac0::,2a00:1ac0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1ac8::,2a00:1ac8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1ad0::,2a00:1ad0:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:1ad8::,2a00:1ad8:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1ae0::,2a00:1ae0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1ae8::,2a00:1ae8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1af0::,2a00:1af7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:1af8::,2a00:1af8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1b00::,2a00:1b00:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a00:1b08::,2a00:1b08:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1b10::,2a00:1b10:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1b18::,2a00:1b18:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1b20::,2a00:1b20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1b28::,2a00:1b28:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1b30::,2a00:1b30:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1b38::,2a00:1b38:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1b40::,2a00:1b40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1b48::,2a00:1b48:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1b50::,2a00:1b50:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1b58::,2a00:1b58:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1b60::,2a00:1b60:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1b68::,2a00:1b68:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1b70::,2a00:1b70:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1b78::,2a00:1b78:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1b80::,2a00:1b80:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:1b88::,2a00:1b88:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1b90::,2a00:1b90:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:1b98::,2a00:1b98:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1ba0::,2a00:1ba0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1ba8::,2a00:1ba8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1bb0::,2a00:1bb0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1bb8::,2a00:1bb8:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a00:1bc0::,2a00:1bc0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1bc8::,2a00:1bc8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1bd0::,2a00:1bd0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1bd8::,2a00:1bd8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1be0::,2a00:1be0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1be8::,2a00:1be8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1bf0::,2a00:1bf0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1bf8::,2a00:1bf8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1c00::,2a00:1c00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1c08::,2a00:1c08:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1c10::,2a00:1c10:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1c18::,2a00:1c1f:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1c20::,2a00:1c20:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1c28::,2a00:1c28:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1c30::,2a00:1c30:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1c38::,2a00:1c3f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1c40::,2a00:1c40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1c48::,2a00:1c48:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1c50::,2a00:1c50:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1c58::,2a00:1c58:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1c60::,2a00:1c60:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a00:1c68::,2a00:1c68:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1c70::,2a00:1c70:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1c78::,2a00:1c78:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1c80::,2a00:1c80:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:1c88::,2a00:1c88:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1c90::,2a00:1c90:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1c98::,2a00:1c98:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1ca0::,2a00:1ca0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1ca8::,2a00:1ca8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1cb0::,2a00:1cb0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1cb8::,2a00:1cb8:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a00:1cc0::,2a00:1cc0:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a00:1cc8::,2a00:1cc8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1cd0::,2a00:1cd0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1cd8::,2a00:1cd8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1ce0::,2a00:1ce0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:1ce8::,2a00:1ce8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1cf0::,2a00:1cf0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1cf8::,2a00:1cf8:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:1d00::,2a00:1d00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1d08::,2a00:1d08:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1d10::,2a00:1d10:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:1d18::,2a00:1d18:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1d20::,2a00:1d27:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1d28::,2a00:1d28:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1d30::,2a00:1d30:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:1d38::,2a00:1d38:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1d40::,2a00:1d40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1d48::,2a00:1d48:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1d50::,2a00:1d50:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1d58::,2a00:1d58:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:1d60::,2a00:1d60:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1d68::,2a00:1d68:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1d70::,2a00:1d70:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:1d78::,2a00:1d78:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1d80::,2a00:1d80:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1d88::,2a00:1d88:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1d90::,2a00:1d90:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1da0::,2a00:1da0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1da8::,2a00:1da8:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:1db0::,2a00:1db0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1db8::,2a00:1db8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1dc0::,2a00:1dc7:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a00:1dc8::,2a00:1dc8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1dd0::,2a00:1dd0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1dd8::,2a00:1ddf:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:1de0::,2a00:1de0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1de8::,2a00:1de8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1df0::,2a00:1df0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1df8::,2a00:1df8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1e00::,2a00:1e00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1e08::,2a00:1e08:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1e10::,2a00:1e10:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1e18::,2a00:1e18:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1e20::,2a00:1e20:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1e28::,2a00:1e28:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1e30::,2a00:1e30:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1e38::,2a00:1e38:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1e40::,2a00:1e40:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:1e48::,2a00:1e48:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1e50::,2a00:1e50:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1e58::,2a00:1e58:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1e60::,2a00:1e60:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1e68::,2a00:1e68:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1e70::,2a00:1e70:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1e78::,2a00:1e78:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1e80::,2a00:1e80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1e88::,2a00:1e88:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1e90::,2a00:1e90:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1e98::,2a00:1e98:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:1ea0::,2a00:1ea0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1ea8::,2a00:1ea8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1eb0::,2a00:1eb0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:1eb8::,2a00:1eb8:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:1ec0::,2a00:1ec0:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a00:1ec8::,2a00:1ecf:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1ed0::,2a00:1ed0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:1ed8::,2a00:1edf:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:1ee0::,2a00:1ee0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1ee8::,2a00:1ee8:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a00:1ef0::,2a00:1ef0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:1ef8::,2a00:1ef8:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:1f00::,2a00:1f00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1f08::,2a00:1f08:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1f10::,2a00:1f10:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1f18::,2a00:1f18:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:1f20::,2a00:1f20:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:1f28::,2a00:1f28:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a00:1f30::,2a00:1f30:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1f38::,2a00:1f38:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1f40::,2a00:1f40:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:1f48::,2a00:1f48:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:1f50::,2a00:1f50:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:1f58::,2a00:1f58:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1f60::,2a00:1f60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1f68::,2a00:1f68:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a00:1f70::,2a00:1f70:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1f78::,2a00:1f78:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1f80::,2a00:1f80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:1f88::,2a00:1f88:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:1f90::,2a00:1f90:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:1f98::,2a00:1f98:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:1fa0::,2a00:1fa0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1fa8::,2a00:1fa8:ffff:ffff:ffff:ffff:ffff:ffff,GL +2a00:1fb0::,2a00:1fb0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1fb8::,2a00:1fb8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:1fc0::,2a00:1fc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:1fd0::,2a00:1fd0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:1fd8::,2a00:1fd8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1fe0::,2a00:1fe0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:1fe8::,2a00:1fe8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:1ff0::,2a00:1ff0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:1ff8::,2a00:1ff8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:2000::,2a00:23ff:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4000::,2a00:4000:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:4040::,2a00:4040:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4060::,2a00:4060:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:4080::,2a00:4087:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:40a0::,2a00:40a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:40c0::,2a00:40c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:40e0::,2a00:40e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:4100::,2a00:4100:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4120::,2a00:4120:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:4160::,2a00:4160:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:4180::,2a00:4180:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:41a0::,2a00:41a0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:41c0::,2a00:41c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:41e0::,2a00:41e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4200::,2a00:4200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4220::,2a00:4220:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:4240::,2a00:4240:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4260::,2a00:4260:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:4280::,2a00:4280:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:42a0::,2a00:42a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:42c0::,2a00:42c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:42e0::,2a00:42e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:4300::,2a00:4300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4320::,2a00:4320:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4340::,2a00:4340:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4360::,2a00:4360:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:4380::,2a00:4380:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:43a0::,2a00:43a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:43c0::,2a00:43c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:43e0::,2a00:43e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:4400::,2a00:4400:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:4420::,2a00:4420:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4440::,2a00:4440:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:4460::,2a00:4460:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:4480::,2a00:4480:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:44a0::,2a00:44a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:44c0::,2a00:44c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:44e0::,2a00:44e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4500::,2a00:4500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4520::,2a00:4520:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a00:4540::,2a00:4540:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:4560::,2a00:4560:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:4580::,2a00:4580:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:45a0::,2a00:45a0:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a00:45c0::,2a00:45c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:45e0::,2a00:45e0:ffff:ffff:ffff:ffff:ffff:ffff,IM +2a00:4600::,2a00:4600:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:4620::,2a00:4620:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a00:4640::,2a00:4640:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4660::,2a00:4660:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4680::,2a00:4680:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:46a0::,2a00:46a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:46c0::,2a00:46c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:46e0::,2a00:46e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4700::,2a00:4700:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4720::,2a00:4720:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4740::,2a00:4740:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:4760::,2a00:4760:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:4780::,2a00:4780:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:47a0::,2a00:47a0:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a00:47c0::,2a00:47c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:47e0::,2a00:47e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4800::,2a00:4807:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:4840::,2a00:4840:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4860::,2a00:4860:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4880::,2a00:4880:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:48a0::,2a00:48a0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:48c0::,2a00:48c0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:48e0::,2a00:48e0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:4900::,2a00:4900:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4920::,2a00:4920:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:4940::,2a00:4940:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a00:4960::,2a00:4960:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4980::,2a00:4987:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:49c0::,2a00:49c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:49e0::,2a00:49e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4a00::,2a00:4a00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4a20::,2a00:4a20:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4a40::,2a00:4a40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:4a60::,2a00:4a60:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a00:4a80::,2a00:4a80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4aa0::,2a00:4aa0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4ac0::,2a00:4ac0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4ae0::,2a00:4ae0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4b00::,2a00:4b00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4b40::,2a00:4b40:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:4b60::,2a00:4b60:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a00:4b80::,2a00:4b80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:4ba0::,2a00:4ba0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:4bc0::,2a00:4bc0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:4be0::,2a00:4be0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:4c00::,2a00:4c00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4c20::,2a00:4c20:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:4c40::,2a00:4c40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4c60::,2a00:4c60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4c80::,2a00:4c87:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a00:4ca0::,2a00:4ca0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4cc0::,2a00:4cc7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:4ce0::,2a00:4ce0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4d00::,2a00:4d00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:4d20::,2a00:4d20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4d40::,2a00:4d40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4d60::,2a00:4d60:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:4d80::,2a00:4d80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4da0::,2a00:4da0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:4dc0::,2a00:4dc0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:4de0::,2a00:4de0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:4e00::,2a00:4e00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4e20::,2a00:4e20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:4e40::,2a00:4e40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:4e60::,2a00:4e60:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:4e80::,2a00:4e80:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a00:4ea0::,2a00:4ea0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:4ec0::,2a00:4ec0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:4f00::,2a00:4f00:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:4f20::,2a00:4f20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:4f40::,2a00:4f40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4f60::,2a00:4f60:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:4f80::,2a00:4f80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:4fa0::,2a00:4fa7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:4fc0::,2a00:4fc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:4fe0::,2a00:4fe0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:5000::,2a00:5000:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:5040::,2a00:5040:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:5060::,2a00:5060:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:5080::,2a00:5080:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:50a0::,2a00:50a0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:50c0::,2a00:50c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:50e0::,2a00:50e7:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:5100::,2a00:5100:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:5120::,2a00:5120:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5140::,2a00:5140:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5160::,2a00:5160:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5180::,2a00:5180:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:51c0::,2a00:51c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:51e0::,2a00:51e0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:5200::,2a00:5200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5220::,2a00:5220:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:5240::,2a00:5240:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:5260::,2a00:5260:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5280::,2a00:5280:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:52a0::,2a00:52a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:52c0::,2a00:52c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:52e0::,2a00:52e0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:5300::,2a00:5300:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5320::,2a00:5320:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:5340::,2a00:5340:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:5360::,2a00:5360:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:5380::,2a00:5380:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:53a0::,2a00:53a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:53c0::,2a00:53c0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:53e0::,2a00:53e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5400::,2a00:5400:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:5420::,2a00:5420:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5440::,2a00:5440:ffff:ffff:ffff:ffff:ffff:ffff,US +2a00:5460::,2a00:5460:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5480::,2a00:5480:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:54a0::,2a00:54a0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:54c0::,2a00:54c0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:54e0::,2a00:54e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:5500::,2a00:5500:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:5520::,2a00:5520:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:5540::,2a00:5540:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5560::,2a00:5560:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5580::,2a00:5580:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:55a0::,2a00:55a0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a00:55c0::,2a00:55c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:55e0::,2a00:55e0:ffff:ffff:ffff:ffff:ffff:ffff,SM +2a00:5600::,2a00:5600:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5620::,2a00:5620:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5640::,2a00:5647:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5680::,2a00:5680:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:56a0::,2a00:56a0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:56c0::,2a00:56c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:56e0::,2a00:56e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:5700::,2a00:5700:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a00:5720::,2a00:5720:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:5740::,2a00:5740:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:5760::,2a00:5760:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5780::,2a00:5780:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:57a0::,2a00:57a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:57c0::,2a00:57c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:57e0::,2a00:57e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:5800::,2a00:5800:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:5820::,2a00:5820:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5840::,2a00:5840:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5860::,2a00:5860:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:5880::,2a00:5887:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:58e0::,2a00:58e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5900::,2a00:5900:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:5920::,2a00:5920:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:5940::,2a00:5940:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:5960::,2a00:5960:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5980::,2a00:5980:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:59a0::,2a00:59a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:59c0::,2a00:59c0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:59e0::,2a00:59e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5a00::,2a00:5a00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5a20::,2a00:5a20:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:5a40::,2a00:5a40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:5a60::,2a00:5a60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5a80::,2a00:5a80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5aa0::,2a00:5aa0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:5ac0::,2a00:5ac0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:5ae0::,2a00:5ae0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:5b00::,2a00:5b07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:5b20::,2a00:5b20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:5b40::,2a00:5b40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:5b60::,2a00:5b60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5b80::,2a00:5b87:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:5ba0::,2a00:5ba0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5bc0::,2a00:5bc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5be0::,2a00:5be0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5c00::,2a00:5c00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:5c20::,2a00:5c20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:5c40::,2a00:5c47:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a00:5c60::,2a00:5c60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5c80::,2a00:5c80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:5ca0::,2a00:5ca0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:5cc0::,2a00:5cc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5ce0::,2a00:5ce0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:5d00::,2a00:5d00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:5d20::,2a00:5d20:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:5d40::,2a00:5d40:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:5d60::,2a00:5d60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5d80::,2a00:5d80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5da0::,2a00:5da0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a00:5dc0::,2a00:5dc0:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:5de0::,2a00:5de0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:5e00::,2a00:5e00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5e20::,2a00:5e20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5e40::,2a00:5e40:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:5e60::,2a00:5e60:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:5e80::,2a00:5e80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:5ea0::,2a00:5ea0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:5ec0::,2a00:5ec0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:5ee0::,2a00:5ee0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:5f00::,2a00:5f00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:5f20::,2a00:5f20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:5f40::,2a00:5f47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5fa0::,2a00:5fa0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:5fc0::,2a00:5fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:5fe0::,2a00:5fe0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:6000::,2a00:6000:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6020::,2a00:6020:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6040::,2a00:6040:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:6060::,2a00:6060:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6080::,2a00:6080:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:60a0::,2a00:60a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:60e0::,2a00:60e0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:6100::,2a00:6100:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6120::,2a00:6120:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:6140::,2a00:6140:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6160::,2a00:6160:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6180::,2a00:6180:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:61a0::,2a00:61a0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:61c0::,2a00:61c7:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:61e0::,2a00:61e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6200::,2a00:6200:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6220::,2a00:6220:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:6240::,2a00:6240:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6260::,2a00:6260:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:6280::,2a00:6280:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:62a0::,2a00:62a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:62c0::,2a00:62c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:62e0::,2a00:62e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6300::,2a00:6300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6320::,2a00:6320:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6340::,2a00:6340:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:6360::,2a00:6360:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6380::,2a00:6380:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:63a0::,2a00:63a0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:63c0::,2a00:63c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:63e0::,2a00:63e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6400::,2a00:6400:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6420::,2a00:6420:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6440::,2a00:6440:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a00:6460::,2a00:6460:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:6480::,2a00:6480:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:64a0::,2a00:64a0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:64c0::,2a00:64c0:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:64e0::,2a00:64e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:6500::,2a00:6500:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:6520::,2a00:6520:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6540::,2a00:6540:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6560::,2a00:6560:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6580::,2a00:6580:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:65a0::,2a00:65a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:65c0::,2a00:65c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:65e0::,2a00:65e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6600::,2a00:6600:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a00:6620::,2a00:6620:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a00:6640::,2a00:6640:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:6660::,2a00:6660:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:6680::,2a00:6680:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:66a0::,2a00:66a0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a00:66e0::,2a00:66e0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:6720::,2a00:6720:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6740::,2a00:6740:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:6760::,2a00:6760:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6780::,2a00:6780:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:67a0::,2a00:67a7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:67c0::,2a00:67c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:67e0::,2a00:67e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6800::,2a00:6800:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6820::,2a00:6820:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6840::,2a00:6840:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:6860::,2a00:6867:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:68a0::,2a00:68a0:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a00:68c0::,2a00:68c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:68e0::,2a00:68e0:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a00:6900::,2a00:6900:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6920::,2a00:6920:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:6940::,2a00:6940:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:6960::,2a00:6960:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:6980::,2a00:6980:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:69a0::,2a00:69a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:69c0::,2a00:69c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:69e0::,2a00:69e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6a00::,2a00:6a00:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a00:6a20::,2a00:6a20:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:6a40::,2a00:6a40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6a60::,2a00:6a60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:6a80::,2a00:6a80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6ac0::,2a00:6ac0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:6ae0::,2a00:6ae0:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:6b00::,2a00:6b00:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:6b20::,2a00:6b20:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a00:6b40::,2a00:6b40:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:6b60::,2a00:6b60:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:6b80::,2a00:6b80:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a00:6bc0::,2a00:6bc0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:6be0::,2a00:6be0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6c00::,2a00:6c00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6c20::,2a00:6c20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6c40::,2a00:6c40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:6c60::,2a00:6c60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6c80::,2a00:6c80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6ca0::,2a00:6ca0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:6ce0::,2a00:6ce0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6d20::,2a00:6d20:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:6d40::,2a00:6d47:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:6d60::,2a00:6d60:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:6d80::,2a00:6d80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:6da0::,2a00:6da0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:6dc0::,2a00:6dc0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:6de0::,2a00:6de0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6e00::,2a00:6e00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6e20::,2a00:6e20:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:6e40::,2a00:6e40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:6e60::,2a00:6e60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6e80::,2a00:6e80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:6ea0::,2a00:6ea0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6ec0::,2a00:6ec0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:6f00::,2a00:6f00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:6f20::,2a00:6f20:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:6f40::,2a00:6f40:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:6f60::,2a00:6f60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6f80::,2a00:6f80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:6fa0::,2a00:6fa0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:6fc0::,2a00:6fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:6fe0::,2a00:6fe0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7000::,2a00:7000:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:7020::,2a00:7020:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7040::,2a00:7040:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:7060::,2a00:7060:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7080::,2a00:7080:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:70a0::,2a00:70a0:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a00:70c0::,2a00:70c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:70e0::,2a00:70e0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:7100::,2a00:7100:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:7120::,2a00:7120:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:7140::,2a00:7147:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7160::,2a00:7160:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a00:7180::,2a00:7180:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:71a0::,2a00:71a0:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:71c0::,2a00:71c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:71e0::,2a00:71e0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:7200::,2a00:7200:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7220::,2a00:7220:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:7240::,2a00:7243:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:7260::,2a00:7260:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7280::,2a00:7280:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:72a0::,2a00:72a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:72e0::,2a00:72e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7300::,2a00:7300:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:7320::,2a00:7327:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:7340::,2a00:7340:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:7360::,2a00:7360:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:7380::,2a00:7380:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:73a0::,2a00:73a0:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:73c0::,2a00:73c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:73e0::,2a00:73e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7400::,2a00:7400:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:7420::,2a00:7420:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7440::,2a00:7447:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:7460::,2a00:7460:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:7480::,2a00:7480:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:74a0::,2a00:74a0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:74c0::,2a00:74c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:74e0::,2a00:74e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7500::,2a00:7500:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7520::,2a00:7520:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:7540::,2a00:7540:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7560::,2a00:7560:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:7580::,2a00:7580:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:75a0::,2a00:75a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:75c0::,2a00:75c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:75e0::,2a00:75e0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:7600::,2a00:7600:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:7620::,2a00:7620:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a00:7640::,2a00:7640:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7660::,2a00:7660:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:7680::,2a00:7680:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:76a0::,2a00:76a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:76c0::,2a00:76c0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:76e0::,2a00:76e0:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a00:7700::,2a00:7700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7720::,2a00:7720:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:7740::,2a00:7740:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7760::,2a00:7767:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7780::,2a00:7780:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:77a0::,2a00:77a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:77c0::,2a00:77c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:77e0::,2a00:77e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7800::,2a00:7800:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:7820::,2a00:7820:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7840::,2a00:7840:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:7860::,2a00:7860:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7880::,2a00:7880:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a00:78a0::,2a00:78a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:78c0::,2a00:78c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:78e0::,2a00:78e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7900::,2a00:7900:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7920::,2a00:7920:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:7940::,2a00:7940:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7960::,2a00:7960:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7980::,2a00:7980:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:79a0::,2a00:79a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:79c0::,2a00:79c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:79e0::,2a00:79e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:7a00::,2a00:7a00:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:7a20::,2a00:7a20:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:7a40::,2a00:7a40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7a60::,2a00:7a60:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:7a80::,2a00:7a80:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:7ac0::,2a00:7ac0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7ae0::,2a00:7ae0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:7b00::,2a00:7b07:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:7b40::,2a00:7b40:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:7b60::,2a00:7b60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7b80::,2a00:7b80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7ba0::,2a00:7ba0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7be0::,2a00:7be0:ffff:ffff:ffff:ffff:ffff:ffff,QA +2a00:7c00::,2a00:7c00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7c20::,2a00:7c20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:7c40::,2a00:7c40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7c60::,2a00:7c60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7c80::,2a00:7c80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7ca0::,2a00:7ca0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:7cc0::,2a00:7cc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:7ce0::,2a00:7ce0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7d00::,2a00:7d00:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:7d20::,2a00:7d20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:7d40::,2a00:7d40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:7d60::,2a00:7d60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7d80::,2a00:7d80:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:7da0::,2a00:7da0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:7dc0::,2a00:7dc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7de0::,2a00:7de0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:7e00::,2a00:7e00:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:7e20::,2a00:7e20:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:7e40::,2a00:7e40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7e60::,2a00:7e60:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:7e80::,2a00:7e80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:7ea0::,2a00:7ea0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:7ec0::,2a00:7ec0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7f00::,2a00:7f00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:7f20::,2a00:7f20:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:7f40::,2a00:7f40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:7f60::,2a00:7f60:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a00:7f80::,2a00:7f87:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:7fc0::,2a00:7fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:7fe0::,2a00:7fe0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:8020::,2a00:8020:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:8040::,2a00:8040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8060::,2a00:8060:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8080::,2a00:8080:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:80a0::,2a00:80a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:80c0::,2a00:80c0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:80e0::,2a00:80e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:8100::,2a00:8100:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:8120::,2a00:8120:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8140::,2a00:8140:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8160::,2a00:8160:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:8180::,2a00:8180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:81a0::,2a00:81a0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:81c0::,2a00:81c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:81e0::,2a00:81e0:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:8200::,2a00:8200:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:8220::,2a00:8220:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:8240::,2a00:8240:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8260::,2a00:8260:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:8280::,2a00:8280:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:82a0::,2a00:82a0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:82c0::,2a00:82c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:82e0::,2a00:82e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:8300::,2a00:8300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8320::,2a00:8320:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:8340::,2a00:8340:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:8360::,2a00:8360:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:8380::,2a00:8380:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:83a0::,2a00:83a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:83e0::,2a00:83e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:8400::,2a00:8400:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:8420::,2a00:8420:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8440::,2a00:8440:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8460::,2a00:8460:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8480::,2a00:8480:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:84a0::,2a00:84a0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:84c0::,2a00:84c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:84e0::,2a00:84e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:8500::,2a00:8500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8520::,2a00:8520:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a00:8540::,2a00:8540:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8560::,2a00:8560:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:8580::,2a00:8580:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:85a0::,2a00:85a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:85c0::,2a00:85c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:85e0::,2a00:85e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:8600::,2a00:8600:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8640::,2a00:8647:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8660::,2a00:8660:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8680::,2a00:8680:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:86a0::,2a00:86a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:86c0::,2a00:86c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:86e0::,2a00:86e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:8700::,2a00:8700:ffff:ffff:ffff:ffff:ffff:ffff,ME +2a00:8720::,2a00:8720:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:8740::,2a00:8740:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8760::,2a00:8760:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8780::,2a00:8780:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:87a0::,2a00:87a0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:87c0::,2a00:87c0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:87e0::,2a00:87e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8800::,2a00:8800:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8820::,2a00:8820:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:8840::,2a00:8840:ffff:ffff:ffff:ffff:ffff:ffff,UZ +2a00:8880::,2a00:8880:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:88a0::,2a00:88a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:88c0::,2a00:88c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:88e0::,2a00:88e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8900::,2a00:8900:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8920::,2a00:8920:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8940::,2a00:8940:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8960::,2a00:8960:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8980::,2a00:8980:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:89a0::,2a00:89a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:89c0::,2a00:89c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:89e0::,2a00:89e0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:8a00::,2a00:8a00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:8a20::,2a00:8a20:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:8a40::,2a00:8a40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:8a80::,2a00:8a87:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:8aa0::,2a00:8aa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8ac0::,2a00:8ac0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:8ae0::,2a00:8ae0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8b00::,2a00:8b00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8b20::,2a00:8b20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8b60::,2a00:8b60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8b80::,2a00:8b80:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:8ba0::,2a00:8ba0:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a00:8bc0::,2a00:8bc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8be0::,2a00:8be0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:8c00::,2a00:8c00:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:8c20::,2a00:8c20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8c40::,2a00:8c40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8c60::,2a00:8c60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:8c80::,2a00:8c80:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:8ca0::,2a00:8ca0:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:8cc0::,2a00:8cc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:8ce0::,2a00:8ce0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:8d00::,2a00:8d00:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:8d40::,2a00:8d40:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:8d60::,2a00:8d60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:8d80::,2a00:8d80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:8dc0::,2a00:8dc0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:8de0::,2a00:8de0:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a00:8e00::,2a00:8e00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8e20::,2a00:8e20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:8e40::,2a00:8e40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8e60::,2a00:8e60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8ea0::,2a00:8ea0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:8ec0::,2a00:8ec0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:8ee0::,2a00:8ee7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:8f00::,2a00:8f00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:8f20::,2a00:8f20:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:8f40::,2a00:8f40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8f60::,2a00:8f60:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:8fa0::,2a00:8fa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8fc0::,2a00:8fc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:8fe0::,2a00:8fe0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:9000::,2a00:9000:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:9020::,2a00:9020:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:9040::,2a00:9040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9060::,2a00:9060:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:9080::,2a00:9080:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:90a0::,2a00:90a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:90c0::,2a00:90c7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:9100::,2a00:9100:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:9120::,2a00:9120:ffff:ffff:ffff:ffff:ffff:ffff,OM +2a00:9140::,2a00:9140:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:9160::,2a00:9160:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:9180::,2a00:9180:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:91a0::,2a00:91a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:91c0::,2a00:91c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:91e0::,2a00:91e0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:9200::,2a00:9200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:9220::,2a00:9220:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:9240::,2a00:9240:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a00:9260::,2a00:9260:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:9280::,2a00:9280:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:92a0::,2a00:92a7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:92c0::,2a00:92c0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:92e0::,2a00:92e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9300::,2a00:93ff:ffff:ffff:ffff:ffff:ffff:ffff,SX +2a00:9400::,2a00:9400:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9420::,2a00:9420:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:9440::,2a00:9440:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:9460::,2a00:9467:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9480::,2a00:9480:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:94a0::,2a00:94a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:94c0::,2a00:94c0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:94e0::,2a00:94e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9500::,2a00:9500:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:9520::,2a00:9520:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:9540::,2a00:9540:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:9560::,2a00:9560:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:9580::,2a00:9580:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:95a0::,2a00:95a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:95c0::,2a00:95c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:95e0::,2a00:95e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9600::,2a00:9600:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9620::,2a00:9620:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:9640::,2a00:9640:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:9680::,2a00:9680:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:96a0::,2a00:96a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:96c0::,2a00:96c0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:96e0::,2a00:96e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:9700::,2a00:9700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:9720::,2a00:9720:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:9740::,2a00:9740:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:9760::,2a00:9760:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:9780::,2a00:9780:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:97a0::,2a00:97a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:97c0::,2a00:97c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:97e0::,2a00:97e0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:9800::,2a00:9800:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:9820::,2a00:9820:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:9840::,2a00:9840:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:9860::,2a00:9860:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a00:9880::,2a00:9880:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:98a0::,2a00:98a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:98c0::,2a00:98c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:98e0::,2a00:98e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:9900::,2a00:9900:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a00:9920::,2a00:9920:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a00:9980::,2a00:9980:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:99a0::,2a00:99a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:99c0::,2a00:99c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:99e0::,2a00:99e7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:9a00::,2a00:9a00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:9a20::,2a00:9a20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:9a40::,2a00:9a40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:9a60::,2a00:9a60:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:9a80::,2a00:9a80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9aa0::,2a00:9aa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9ac0::,2a00:9ac0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:9ae0::,2a00:9ae0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:9b00::,2a00:9b00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:9b40::,2a00:9b40:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a00:9b60::,2a00:9b60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:9b80::,2a00:9b80:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:9ba0::,2a00:9ba0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9bc0::,2a00:9bc0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:9be0::,2a00:9be0:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a00:9c00::,2a00:9c00:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:9c20::,2a00:9c20:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:9c40::,2a00:9c40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:9c80::,2a00:9c80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:9ca0::,2a00:9ca0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:9cc0::,2a00:9cc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:9ce0::,2a00:9ce0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9d00::,2a00:9d00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9d20::,2a00:9d20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:9d40::,2a00:9d40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:9d60::,2a00:9d60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9d80::,2a00:9d87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:9dc0::,2a00:9dc0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:9de0::,2a00:9de0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9e00::,2a00:9e07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:9e20::,2a00:9e20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:9e40::,2a00:9e40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:9e60::,2a00:9e60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:9e80::,2a00:9e80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:9ea0::,2a00:9ea0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:9ec0::,2a00:9ec0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a00:9ee0::,2a00:9ee0:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:9f00::,2a00:9f00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:9f20::,2a00:9f20:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:9f40::,2a00:9f40:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a00:9f60::,2a00:9f60:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a00:9f80::,2a00:9f80:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:9fa0::,2a00:9fa0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:9fc0::,2a00:9fc0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:9fe0::,2a00:9fe7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:a000::,2a00:a000:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:a020::,2a00:a020:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a040::,2a00:a040:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a00:a060::,2a00:a060:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a080::,2a00:a080:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:a0a0::,2a00:a0a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a0c0::,2a00:a0c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:a0e0::,2a00:a0e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a100::,2a00:a100:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:a120::,2a00:a120:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:a140::,2a00:a140:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:a160::,2a00:a160:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:a180::,2a00:a180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a1a0::,2a00:a1a0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:a1c0::,2a00:a1c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:a1e0::,2a00:a1e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a200::,2a00:a200:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a220::,2a00:a220:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:a240::,2a00:a240:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:a260::,2a00:a260:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a00:a280::,2a00:a280:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a2a0::,2a00:a2a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:a2c0::,2a00:a2c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a2e0::,2a00:a2e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a300::,2a00:a300:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:a320::,2a00:a320:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:a340::,2a00:a340:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:a360::,2a00:a360:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:a380::,2a00:a380:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:a3a0::,2a00:a3a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:a3c0::,2a00:a3c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a3e0::,2a00:a3e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:a400::,2a00:a400:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a420::,2a00:a420:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:a440::,2a00:a440:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:a460::,2a00:a460:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:a480::,2a00:a480:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:a4a0::,2a00:a4a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:a4c0::,2a00:a4c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:a4e0::,2a00:a4e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a500::,2a00:a500:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:a520::,2a00:a520:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a540::,2a00:a540:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:a560::,2a00:a560:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:a580::,2a00:a580:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:a5a0::,2a00:a5a0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:a5c0::,2a00:a5c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:a5e0::,2a00:a5e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:a600::,2a00:a600:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a620::,2a00:a620:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:a640::,2a00:a640:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:a660::,2a00:a660:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:a680::,2a00:a680:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:a6a0::,2a00:a6a0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:a6c0::,2a00:a6c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:a6e0::,2a00:a6e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:a700::,2a00:a700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:a720::,2a00:a720:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:a740::,2a00:a740:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:a760::,2a00:a760:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:a780::,2a00:a780:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a7a0::,2a00:a7a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:a7c0::,2a00:a7c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:a7e0::,2a00:a7e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:a800::,2a00:a800:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:a820::,2a00:a820:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a840::,2a00:a840:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:a860::,2a00:a860:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a880::,2a00:a880:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a00:a8a0::,2a00:a8a0:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:a8e0::,2a00:a8e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a900::,2a00:a900:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:a920::,2a00:a920:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:a960::,2a00:a960:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:a980::,2a00:a987:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:a9a0::,2a00:a9a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:a9c0::,2a00:a9c0:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a00:a9e0::,2a00:a9e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:aa00::,2a00:aa00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:aa40::,2a00:aa40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:aa60::,2a00:aa60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:aa80::,2a00:aa80:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:aaa0::,2a00:aaa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:aac0::,2a00:aac0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:aae0::,2a00:aae0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ab00::,2a00:ab00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ab20::,2a00:ab20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:ab40::,2a00:ab40:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a00:ab60::,2a00:ab60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:ab80::,2a00:ab80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:aba0::,2a00:aba0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:abe0::,2a00:abe0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:ac00::,2a00:ac00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:ac20::,2a00:ac20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:ac40::,2a00:ac40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ac60::,2a00:ac60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ac80::,2a00:ac80:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:aca0::,2a00:aca0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:acc0::,2a00:acc0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:ace0::,2a00:ace0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:ad00::,2a00:ad00:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:ad20::,2a00:ad20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:ad40::,2a00:ad40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ad60::,2a00:ad60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ad80::,2a00:ad87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:adc0::,2a00:adc0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:ade0::,2a00:ade0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:ae00::,2a00:ae00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:ae20::,2a00:ae20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:ae40::,2a00:ae40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ae60::,2a00:ae60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:ae80::,2a00:ae80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:aea0::,2a00:aea0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:aec0::,2a00:aec0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:aee0::,2a00:aee0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:af00::,2a00:af00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:af20::,2a00:af20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:af40::,2a00:af40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:af60::,2a00:af60:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:af80::,2a00:af80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:afa0::,2a00:afa0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:afc0::,2a00:afc0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:afe0::,2a00:afe0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b000::,2a00:b000:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:b020::,2a00:b020:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a00:b040::,2a00:b040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b060::,2a00:b060:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:b080::,2a00:b080:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:b0a0::,2a00:b0a0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:b0c0::,2a00:b0c0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:b0e0::,2a00:b0e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b100::,2a00:b100:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b120::,2a00:b120:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b140::,2a00:b140:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:b160::,2a00:b160:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b180::,2a00:b180:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b1a0::,2a00:b1a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b1c0::,2a00:b1c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b1e0::,2a00:b1e0:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:b200::,2a00:b200:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:b220::,2a00:b220:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:b260::,2a00:b260:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:b280::,2a00:b280:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b2a0::,2a00:b2a0:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:b2e0::,2a00:b2e0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:b300::,2a00:b300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b320::,2a00:b320:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b340::,2a00:b340:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b360::,2a00:b360:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b380::,2a00:b380:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:b3a0::,2a00:b3a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:b3c0::,2a00:b3c0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:b3e0::,2a00:b3e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b400::,2a00:b407:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:b420::,2a00:b420:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:b440::,2a00:b440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b460::,2a00:b460:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:b480::,2a00:b480:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:b4a0::,2a00:b4a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b4c0::,2a00:b4c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b500::,2a00:b500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b520::,2a00:b520:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:b540::,2a00:b540:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:b560::,2a00:b560:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b580::,2a00:b580:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:b5a0::,2a00:b5a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b5c0::,2a00:b5c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:b5e0::,2a00:b5e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b600::,2a00:b607:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b640::,2a00:b640:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:b660::,2a00:b660:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:b680::,2a00:b680:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:b6a0::,2a00:b6a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:b6c0::,2a00:b6c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:b6e0::,2a00:b6e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b700::,2a00:b700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b720::,2a00:b720:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:b740::,2a00:b740:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:b760::,2a00:b760:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b780::,2a00:b780:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:b7a0::,2a00:b7a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:b7c0::,2a00:b7c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:b7e0::,2a00:b7e0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a00:b800::,2a00:b800:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a00:b820::,2a00:b820:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:b840::,2a00:b840:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b860::,2a00:b860:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a00:b880::,2a00:b880:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:b8a0::,2a00:b8a0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:b8c0::,2a00:b8c0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:b8e0::,2a00:b8e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:b900::,2a00:b900:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b920::,2a00:b920:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:b960::,2a00:b960:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:b980::,2a00:b981:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:b9a0::,2a00:b9a0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:b9c0::,2a00:b9c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:b9e0::,2a00:b9e0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a00:ba00::,2a00:ba00:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:ba20::,2a00:ba20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ba40::,2a00:ba40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:ba60::,2a00:ba60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:ba80::,2a00:ba80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:baa0::,2a00:baa0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:bac0::,2a00:bac0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:bae0::,2a00:bae0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:bb00::,2a00:bb00:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:bb20::,2a00:bb20:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:bb40::,2a00:bb40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:bb60::,2a00:bb60:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:bb80::,2a00:bb80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:bba0::,2a00:bba0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:bbc0::,2a00:bbc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:bbe0::,2a00:bbe0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:bc00::,2a00:bc00:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:bc20::,2a00:bc20:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a00:bc40::,2a00:bc40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:bc60::,2a00:bc60:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:bc80::,2a00:bc80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:bca0::,2a00:bca0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:bcc0::,2a00:bcc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:bce0::,2a00:bce0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:bd00::,2a00:bd00:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:bd20::,2a00:bd20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:bd40::,2a00:bd40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:bd60::,2a00:bd60:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:bd80::,2a00:bd80:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:bda0::,2a00:bda0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:bdc0::,2a00:bdc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:bde0::,2a00:bde0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:be00::,2a00:be00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:be20::,2a00:be20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:be40::,2a00:be40:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:be60::,2a00:be60:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:be80::,2a00:be80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:bea0::,2a00:bea0:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a00:bec0::,2a00:bec7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:bf00::,2a00:bf00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:bf20::,2a00:bf20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:bf40::,2a00:bf40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:bf60::,2a00:bf60:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:bf80::,2a00:bf80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:bfa0::,2a00:bfa0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:bfc0::,2a00:bfc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c000::,2a00:c000:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:c040::,2a00:c040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c060::,2a00:c060:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c080::,2a00:c080:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c0a0::,2a00:c0a0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:c0c0::,2a00:c0c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c0e0::,2a00:c0e0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:c100::,2a00:c100:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:c120::,2a00:c120:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:c140::,2a00:c140:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:c160::,2a00:c160:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a00:c180::,2a00:c180:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:c1a0::,2a00:c1a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:c1c0::,2a00:c1c0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:c1e0::,2a00:c1e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:c200::,2a00:c200:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:c220::,2a00:c220:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c240::,2a00:c240:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a00:c260::,2a00:c260:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:c280::,2a00:c280:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a00:c2a0::,2a00:c2a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c2c0::,2a00:c2c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c300::,2a00:c300:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c320::,2a00:c320:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:c340::,2a00:c340:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:c360::,2a00:c360:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c380::,2a00:c380:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:c3a0::,2a00:c3a0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a00:c3c0::,2a00:c3c0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:c3e0::,2a00:c3e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c400::,2a00:c400:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c420::,2a00:c420:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:c440::,2a00:c447:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:c460::,2a00:c460:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c4a0::,2a00:c4a0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:c4c0::,2a00:c4c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c4e0::,2a00:c4e0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:c500::,2a00:c500:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:c520::,2a00:c520:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c540::,2a00:c540:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:c560::,2a00:c560:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a00:c580::,2a00:c580:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:c5a0::,2a00:c5a0:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a00:c5c0::,2a00:c5c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c5e0::,2a00:c5e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:c600::,2a00:c600:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c620::,2a00:c620:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:c640::,2a00:c640:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:c660::,2a00:c660:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c680::,2a00:c680:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:c6a0::,2a00:c6a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c6c0::,2a00:c6c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c6e0::,2a00:c6e0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:c700::,2a00:c700:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a00:c720::,2a00:c720:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:c740::,2a00:c740:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:c760::,2a00:c760:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:c780::,2a00:c780:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:c7a0::,2a00:c7a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c7c0::,2a00:c7c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:c7e0::,2a00:c7e0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:c800::,2a00:c800:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:c820::,2a00:c820:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a00:c840::,2a00:c840:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:c860::,2a00:c860:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:c880::,2a00:c880:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:c8a0::,2a00:c8a7:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a00:c8c0::,2a00:c8c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c8e0::,2a00:c8e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:c900::,2a00:c900:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c920::,2a00:c920:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:c940::,2a00:c940:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:c960::,2a00:c960:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a00:c980::,2a00:c980:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:c9a0::,2a00:c9a0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:c9c0::,2a00:c9c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:c9e0::,2a00:c9e0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:ca00::,2a00:ca00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:ca20::,2a00:ca20:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:ca40::,2a00:ca40:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:ca60::,2a00:ca67:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:ca80::,2a00:ca80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:caa0::,2a00:caa0:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a00:cac0::,2a00:cac0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:cae0::,2a00:cae0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:cb00::,2a00:cb00:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:cb20::,2a00:cb20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:cb40::,2a00:cb40:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:cb60::,2a00:cb60:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:cb80::,2a00:cb80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:cba0::,2a00:cba0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:cbc0::,2a00:cbc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:cbe0::,2a00:cbe0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:cc00::,2a00:cc00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:cc20::,2a00:cc20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:cc40::,2a00:cc40:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a00:cc60::,2a00:cc60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:cc80::,2a00:cc80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:cca0::,2a00:cca0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:ccc0::,2a00:ccc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:cce0::,2a00:cce0:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a00:cd00::,2a00:cd00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:cd20::,2a00:cd20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:cd40::,2a00:cd40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:cd60::,2a00:cd60:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:cd80::,2a00:cd80:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:cda0::,2a00:cda0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:cdc0::,2a00:cdc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:cde0::,2a00:cde0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ce00::,2a00:ce00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:ce20::,2a00:ce27:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:ce40::,2a00:ce40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ce60::,2a00:ce60:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:ce80::,2a00:ce80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:cea0::,2a00:cea0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:cec0::,2a00:cec0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:cee0::,2a00:cee7:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a00:cf00::,2a00:cf00:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:cf20::,2a00:cf20:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:cf40::,2a00:cf40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:cf60::,2a00:cf60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:cf80::,2a00:cf80:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:cfa0::,2a00:cfa0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:cfc0::,2a00:cfc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:cfe0::,2a00:cfe0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:d000::,2a00:d000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d020::,2a00:d020:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:d040::,2a00:d040:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:d060::,2a00:d060:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:d080::,2a00:d080:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:d0a0::,2a00:d0a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:d0c0::,2a00:d0c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:d0e0::,2a00:d0e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:d100::,2a00:d100:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:d120::,2a00:d120:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d140::,2a00:d140:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a00:d160::,2a00:d160:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:d180::,2a00:d180:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a00:d1a0::,2a00:d1a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:d1c0::,2a00:d1c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d1e0::,2a00:d1e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:d200::,2a00:d200:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d240::,2a00:d240:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:d260::,2a00:d267:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d280::,2a00:d280:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:d2a0::,2a00:d2a7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d2c0::,2a00:d2c0:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a00:d2e0::,2a00:d2e7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d300::,2a00:d300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d320::,2a00:d327:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d340::,2a00:d340:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d360::,2a00:d367:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d380::,2a00:d380:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d3a0::,2a00:d3a7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d3e0::,2a00:d3e7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d400::,2a00:d400:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:d420::,2a00:d427:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d440::,2a00:d447:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:d480::,2a00:d480:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:d4a0::,2a00:d4a7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d4c0::,2a00:d4c0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:d4e0::,2a00:d4e7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d500::,2a00:d500:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:d520::,2a00:d527:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d540::,2a00:d540:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d560::,2a00:d567:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:d580::,2a00:d580:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:d5a0::,2a00:d5a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d5c0::,2a00:d5c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:d5e0::,2a00:d5e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d600::,2a00:d600:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d620::,2a00:d620:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:d640::,2a00:d640:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d660::,2a00:d660:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:d680::,2a00:d680:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d6a0::,2a00:d6a0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:d6c0::,2a00:d6c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:d6e0::,2a00:d6e0:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a00:d700::,2a00:d700:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d720::,2a00:d727:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d740::,2a00:d747:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:d780::,2a00:d780:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:d7a0::,2a00:d7a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:d7c0::,2a00:d7c0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:d7e0::,2a00:d7e0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:d800::,2a00:d800:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a00:d820::,2a00:d820:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:d840::,2a00:d840:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:d860::,2a00:d860:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:d880::,2a00:d880:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d8a0::,2a00:d8a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d8c0::,2a00:d8c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:d8e0::,2a00:d8e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:d900::,2a00:d900:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:d920::,2a00:d920:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:d940::,2a00:d940:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:d960::,2a00:d967:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:d980::,2a00:d980:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:d9a0::,2a00:d9a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:d9c0::,2a00:d9c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:da00::,2a00:da00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:da20::,2a00:da20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:da40::,2a00:da40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:da60::,2a00:da60:ffff:ffff:ffff:ffff:ffff:ffff,LI +2a00:da80::,2a00:da80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:daa0::,2a00:daa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:dac0::,2a00:dac0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:dae0::,2a00:dae0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:db00::,2a00:db00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:db20::,2a00:db20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:db40::,2a00:db40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:db60::,2a00:db60:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:db80::,2a00:db80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:dba0::,2a00:dba0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:dbc0::,2a00:dbc0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:dbe0::,2a00:dbe0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:dc00::,2a00:dc00:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:dc20::,2a00:dc20:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a00:dc40::,2a00:dc40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:dc60::,2a00:dc60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:dc80::,2a00:dc80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:dca0::,2a00:dca7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:dcc0::,2a00:dcc7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:dd00::,2a00:dd00:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:dd20::,2a00:dd20:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:dd40::,2a00:dd40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:dd60::,2a00:dd60:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:dda0::,2a00:dda0:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a00:ddc0::,2a00:ddc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:dde0::,2a00:dde0:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a00:de00::,2a00:de00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:de20::,2a00:de20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:de40::,2a00:de40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:de60::,2a00:de60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:de80::,2a00:de80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:dea0::,2a00:dea0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:dec0::,2a00:dec0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:dee0::,2a00:dee0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:df00::,2a00:df00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:df20::,2a00:df20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:df40::,2a00:df40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:df60::,2a00:df60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:df80::,2a00:df80:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:dfa0::,2a00:dfa0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:dfc0::,2a00:dfc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:dfe0::,2a00:dfe7:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:e000::,2a00:e000:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a00:e020::,2a00:e020:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:e040::,2a00:e040:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:e060::,2a00:e060:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e080::,2a00:e080:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:e0a0::,2a00:e0a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2a00:e0c0::,2a00:e0c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e100::,2a00:e100:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e120::,2a00:e120:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e140::,2a00:e140:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:e160::,2a00:e160:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:e180::,2a00:e180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e1a0::,2a00:e1a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e1c0::,2a00:e1c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e1e0::,2a00:e1e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:e200::,2a00:e200:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:e220::,2a00:e220:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:e240::,2a00:e240:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e260::,2a00:e260:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e280::,2a00:e280:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:e2a0::,2a00:e2a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e2c0::,2a00:e2c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:e2e0::,2a00:e2e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:e300::,2a00:e300:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:e320::,2a00:e320:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e340::,2a00:e340:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e360::,2a00:e360:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:e380::,2a00:e380:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:e3a0::,2a00:e3a0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:e3e0::,2a00:e3e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e400::,2a00:e407:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e440::,2a00:e440:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e460::,2a00:e460:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e480::,2a00:e480:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:e4a0::,2a00:e4a0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:e4c0::,2a00:e4c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:e500::,2a00:e500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e520::,2a00:e520:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e540::,2a00:e540:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:e560::,2a00:e560:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:e580::,2a00:e580:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:e5a0::,2a00:e5a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:e5c0::,2a00:e5c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:e5e0::,2a00:e5e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:e600::,2a00:e600:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:e620::,2a00:e620:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e640::,2a00:e640:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:e660::,2a00:e660:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:e680::,2a00:e680:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:e6a0::,2a00:e6a0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a00:e6c0::,2a00:e6c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:e6e0::,2a00:e6e0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:e700::,2a00:e700:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:e720::,2a00:e720:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:e740::,2a00:e740:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e760::,2a00:e760:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:e780::,2a00:e780:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:e7a0::,2a00:e7a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e7c0::,2a00:e7c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:e7e0::,2a00:e7e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:e800::,2a00:e807:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:e840::,2a00:e840:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:e860::,2a00:e860:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a00:e880::,2a00:e880:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:e8c0::,2a00:e8c0:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a00:e8e0::,2a00:e8e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:e900::,2a00:e900:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:e920::,2a00:e920:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:e940::,2a00:e940:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:e960::,2a00:e960:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:e980::,2a00:e980:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e9a0::,2a00:e9a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:e9c0::,2a00:e9c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:e9e0::,2a00:e9e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ea00::,2a00:ea00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:ea20::,2a00:ea20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ea40::,2a00:ea40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ea60::,2a00:ea60:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:ea80::,2a00:ea80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:eaa0::,2a00:eaa0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:eac0::,2a00:eac0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:eae0::,2a00:eae0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:eb00::,2a00:eb00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:eb20::,2a00:eb20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:eb40::,2a00:eb40:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:eb60::,2a00:eb60:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:eb80::,2a00:eb80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:ebc0::,2a00:ebc0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:ebe0::,2a00:ebe0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ec00::,2a00:ec00:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:ec20::,2a00:ec23:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:ec40::,2a00:ec47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:ec80::,2a00:ec80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:eca0::,2a00:eca0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:ecc0::,2a00:ecc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:ece0::,2a00:ece0:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a00:ed00::,2a00:ed00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ed20::,2a00:ed20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ed40::,2a00:ed40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ed60::,2a00:ed60:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:ed80::,2a00:ed80:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:eda0::,2a00:eda0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:ede0::,2a00:ede0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:ee00::,2a00:ee00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ee20::,2a00:ee20:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:ee40::,2a00:ee40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:ee60::,2a00:ee60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:eea0::,2a00:eea0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:eec0::,2a00:eec0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:eee0::,2a00:eee0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:ef00::,2a00:ef00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:ef20::,2a00:ef20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:ef40::,2a00:ef40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:ef60::,2a00:ef67:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:ef80::,2a00:ef80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:efa0::,2a00:efa0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:efc0::,2a00:efc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:efe0::,2a00:efe0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:f000::,2a00:f000:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a00:f020::,2a00:f020:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:f040::,2a00:f040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f060::,2a00:f060:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:f080::,2a00:f080:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:f0a0::,2a00:f0a7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:f0c0::,2a00:f0c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f0e0::,2a00:f0e0:ffff:ffff:ffff:ffff:ffff:ffff,QA +2a00:f100::,2a00:f100:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:f120::,2a00:f120:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:f140::,2a00:f140:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f160::,2a00:f160:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f180::,2a00:f180:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f1a0::,2a00:f1a0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:f1c0::,2a00:f1c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f1e0::,2a00:f1e0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:f200::,2a00:f200:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:f220::,2a00:f220:ffff:ffff:ffff:ffff:ffff:ffff,ME +2a00:f260::,2a00:f260:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a00:f280::,2a00:f280:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:f2a0::,2a00:f2a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f2c0::,2a00:f2c0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:f2e0::,2a00:f2e0:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a00:f300::,2a00:f300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f320::,2a00:f320:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:f340::,2a00:f340:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:f360::,2a00:f360:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:f380::,2a00:f380:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:f3a0::,2a00:f3a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:f3c0::,2a00:f3c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f3e0::,2a00:f3e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f400::,2a00:f4ff:ffff:ffff:ffff:ffff:ffff:ffff,RW +2a00:f500::,2a00:f507:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a00:f520::,2a00:f520:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f540::,2a00:f540:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f560::,2a00:f560:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:f580::,2a00:f580:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a00:f5a0::,2a00:f5a0:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a00:f5c0::,2a00:f5c0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:f5e0::,2a00:f5e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:f600::,2a00:f600:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:f620::,2a00:f620:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a00:f640::,2a00:f640:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:f660::,2a00:f660:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f680::,2a00:f680:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:f6a0::,2a00:f6a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f6c0::,2a00:f6c0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:f6e0::,2a00:f6e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f700::,2a00:f707:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f720::,2a00:f720:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a00:f760::,2a00:f760:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:f780::,2a00:f780:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:f7a0::,2a00:f7a0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a00:f7c0::,2a00:f7c7:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a00:f800::,2a00:f800:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:f820::,2a00:f827:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f860::,2a00:f860:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:f880::,2a00:f880:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f8a0::,2a00:f8a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f8c0::,2a00:f8c0:ffff:ffff:ffff:ffff:ffff:ffff,LI +2a00:f8e0::,2a00:f8e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:f900::,2a00:f900:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a00:f920::,2a00:f920:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f940::,2a00:f940:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f960::,2a00:f960:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a00:f980::,2a00:f980:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a00:f9a0::,2a00:f9a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:f9c0::,2a00:f9c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:f9e0::,2a00:f9e0:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a00:fa00::,2a00:fa00:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a00:fa20::,2a00:fa20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:fa40::,2a00:fa40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fa60::,2a00:fa60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:fa80::,2a00:fa80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:faa0::,2a00:faa0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a00:fac0::,2a00:fac0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fae0::,2a00:fae0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:fb00::,2a00:fb00:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:fb20::,2a00:fb20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:fb40::,2a00:fb40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a00:fb60::,2a00:fb60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a00:fb80::,2a00:fb80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fba0::,2a00:fba0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:fbc0::,2a00:fbc0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:fbe0::,2a00:fbe0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:fc00::,2a00:fc00:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:fc20::,2a00:fc20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:fc40::,2a00:fc40:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a00:fc60::,2a00:fc60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:fc80::,2a00:fc80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:fca0::,2a00:fca0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a00:fcc0::,2a00:fcc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fce0::,2a00:fce0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:fd00::,2a00:fd00:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a00:fd20::,2a00:fd20:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a00:fd40::,2a00:fd40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:fd60::,2a00:fd60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:fd80::,2a00:fd80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:fda0::,2a00:fda0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fdc0::,2a00:fdc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:fde0::,2a00:fde0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:fe00::,2a00:fe00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fe20::,2a00:fe20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a00:fe40::,2a00:fe40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a00:fe60::,2a00:fe60:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a00:fe80::,2a00:fe80:ffff:ffff:ffff:ffff:ffff:ffff,ME +2a00:fea0::,2a00:fea0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a00:fec0::,2a00:fec0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a00:fee0::,2a00:fee0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ff00::,2a00:ff00:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a00:ff20::,2a00:ff20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a00:ff40::,2a00:ff40:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a00:ff60::,2a00:ff60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a00:ff80::,2a00:ff80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a00:ffa0::,2a00:ffa0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a00:ffc0::,2a00:ffc0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a00:ffe0::,2a00:ffe0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01::,2a01::ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8::,2a01:8:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a01:10::,2a01:10:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a01:18::,2a01:18:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:20::,2a01:20:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:28::,2a01:28:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:30::,2a01:30:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:38::,2a01:38:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:40::,2a01:40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:48::,2a01:48:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:50::,2a01:50:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:58::,2a01:58:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:68::,2a01:68:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:70::,2a01:70:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:78::,2a01:78:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:80::,2a01:80:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:88::,2a01:88:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:90::,2a01:90:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:98::,2a01:98:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a0::,2a01:a0:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a01:a8::,2a01:a8:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:b0::,2a01:b1:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:b8::,2a01:b8:ffff:ffff:ffff:ffff:ffff:ffff,VA +2a01:c0::,2a01:c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:c8::,2a01:c8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:d0::,2a01:d0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:d8::,2a01:d8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:e0::,2a01:e0:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:e8::,2a01:e8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:f0::,2a01:f0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:f8::,2a01:f8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:100::,2a01:100:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:108::,2a01:108:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:120::,2a01:120:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:130::,2a01:130:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:138::,2a01:138:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:140::,2a01:140:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:148::,2a01:148:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:150::,2a01:150:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:158::,2a01:158:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:160::,2a01:160:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:168::,2a01:168:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:170::,2a01:170:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:178::,2a01:178:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:180::,2a01:180:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a01:188::,2a01:188:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:190::,2a01:197:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:198::,2a01:198:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:1a0::,2a01:1a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:1a8::,2a01:1a8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:1b0::,2a01:1b0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:1b8::,2a01:1b8:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:1c0::,2a01:1c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:1c8::,2a01:1c8:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:1d0::,2a01:1d0:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a01:1d8::,2a01:1d8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:1e0::,2a01:1e0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:1e8::,2a01:1e8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:1f0::,2a01:1f0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:1f8::,2a01:1f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:200::,2a01:200:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:208::,2a01:208:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:210::,2a01:210:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:220::,2a01:220:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:228::,2a01:228:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:230::,2a01:230:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:238::,2a01:238:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:240::,2a01:240:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:248::,2a01:248:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:250::,2a01:250:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:258::,2a01:258:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:260::,2a01:260:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a01:268::,2a01:268:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:270::,2a01:270:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:278::,2a01:27f:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:280::,2a01:287:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:288::,2a01:288:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:290::,2a01:290:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:298::,2a01:29f:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:2a0::,2a01:2a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:2a8::,2a01:2af:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:2b0::,2a01:2b7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:2b8::,2a01:2b8:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a01:2c0::,2a01:2c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:2c8::,2a01:2c8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:2d0::,2a01:2d0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:2d8::,2a01:2d8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:2e0::,2a01:2ef:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:308::,2a01:308:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:310::,2a01:310:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:320::,2a01:320:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a01:328::,2a01:328:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:330::,2a01:330:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:338::,2a01:338:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:340::,2a01:340:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:348::,2a01:348:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:350::,2a01:350:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:358::,2a01:358:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:360::,2a01:360:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:368::,2a01:36f:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:378::,2a01:378:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:380::,2a01:380:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:388::,2a01:38f:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:390::,2a01:390:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:398::,2a01:398:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:3a0::,2a01:3a7:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:3a8::,2a01:3a8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:3b8::,2a01:3b8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:3c8::,2a01:3c8:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:3d8::,2a01:3d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:3e8::,2a01:3e8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:3f0::,2a01:3f0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:3f8::,2a01:3f8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:400::,2a01:400:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:408::,2a01:408:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:410::,2a01:410:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:418::,2a01:418:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:420::,2a01:420:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:428::,2a01:428:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:430::,2a01:430:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:438::,2a01:438:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:440::,2a01:447:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:448::,2a01:448:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:450::,2a01:450:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:458::,2a01:458:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:460::,2a01:460:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:468::,2a01:468:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:470::,2a01:477:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:478::,2a01:47f:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a01:480::,2a01:480:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:488::,2a01:488:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:490::,2a01:490:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:498::,2a01:498:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:4a0::,2a01:4a8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4b0::,2a01:4b0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:4c0::,2a01:4c0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:4c8::,2a01:4cf:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4d0::,2a01:4d0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4d8::,2a01:4d8:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:4e0::,2a01:4e7:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a01:4e8::,2a01:4e8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4f0::,2a01:4f0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:4f8::,2a01:4ff:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:500::,2a01:500:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:508::,2a01:508:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:510::,2a01:510:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:518::,2a01:518:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:520::,2a01:520:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:528::,2a01:528:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:530::,2a01:530:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:538::,2a01:538:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:540::,2a01:540:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:548::,2a01:548:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:550::,2a01:550:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:558::,2a01:558:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:560::,2a01:567:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:568::,2a01:570:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:578::,2a01:578:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:580::,2a01:580:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:590::,2a01:590:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:598::,2a01:59f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5a0::,2a01:5a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5a8::,2a01:5a8:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:5b0::,2a01:5b0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5b8::,2a01:5bf:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a01:5c0::,2a01:5c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5c8::,2a01:5c8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5d0::,2a01:5d0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:5d8::,2a01:5df:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:5e0::,2a01:5e0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:5f0::,2a01:5f0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:5f8::,2a01:5f8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:600::,2a01:600:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:608::,2a01:608:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a01:610::,2a01:610:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:618::,2a01:618:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:620::,2a01:620:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:628::,2a01:628:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:630::,2a01:630:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:640::,2a01:647:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:648::,2a01:648:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:650::,2a01:650:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:658::,2a01:658:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:660::,2a01:667:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:668::,2a01:668:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:670::,2a01:670:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:678::,2a01:67f:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:680::,2a01:680:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:688::,2a01:688:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:690::,2a01:690:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:698::,2a01:698:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:6a0::,2a01:6a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:6a8::,2a01:6a8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:6b0::,2a01:6b0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:6b8::,2a01:6b8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6c0::,2a01:6c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6c8::,2a01:6c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6d0::,2a01:6d0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:6d8::,2a01:6d8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6e0::,2a01:6e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6e8::,2a01:6e8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6f0::,2a01:6f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6f8::,2a01:6f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:700::,2a01:700:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:710::,2a01:710:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:718::,2a01:718:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:720::,2a01:720:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:728::,2a01:72f:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:730::,2a01:730:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:738::,2a01:738:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:740::,2a01:740:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:748::,2a01:748:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:750::,2a01:750:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:758::,2a01:758:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:760::,2a01:760:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:768::,2a01:768:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:770::,2a01:770:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:778::,2a01:778:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:780::,2a01:780:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:788::,2a01:788:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:790::,2a01:790:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:798::,2a01:79f:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:7a0::,2a01:7a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7a8::,2a01:7a8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7b0::,2a01:7b0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:7b8::,2a01:7b8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7c0::,2a01:7c0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:7c8::,2a01:7c8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:7d0::,2a01:7d0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:7d8::,2a01:7d8:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a01:7e0::,2a01:7e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7e8::,2a01:7e8:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:7f0::,2a01:7f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7f8::,2a01:7f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:800::,2a01:8ff:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:c00::,2a01:c3f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:e00::,2a01:eff:ffff:ffff:ffff:ffff:ffff:ffff,SX +2a01:1000::,2a01:17ff:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:2000::,2a01:2fff:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:4000::,2a01:4000:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a01:4020::,2a01:4020:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4040::,2a01:4040:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:4060::,2a01:4060:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4080::,2a01:4080:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:40a0::,2a01:40a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:40c0::,2a01:40c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:40e0::,2a01:40e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:4120::,2a01:4120:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:4160::,2a01:4160:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a01:41a0::,2a01:41a0:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a01:41c0::,2a01:41c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:41e0::,2a01:41e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4200::,2a01:4207:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4240::,2a01:4240:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:4260::,2a01:4260:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:4280::,2a01:4280:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a01:42a0::,2a01:42a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:42c0::,2a01:42c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:42e0::,2a01:42e0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:4300::,2a01:4300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4320::,2a01:4320:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4340::,2a01:4340:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:4360::,2a01:4360:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:4380::,2a01:4380:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:43a0::,2a01:43a0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:43c0::,2a01:43c0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a01:43e0::,2a01:43e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4400::,2a01:4400:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:4420::,2a01:4420:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4440::,2a01:4440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4460::,2a01:4460:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4480::,2a01:4480:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:44a0::,2a01:44a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:44c0::,2a01:44c0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:44e0::,2a01:44e0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:4500::,2a01:4500:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a01:4520::,2a01:4520:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:4540::,2a01:4547:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:4580::,2a01:4587:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:45c0::,2a01:45c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:45e0::,2a01:45e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:4600::,2a01:4600:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a01:4620::,2a01:4620:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4640::,2a01:4640:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:4660::,2a01:4660:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:4680::,2a01:4680:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a01:46a0::,2a01:46a0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a01:46c0::,2a01:46c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:46e0::,2a01:46e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4720::,2a01:4720:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4740::,2a01:4740:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a01:4760::,2a01:4760:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4780::,2a01:4780:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a01:47a0::,2a01:47a0:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a01:47c0::,2a01:47c0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:47e0::,2a01:47e0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:4800::,2a01:4800:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4820::,2a01:4820:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:4840::,2a01:4840:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:4860::,2a01:4860:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a01:4880::,2a01:4880:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:48a0::,2a01:48a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:48c0::,2a01:48c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:48e0::,2a01:48e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:4900::,2a01:4900:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a01:4920::,2a01:4920:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4940::,2a01:4940:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4960::,2a01:4960:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:4980::,2a01:4980:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:49a0::,2a01:49a0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:49c0::,2a01:49c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:49e0::,2a01:49e0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a01:4a00::,2a01:4a00:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a01:4a20::,2a01:4a20:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:4a40::,2a01:4a40:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:4a60::,2a01:4a60:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:4a80::,2a01:4a80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:4aa0::,2a01:4aa0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:4ac0::,2a01:4ac0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:4ae0::,2a01:4ae0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4b00::,2a01:4b00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4b20::,2a01:4b20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4b40::,2a01:4b40:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:4b60::,2a01:4b60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4b80::,2a01:4b80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:4ba0::,2a01:4ba0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a01:4bc0::,2a01:4bc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4be0::,2a01:4be0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:4c00::,2a01:4c00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:4c20::,2a01:4c20:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:4c40::,2a01:4c40:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:4c60::,2a01:4c60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4c80::,2a01:4c80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4ca0::,2a01:4ca0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4cc0::,2a01:4cc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4d00::,2a01:4d00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4d20::,2a01:4d20:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:4d40::,2a01:4d40:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:4d60::,2a01:4d60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:4d80::,2a01:4d80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4da0::,2a01:4da0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4dc0::,2a01:4dc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4de0::,2a01:4de0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4e00::,2a01:4e00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:4e20::,2a01:4e20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:4e40::,2a01:4e40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4e60::,2a01:4e60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:4e80::,2a01:4e80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:4ea0::,2a01:4ea0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4ec0::,2a01:4ec0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:4ee0::,2a01:4ee0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4f00::,2a01:4f00:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a01:4f20::,2a01:4f20:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:4f40::,2a01:4f40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:4f60::,2a01:4f60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:4f80::,2a01:4f80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4fa0::,2a01:4fa0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:4fc0::,2a01:4fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:4fe0::,2a01:4fe0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5000::,2a01:5000:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5020::,2a01:5020:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5040::,2a01:5047:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5080::,2a01:5080:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:50a0::,2a01:50a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:50c0::,2a01:50c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:50e0::,2a01:50e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5100::,2a01:5100:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:5120::,2a01:5120:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a01:5140::,2a01:5140:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5160::,2a01:5160:ffff:ffff:ffff:ffff:ffff:ffff,ME +2a01:5180::,2a01:5180:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:51a0::,2a01:51a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:51c0::,2a01:51c7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:5200::,2a01:5200:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:5220::,2a01:5220:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5240::,2a01:5240:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5260::,2a01:5260:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5280::,2a01:5280:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:52a0::,2a01:52a0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:52c0::,2a01:52c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:52e0::,2a01:52e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5300::,2a01:5300:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:5320::,2a01:5320:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:5340::,2a01:5340:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5360::,2a01:5360:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5380::,2a01:5380:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:53a0::,2a01:53a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:53c0::,2a01:53c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:53e0::,2a01:53e0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:5400::,2a01:5400:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5420::,2a01:5420:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5440::,2a01:5440:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:5460::,2a01:5460:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5480::,2a01:5480:ffff:ffff:ffff:ffff:ffff:ffff,GG +2a01:54a0::,2a01:54a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:54c0::,2a01:54c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:54e0::,2a01:54e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5500::,2a01:5507:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:5540::,2a01:5540:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:5560::,2a01:5560:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5580::,2a01:5580:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:55a0::,2a01:55a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:55c0::,2a01:55c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:55e0::,2a01:55e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5600::,2a01:5600:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:5620::,2a01:5620:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5640::,2a01:5640:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5660::,2a01:5660:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:5680::,2a01:5680:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:56a0::,2a01:56a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:56c0::,2a01:56c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:56e0::,2a01:56e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:5700::,2a01:5700:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:5720::,2a01:5720:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5740::,2a01:5740:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:5760::,2a01:5760:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5780::,2a01:5780:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:57a0::,2a01:57a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:57c0::,2a01:57c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:57e0::,2a01:57e0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a01:5800::,2a01:5800:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:5820::,2a01:5820:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5840::,2a01:5840:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:5860::,2a01:5860:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:58a0::,2a01:58a0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a01:58e0::,2a01:58e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5900::,2a01:5900:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:5920::,2a01:5920:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5940::,2a01:5940:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5960::,2a01:5960:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:5980::,2a01:5980:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:59a0::,2a01:59a7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:59c0::,2a01:59c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:59e0::,2a01:59e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5a00::,2a01:5a00:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:5a20::,2a01:5a20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:5a40::,2a01:5a40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5a60::,2a01:5a60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5a80::,2a01:5a80:ffff:ffff:ffff:ffff:ffff:ffff,US +2a01:5aa0::,2a01:5aa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5ac0::,2a01:5ac0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5ae0::,2a01:5ae0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5b00::,2a01:5b00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5b20::,2a01:5b20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:5b40::,2a01:5b40:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:5b60::,2a01:5b60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5b80::,2a01:5b80:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:5ba0::,2a01:5ba0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5bc0::,2a01:5bc0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:5be0::,2a01:5be0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5c00::,2a01:5c00:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:5c20::,2a01:5c20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5c40::,2a01:5c40:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:5c60::,2a01:5c60:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:5c80::,2a01:5c80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5ca0::,2a01:5ca0:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a01:5cc0::,2a01:5cc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:5ce0::,2a01:5ce0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5d00::,2a01:5d00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5d20::,2a01:5d20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5d40::,2a01:5d40:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:5d60::,2a01:5d67:ffff:ffff:ffff:ffff:ffff:ffff,TJ +2a01:5d80::,2a01:5d80:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a01:5da0::,2a01:5da0:ffff:ffff:ffff:ffff:ffff:ffff,ME +2a01:5dc0::,2a01:5dc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:5de0::,2a01:5de0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5e00::,2a01:5e00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:5e20::,2a01:5e20:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:5e40::,2a01:5e40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:5e60::,2a01:5e60:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a01:5e80::,2a01:5e80:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:5ea0::,2a01:5ea0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5ec0::,2a01:5ec0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:5ee0::,2a01:5ee0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:5f00::,2a01:5f00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5f20::,2a01:5f20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5f40::,2a01:5f40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5f60::,2a01:5f60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5f80::,2a01:5f80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:5fa0::,2a01:5fa0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:5fc0::,2a01:5fc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:5fe0::,2a01:5fe0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:6000::,2a01:6000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6020::,2a01:6020:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6040::,2a01:6040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6060::,2a01:6060:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:6080::,2a01:6080:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:60a0::,2a01:60a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:60c0::,2a01:60c0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:60e0::,2a01:60e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6100::,2a01:6100:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:6120::,2a01:6120:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6140::,2a01:6140:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:6160::,2a01:6160:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6180::,2a01:6180:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:61a0::,2a01:61a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:61c0::,2a01:61c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:61e0::,2a01:61e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6200::,2a01:6200:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:6220::,2a01:6220:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:6240::,2a01:6240:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6260::,2a01:6260:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:6280::,2a01:6280:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:62a0::,2a01:62a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:62c0::,2a01:62c0:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a01:6300::,2a01:6300:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:6320::,2a01:6320:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a01:6340::,2a01:6347:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:6360::,2a01:6360:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:6380::,2a01:6380:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:63a0::,2a01:63a0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:63c0::,2a01:63c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:63e0::,2a01:63e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:6400::,2a01:6400:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:6420::,2a01:6420:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6440::,2a01:6440:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a01:6460::,2a01:6460:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6480::,2a01:6480:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a01:64a0::,2a01:64a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:64c0::,2a01:64c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:64e0::,2a01:64e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6500::,2a01:6500:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a01:6520::,2a01:6520:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6540::,2a01:6540:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6560::,2a01:6560:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:6580::,2a01:6580:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:65a0::,2a01:65a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:65c0::,2a01:65c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:65e0::,2a01:65e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6600::,2a01:6600:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6620::,2a01:6620:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:6640::,2a01:6647:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:6680::,2a01:6680:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:66a0::,2a01:66a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:66c0::,2a01:66c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:66e0::,2a01:66e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:6700::,2a01:6700:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a01:6720::,2a01:6720:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a01:6740::,2a01:6740:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6760::,2a01:6760:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:6780::,2a01:6780:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:67a0::,2a01:67a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:67c0::,2a01:67c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:67e0::,2a01:67e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6800::,2a01:6800:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:6820::,2a01:6820:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6840::,2a01:6840:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:6860::,2a01:6860:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6880::,2a01:6880:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:68a0::,2a01:68a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:68c0::,2a01:68c0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:68e0::,2a01:68e0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:6900::,2a01:6900:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:6920::,2a01:6920:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:6940::,2a01:6940:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6960::,2a01:6960:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6980::,2a01:6980:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:69a0::,2a01:69a0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:69c0::,2a01:69c0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:69e0::,2a01:69e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:6a00::,2a01:6a07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6a40::,2a01:6a40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:6a60::,2a01:6a60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6a80::,2a01:6a80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:6aa0::,2a01:6aa0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6ac0::,2a01:6ac0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6ae0::,2a01:6ae7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6b00::,2a01:6b00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6b20::,2a01:6b20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6b40::,2a01:6b40:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:6b60::,2a01:6b60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6b80::,2a01:6b80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:6ba0::,2a01:6ba0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6bc0::,2a01:6bc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6be0::,2a01:6be0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:6c00::,2a01:6c00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:6c20::,2a01:6c20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6c40::,2a01:6c40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:6c60::,2a01:6c60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6c80::,2a01:6c80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:6ca0::,2a01:6ca0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6cc0::,2a01:6cc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6ce0::,2a01:6ce0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:6d00::,2a01:6d00:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:6d20::,2a01:6d20:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:6d40::,2a01:6d40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:6d60::,2a01:6d60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:6d80::,2a01:6d80:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:6da0::,2a01:6da0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:6dc0::,2a01:6dc0:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a01:6de0::,2a01:6de0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6e00::,2a01:6e00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:6e20::,2a01:6e20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:6e40::,2a01:6e40:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a01:6e60::,2a01:6e60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6e80::,2a01:6e80:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:6ea0::,2a01:6ea0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6ec0::,2a01:6ec0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6ee0::,2a01:6ee0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:6f00::,2a01:6f07:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:6f20::,2a01:6f20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:6f40::,2a01:6f40:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:6f60::,2a01:6f60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:6f80::,2a01:6f80:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:6fa0::,2a01:6fa0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:6fc0::,2a01:6fc0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:6fe0::,2a01:6fe0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:7000::,2a01:7000:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:7020::,2a01:7020:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:7040::,2a01:7040:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:7060::,2a01:7060:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:7080::,2a01:7080:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:70a0::,2a01:70a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:70c0::,2a01:70c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:70e0::,2a01:70e0:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a01:7100::,2a01:7100:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:7120::,2a01:7120:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:7140::,2a01:7140:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:7160::,2a01:7160:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:7180::,2a01:7180:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:71a0::,2a01:71a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:71c0::,2a01:71c1:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:71e0::,2a01:71e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:7200::,2a01:7200:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:7220::,2a01:7220:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a01:7240::,2a01:7240:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:7260::,2a01:7260:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a01:7280::,2a01:7280:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:72a0::,2a01:72a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:72e0::,2a01:72e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:7300::,2a01:7300:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:7320::,2a01:7320:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:7340::,2a01:7340:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:7360::,2a01:7360:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a01:7380::,2a01:7380:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:73a0::,2a01:73a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:73c0::,2a01:73c0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a01:73e0::,2a01:73e0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:7400::,2a01:7400:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:7420::,2a01:7420:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7440::,2a01:7440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:7460::,2a01:7460:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7480::,2a01:7480:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:74a0::,2a01:74a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:74c0::,2a01:74c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:74e0::,2a01:74e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:7500::,2a01:7500:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:7520::,2a01:7520:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:7540::,2a01:7540:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:7560::,2a01:7560:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:7580::,2a01:7580:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:75a0::,2a01:75a0:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a01:75c0::,2a01:75c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7600::,2a01:7600:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:7620::,2a01:7620:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:7640::,2a01:7640:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:7660::,2a01:7660:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7680::,2a01:7680:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:76a0::,2a01:76a0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:76c0::,2a01:76c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:76e0::,2a01:76e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:7700::,2a01:7700:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7720::,2a01:7720:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:7740::,2a01:7740:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7760::,2a01:7760:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7780::,2a01:7780:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a01:77a0::,2a01:77a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:77c0::,2a01:77c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:77e0::,2a01:77e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:7800::,2a01:7800:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7820::,2a01:7820:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7840::,2a01:7840:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7860::,2a01:7860:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:7880::,2a01:7880:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:78a0::,2a01:78a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:78c0::,2a01:78c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:78e0::,2a01:78e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7900::,2a01:7900:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:7920::,2a01:7920:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:7940::,2a01:7940:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7960::,2a01:7960:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7980::,2a01:7980:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:79a0::,2a01:79a0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:79c0::,2a01:79c0:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a01:79e0::,2a01:79e0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:7a00::,2a01:7a00:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:7a20::,2a01:7a20:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a01:7a40::,2a01:7a40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7a60::,2a01:7a60:ffff:ffff:ffff:ffff:ffff:ffff,SM +2a01:7a80::,2a01:7a87:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:7ac0::,2a01:7ac0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:7ae0::,2a01:7ae0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7b00::,2a01:7b00:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a01:7b20::,2a01:7b20:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:7b40::,2a01:7b40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7b60::,2a01:7b60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:7b80::,2a01:7b80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:7ba0::,2a01:7ba0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:7bc0::,2a01:7bc0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:7be0::,2a01:7be0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7c00::,2a01:7c00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:7c20::,2a01:7c20:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a01:7c40::,2a01:7c40:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a01:7c60::,2a01:7c60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:7c80::,2a01:7c80:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a01:7ca0::,2a01:7ca0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:7cc0::,2a01:7cc0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:7ce0::,2a01:7ce0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:7d00::,2a01:7d00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:7d20::,2a01:7d20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7d40::,2a01:7d40:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:7d60::,2a01:7d60:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:7d80::,2a01:7d80:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:7da0::,2a01:7da0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:7de0::,2a01:7de0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7e00::,2a01:7e00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7e20::,2a01:7e27:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:7e40::,2a01:7e40:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a01:7e60::,2a01:7e60:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:7e80::,2a01:7e80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7ea0::,2a01:7ea0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:7ec0::,2a01:7ec0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:7ee0::,2a01:7ee0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:7f00::,2a01:7f00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:7f20::,2a01:7f20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:7f40::,2a01:7f40:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a01:7f60::,2a01:7f60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7f80::,2a01:7f80:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a01:7fa0::,2a01:7fa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7fc0::,2a01:7fc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:7fe0::,2a01:7fe0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:8000::,2a01:8000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8020::,2a01:8020:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:8040::,2a01:8040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8060::,2a01:8060:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a01:8080::,2a01:8080:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a01:80a0::,2a01:80a0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:80c0::,2a01:80c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:80e0::,2a01:80e0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:8100::,2a01:8100:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:8120::,2a01:8120:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:8140::,2a01:8140:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:8160::,2a01:8160:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:8180::,2a01:8180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:81a0::,2a01:81a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:81c0::,2a01:81c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:81e0::,2a01:81e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8200::,2a01:8200:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8220::,2a01:8220:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:8240::,2a01:8240:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8260::,2a01:8260:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8280::,2a01:8280:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:82a0::,2a01:82a0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:82c0::,2a01:82c0:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a01:82e0::,2a01:82e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8300::,2a01:8300:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:8320::,2a01:8320:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:8340::,2a01:8340:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8360::,2a01:8360:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8380::,2a01:8380:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:83a0::,2a01:83a0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:83c0::,2a01:83c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:83e0::,2a01:83e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:8400::,2a01:8400:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:8420::,2a01:8420:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:8440::,2a01:8440:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:8460::,2a01:8460:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:8480::,2a01:8480:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:84a0::,2a01:84a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:84c0::,2a01:84c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:84e0::,2a01:84e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:8500::,2a01:8500:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8520::,2a01:8520:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:8540::,2a01:8540:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:8560::,2a01:8560:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:8580::,2a01:8580:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:85a0::,2a01:85a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:85e0::,2a01:85e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8600::,2a01:8600:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8620::,2a01:8620:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:8640::,2a01:8640:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8660::,2a01:8660:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8680::,2a01:8680:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:86a0::,2a01:86a0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:86c0::,2a01:86c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:86e0::,2a01:86e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8700::,2a01:8700:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a01:8720::,2a01:8720:ffff:ffff:ffff:ffff:ffff:ffff,US +2a01:8740::,2a01:8740:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:8760::,2a01:8760:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8780::,2a01:8787:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:87c0::,2a01:87c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:87e0::,2a01:87e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8800::,2a01:8800:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8820::,2a01:8820:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8840::,2a01:8840:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:8860::,2a01:8860:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:8880::,2a01:8880:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:88a0::,2a01:88a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:88c0::,2a01:88c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:88e0::,2a01:88e0:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a01:8900::,2a01:8900:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8920::,2a01:8920:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8940::,2a01:8940:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8960::,2a01:8960:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8980::,2a01:8980:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:89a0::,2a01:89a0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:89c0::,2a01:89c0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:89e0::,2a01:89e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8a00::,2a01:8a00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:8a20::,2a01:8a20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:8a40::,2a01:8a40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:8a60::,2a01:8a60:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:8a80::,2a01:8a80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:8aa0::,2a01:8aa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8ac0::,2a01:8ac0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8ae0::,2a01:8ae0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8b00::,2a01:8b00:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:8b20::,2a01:8b20:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a01:8b40::,2a01:8b40:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:8b60::,2a01:8b60:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:8b80::,2a01:8b80:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:8ba0::,2a01:8ba7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:8bc0::,2a01:8bc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:8be0::,2a01:8be0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8c00::,2a01:8c00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:8c20::,2a01:8c20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8c40::,2a01:8c40:ffff:ffff:ffff:ffff:ffff:ffff,GI +2a01:8c60::,2a01:8c60:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a01:8c80::,2a01:8c80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:8ca0::,2a01:8ca0:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a01:8cc0::,2a01:8cc0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:8ce0::,2a01:8ce0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:8d00::,2a01:8d00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:8d20::,2a01:8d20:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8d40::,2a01:8d47:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:8d80::,2a01:8d80:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:8da0::,2a01:8da0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:8dc0::,2a01:8dc0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:8de0::,2a01:8de0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:8e00::,2a01:8e00:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:8e20::,2a01:8e20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:8e40::,2a01:8e40:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a01:8e60::,2a01:8e60:ffff:ffff:ffff:ffff:ffff:ffff,US +2a01:8e80::,2a01:8e87:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:8ec0::,2a01:8ec0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:8ee0::,2a01:8ee0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:8f00::,2a01:8f00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:8f20::,2a01:8f20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:8f40::,2a01:8f40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:8f60::,2a01:8f60:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:8f80::,2a01:8f80:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:8fa0::,2a01:8fa0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:8fc0::,2a01:8fc0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:8fe0::,2a01:8fe0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9000::,2a01:9000:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:9020::,2a01:9020:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:9040::,2a01:9040:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a01:9060::,2a01:9060:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:9080::,2a01:9080:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:90a0::,2a01:90a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:90c0::,2a01:90c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:90e0::,2a01:90e0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:9100::,2a01:9100:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:9120::,2a01:9120:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9140::,2a01:9140:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:9160::,2a01:9160:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:9180::,2a01:9180:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:91a0::,2a01:91a0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:91c0::,2a01:91c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:91e0::,2a01:91e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:9220::,2a01:9220:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9240::,2a01:9240:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a01:9260::,2a01:9260:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:9280::,2a01:9280:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:92a0::,2a01:92a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:92c0::,2a01:92c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:92e0::,2a01:92e0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a01:9300::,2a01:9300:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9320::,2a01:9320:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:9340::,2a01:9340:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:9360::,2a01:9360:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:9380::,2a01:9380:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:93a0::,2a01:93a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:93c0::,2a01:93c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:93e0::,2a01:93e0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:9400::,2a01:9400:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:9420::,2a01:9420:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:9440::,2a01:9440:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:9460::,2a01:9460:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:9480::,2a01:9480:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:94a0::,2a01:94a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:94c0::,2a01:94c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:94e0::,2a01:94e0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:9500::,2a01:9500:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:9520::,2a01:9520:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9540::,2a01:9540:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9560::,2a01:9560:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:9580::,2a01:9580:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:95a0::,2a01:95a0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:95c0::,2a01:95c0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:95e0::,2a01:95e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9600::,2a01:9600:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9620::,2a01:9620:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a01:9640::,2a01:9640:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:9660::,2a01:9660:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:9680::,2a01:9680:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:96a0::,2a01:96a0:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a01:96c0::,2a01:96c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:96e0::,2a01:96e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:9700::,2a01:9700:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a01:9720::,2a01:9720:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:9740::,2a01:9740:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9760::,2a01:9760:ffff:ffff:ffff:ffff:ffff:ffff,KY +2a01:9780::,2a01:9780:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:97a0::,2a01:97a0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:97c0::,2a01:97c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:97e0::,2a01:97e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:9800::,2a01:9800:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:9820::,2a01:9820:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:9840::,2a01:9840:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9860::,2a01:9860:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:9880::,2a01:9880:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:98a0::,2a01:98a0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:98c0::,2a01:98c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:98e0::,2a01:98e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:9900::,2a01:9900:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:9920::,2a01:9920:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:9940::,2a01:9940:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:9960::,2a01:9960:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:9980::,2a01:9980:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:99a0::,2a01:99a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:99e0::,2a01:99e0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:9a00::,2a01:9a00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9a20::,2a01:9a20:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:9a40::,2a01:9a40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:9a60::,2a01:9a60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9a80::,2a01:9a80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9aa0::,2a01:9aa0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:9ac0::,2a01:9ac0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9ae0::,2a01:9ae0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:9b00::,2a01:9b00:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:9b20::,2a01:9b20:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a01:9b40::,2a01:9b40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:9b60::,2a01:9b60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:9b80::,2a01:9b80:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:9ba0::,2a01:9ba0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:9bc0::,2a01:9bc7:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:9be0::,2a01:9be0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9c00::,2a01:9c00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9c20::,2a01:9c20:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:9c40::,2a01:9c41:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9c60::,2a01:9c60:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:9c80::,2a01:9c80:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a01:9ca0::,2a01:9ca0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9cc0::,2a01:9cc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9ce0::,2a01:9ce0:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a01:9d00::,2a01:9d00:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a01:9d20::,2a01:9d20:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a01:9d40::,2a01:9d40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:9d60::,2a01:9d60:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:9d80::,2a01:9d80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:9da0::,2a01:9da0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:9dc0::,2a01:9dc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:9de0::,2a01:9de0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:9e00::,2a01:9e07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9e20::,2a01:9e20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9e40::,2a01:9e40:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:9e60::,2a01:9e60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9e80::,2a01:9e80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:9ea0::,2a01:9ea0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:9ec0::,2a01:9ec7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:9f00::,2a01:9f00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:9f20::,2a01:9f20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:9f40::,2a01:9f40:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:9f60::,2a01:9f60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:9f80::,2a01:9f80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:9fa0::,2a01:9fa0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:9fc0::,2a01:9fc0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:9fe0::,2a01:9fe0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a000::,2a01:a000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a020::,2a01:a020:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a040::,2a01:a040:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:a060::,2a01:a060:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:a080::,2a01:a080:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a0a0::,2a01:a0a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a0c0::,2a01:a0c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:a0e0::,2a01:a0e0:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a01:a100::,2a01:a100:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:a120::,2a01:a120:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:a160::,2a01:a160:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:a180::,2a01:a180:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a01:a1a0::,2a01:a1a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:a1c0::,2a01:a1c0:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a01:a1e0::,2a01:a1e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:a200::,2a01:a200:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a220::,2a01:a220:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a240::,2a01:a240:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:a260::,2a01:a260:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:a280::,2a01:a280:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:a2a0::,2a01:a2a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:a2c0::,2a01:a2c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a2e0::,2a01:a2e0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:a300::,2a01:a300:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:a320::,2a01:a320:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a01:a340::,2a01:a340:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:a360::,2a01:a360:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:a380::,2a01:a380:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a3a0::,2a01:a3a0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:a3c0::,2a01:a3c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:a3e0::,2a01:a3e0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a01:a400::,2a01:a400:ffff:ffff:ffff:ffff:ffff:ffff,JE +2a01:a420::,2a01:a420:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:a440::,2a01:a440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:a460::,2a01:a460:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:a480::,2a01:a480:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a4a0::,2a01:a4a0:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a01:a4c0::,2a01:a4c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:a4e0::,2a01:a4e0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:a500::,2a01:a500:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a520::,2a01:a520:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:a540::,2a01:a540:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:a560::,2a01:a560:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:a580::,2a01:a580:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:a5a0::,2a01:a5a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a5c0::,2a01:a5c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a5e0::,2a01:a5e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:a600::,2a01:a600:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:a620::,2a01:a620:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:a640::,2a01:a640:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:a660::,2a01:a660:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:a680::,2a01:a680:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:a6a0::,2a01:a6a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:a6c0::,2a01:a6c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:a6e0::,2a01:a6e0:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a01:a700::,2a01:a707:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a740::,2a01:a740:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a760::,2a01:a760:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a01:a780::,2a01:a780:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a7a0::,2a01:a7a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a7c0::,2a01:a7c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:a7e0::,2a01:a7e0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:a800::,2a01:a800:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:a820::,2a01:a820:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:a840::,2a01:a840:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:a860::,2a01:a860:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:a880::,2a01:a880:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a01:a8a0::,2a01:a8a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:a8c0::,2a01:a8c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:a8e0::,2a01:a8e0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:a900::,2a01:a900:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:a920::,2a01:a920:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:a940::,2a01:a940:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:a960::,2a01:a960:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a01:a980::,2a01:a980:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:a9a0::,2a01:a9a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:a9c0::,2a01:a9c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:a9e0::,2a01:a9e0:ffff:ffff:ffff:ffff:ffff:ffff,US +2a01:aa00::,2a01:aa00:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a01:aa20::,2a01:aa20:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a01:aa40::,2a01:aa40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:aa60::,2a01:aa60:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:aa80::,2a01:aa80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:aaa0::,2a01:aaa0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:aac0::,2a01:aac0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:aae0::,2a01:aae0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:ab00::,2a01:ab00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:ab20::,2a01:ab20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:ab40::,2a01:ab40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:aba0::,2a01:aba0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:abc0::,2a01:abc0:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a01:abe0::,2a01:abe0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:ac00::,2a01:ac00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:ac20::,2a01:ac20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:ac40::,2a01:ac40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:ac60::,2a01:ac60:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:ac80::,2a01:ac80:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a01:aca0::,2a01:aca0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:acc0::,2a01:acc0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:ace0::,2a01:ace0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:ad00::,2a01:ad00:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:ad20::,2a01:ad20:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:ad40::,2a01:ad40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:ad60::,2a01:ad60:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a01:ad80::,2a01:ad80:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:ada0::,2a01:ada0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:adc0::,2a01:adc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:ade0::,2a01:ade0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:ae00::,2a01:ae00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:ae20::,2a01:ae20:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:ae40::,2a01:ae40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:ae60::,2a01:ae60:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:ae80::,2a01:ae80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:aea0::,2a01:aea0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:aec0::,2a01:aec0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:aee0::,2a01:aee0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:af00::,2a01:af00:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:af20::,2a01:af20:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:af40::,2a01:af40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:af60::,2a01:af60:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:af80::,2a01:af80:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a01:afa0::,2a01:afa0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a01:afc0::,2a01:afc0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:afe0::,2a01:afe0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:b000::,2a01:b000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b020::,2a01:b020:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a01:b040::,2a01:b040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b060::,2a01:b060:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:b080::,2a01:b080:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:b0a0::,2a01:b0a0:ffff:ffff:ffff:ffff:ffff:ffff,US +2a01:b0c0::,2a01:b0c0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a01:b0e0::,2a01:b0e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:b100::,2a01:b100:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:b120::,2a01:b120:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:b140::,2a01:b140:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:b160::,2a01:b160:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:b180::,2a01:b180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:b1a0::,2a01:b1a0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:b1c0::,2a01:b1c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:b200::,2a01:b200:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a01:b220::,2a01:b220:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:b240::,2a01:b240:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b260::,2a01:b260:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:b280::,2a01:b280:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b2a0::,2a01:b2a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b2c0::,2a01:b2c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b2e0::,2a01:b2e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:b300::,2a01:b307:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:b340::,2a01:b340:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:b360::,2a01:b360:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:b380::,2a01:b380:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:b3a0::,2a01:b3a0:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a01:b3c0::,2a01:b3c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:b3e0::,2a01:b3e0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:b400::,2a01:b400:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:b420::,2a01:b420:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:b440::,2a01:b440:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:b460::,2a01:b460:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:b480::,2a01:b480:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:b4a0::,2a01:b4a0:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a01:b4c0::,2a01:b4c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:b4e0::,2a01:b4e0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a01:b500::,2a01:b500:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a01:b520::,2a01:b520:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:b540::,2a01:b547:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:b580::,2a01:b580:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:b5a0::,2a01:b5a0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:b5c0::,2a01:b5c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:b5e0::,2a01:b5e0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:b600::,2a01:b600:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:b620::,2a01:b620:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a01:b640::,2a01:b640:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:b660::,2a01:b660:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b680::,2a01:b680:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:b6a0::,2a01:b6a0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a01:b6c0::,2a01:b6c7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:b700::,2a01:b700:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:b720::,2a01:b720:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b740::,2a01:b740:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:b760::,2a01:b760:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b780::,2a01:b780:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a01:b7a0::,2a01:b7a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:b7c0::,2a01:b7c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:b7e0::,2a01:b7e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:b800::,2a01:b800:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a01:b820::,2a01:b820:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b840::,2a01:b840:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b860::,2a01:b860:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b880::,2a01:b880:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a01:b8a0::,2a01:b8a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:b8c0::,2a01:b8c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:b8e0::,2a01:b8e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:b900::,2a01:b900:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:b920::,2a01:b920:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:b940::,2a01:b940:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:b960::,2a01:b960:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:b980::,2a01:b980:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:b9a0::,2a01:b9a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:b9c0::,2a01:b9c0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a01:b9e0::,2a01:b9e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:ba00::,2a01:ba00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a01:ba20::,2a01:ba20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:ba40::,2a01:ba40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:ba60::,2a01:ba60:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a01:ba80::,2a01:ba80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:baa0::,2a01:baa0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:bac0::,2a01:bac0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:bae0::,2a01:bae0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:bb20::,2a01:bb20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:bb40::,2a01:bb40:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:bb60::,2a01:bb60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a01:bb80::,2a01:bb80:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a01:bba0::,2a01:bba0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a01:bbc0::,2a01:bbc0:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a01:bbe0::,2a01:bbe0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:bc00::,2a01:bc07:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:bc40::,2a01:bc40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:bc60::,2a01:bc60:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:bca0::,2a01:bca0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:bcc0::,2a01:bcc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:bce0::,2a01:bce0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:bd00::,2a01:bd00:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:bd20::,2a01:bd20:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a01:bd40::,2a01:bd40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:bd60::,2a01:bd60:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a01:bd80::,2a01:bd80:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a01:bda0::,2a01:bda0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a01:bdc0::,2a01:bdc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a01:bde0::,2a01:bde0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:be00::,2a01:be00:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a01:be40::,2a01:be40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:be60::,2a01:be60:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a01:be80::,2a01:be80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a01:bea0::,2a01:bea0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a01:bec0::,2a01:bec0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:bee0::,2a01:bee0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:bf20::,2a01:bf20:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a01:bf40::,2a01:bf40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a01:bf60::,2a01:bf60:ffff:ffff:ffff:ffff:ffff:ffff,US +2a01:bf80::,2a01:bf80:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a01:bfa0::,2a01:bfa0:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a01:bfc0::,2a01:bfc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a01:bfe0::,2a01:bfe0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a01:c000::,2a01:dfff:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02::,2a02::ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:10::,2a02:17:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:18::,2a02:18:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:20::,2a02:20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:28::,2a02:28:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:30::,2a02:30:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:38::,2a02:38:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:40::,2a02:40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:48::,2a02:48:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a02:50::,2a02:50:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:58::,2a02:58:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:60::,2a02:67:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:68::,2a02:68:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:70::,2a02:70:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:78::,2a02:78:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:80::,2a02:80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:88::,2a02:88:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a02:90::,2a02:97:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:98::,2a02:98:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:a0::,2a02:a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:a8::,2a02:a8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:b0::,2a02:b0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b8::,2a02:b8:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:c0::,2a02:c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:c8::,2a02:c8:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:d0::,2a02:d0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:d8::,2a02:d8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:e0::,2a02:e0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:e8::,2a02:e8:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:f0::,2a02:f0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:f8::,2a02:f8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:100::,2a02:100:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:108::,2a02:10f:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:110::,2a02:110:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:118::,2a02:118:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:120::,2a02:120:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:128::,2a02:128:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:130::,2a02:130:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:138::,2a02:138:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:140::,2a02:140:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:148::,2a02:14f:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:150::,2a02:150:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:158::,2a02:158:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:160::,2a02:160:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:168::,2a02:16b:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:170::,2a02:170:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:178::,2a02:178:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:180::,2a02:180:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:188::,2a02:18f:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:190::,2a02:190:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:198::,2a02:198:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:1a0::,2a02:1a7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1a8::,2a02:1a8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1b8::,2a02:1b8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:1c0::,2a02:1c0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:1c8::,2a02:1c8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1d0::,2a02:1d0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:1d8::,2a02:1d8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:1e0::,2a02:1e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1e8::,2a02:1e8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1f0::,2a02:1f0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:1f8::,2a02:1f8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:200::,2a02:200:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:208::,2a02:208:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:210::,2a02:210:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:218::,2a02:218:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:220::,2a02:220:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:228::,2a02:22f:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:230::,2a02:230:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:238::,2a02:238:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:240::,2a02:240:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:248::,2a02:248:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:250::,2a02:250:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:258::,2a02:258:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:260::,2a02:260:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:268::,2a02:268:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:270::,2a02:270:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:278::,2a02:278:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:280::,2a02:280:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:288::,2a02:290:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:298::,2a02:298:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2a0::,2a02:2a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2a8::,2a02:2a8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:2b0::,2a02:2b0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2b8::,2a02:2b8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2c0::,2a02:2c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2c8::,2a02:2c8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2d0::,2a02:2d0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:2d8::,2a02:2d8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2e0::,2a02:2e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2e8::,2a02:2e8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2f0::,2a02:2f7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2f8::,2a02:2f8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:300::,2a02:300:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:308::,2a02:308:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:310::,2a02:310:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:318::,2a02:318:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:320::,2a02:320:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:328::,2a02:328:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:330::,2a02:330:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:338::,2a02:338:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:340::,2a02:340:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:348::,2a02:348:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:350::,2a02:350:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:358::,2a02:358:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:360::,2a02:360:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:368::,2a02:368:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:370::,2a02:370:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:380::,2a02:381:ffff:ffff:ffff:ffff:ffff:ffff,LI +2a02:388::,2a02:388:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:390::,2a02:390:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:398::,2a02:398:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:3a0::,2a02:3a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:3a8::,2a02:3a8:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:3b0::,2a02:3b0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:3b8::,2a02:3b8:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:3c0::,2a02:3c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:3c8::,2a02:3c8:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a02:3d0::,2a02:3d0:ffff:ffff:ffff:ffff:ffff:ffff,US +2a02:3d8::,2a02:3d8:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:3e0::,2a02:3e0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:3e8::,2a02:3e8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:3f0::,2a02:3f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:3f8::,2a02:3f8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:400::,2a02:400:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:408::,2a02:408:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:410::,2a02:410:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:418::,2a02:41f:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:420::,2a02:420:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:428::,2a02:428:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:430::,2a02:430:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:438::,2a02:438:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:440::,2a02:440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:448::,2a02:448:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:450::,2a02:450:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:458::,2a02:458:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:460::,2a02:460:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:468::,2a02:468:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:470::,2a02:470:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:478::,2a02:478:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:480::,2a02:480:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:488::,2a02:488:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:490::,2a02:490:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:498::,2a02:498:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4a0::,2a02:4a0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:4a8::,2a02:4a8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:4b0::,2a02:4b0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:4b8::,2a02:4c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:4c8::,2a02:4c8:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:4d0::,2a02:4d0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4d8::,2a02:4d8:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:4e0::,2a02:4e0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:4e8::,2a02:4e8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4f0::,2a02:4f0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:4f8::,2a02:4f8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:500::,2a02:500:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a02:508::,2a02:508:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:518::,2a02:518:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:520::,2a02:520:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:530::,2a02:530:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:538::,2a02:538:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:540::,2a02:540:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a02:548::,2a02:548:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:550::,2a02:550:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:558::,2a02:558:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:560::,2a02:560:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:568::,2a02:568:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:570::,2a02:570:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:578::,2a02:578:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:580::,2a02:587:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:588::,2a02:588:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:590::,2a02:590:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:598::,2a02:598:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:5a0::,2a02:5a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:5b0::,2a02:5b0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5b8::,2a02:5b8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5c0::,2a02:5c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:5c8::,2a02:5c8:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:5d0::,2a02:5d0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:5d8::,2a02:5d8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:5e0::,2a02:5e0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:5f0::,2a02:5f0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:5f8::,2a02:5f8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:600::,2a02:600:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:608::,2a02:608:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:610::,2a02:610:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a02:618::,2a02:618:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:620::,2a02:620:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:628::,2a02:628:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:630::,2a02:630:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:638::,2a02:638:ffff:ffff:ffff:ffff:ffff:ffff,GI +2a02:640::,2a02:640:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a02:648::,2a02:648:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:650::,2a02:650:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:658::,2a02:658:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:660::,2a02:660:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a02:668::,2a02:668:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:670::,2a02:670:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:678::,2a02:678:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:680::,2a02:680:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:688::,2a02:688:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:690::,2a02:690:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:698::,2a02:698:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6a0::,2a02:6a0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:6a8::,2a02:6a8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:6b0::,2a02:6b0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6b8::,2a02:6b8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6c0::,2a02:6c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:6c8::,2a02:6c8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:6d0::,2a02:6d0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6d8::,2a02:6d8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:6e0::,2a02:6e0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:6e8::,2a02:6e8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6f0::,2a02:6f0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6f8::,2a02:6f8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:700::,2a02:700:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:708::,2a02:708:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:710::,2a02:710:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:718::,2a02:718:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:720::,2a02:720:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:728::,2a02:728:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:730::,2a02:730:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:738::,2a02:738:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:740::,2a02:740:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:748::,2a02:748:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:750::,2a02:750:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:758::,2a02:758:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:760::,2a02:760:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:768::,2a02:768:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:770::,2a02:770:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:778::,2a02:778:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:780::,2a02:787:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:788::,2a02:788:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:790::,2a02:790:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:798::,2a02:798:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:7a0::,2a02:7a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:7a8::,2a02:7a8:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:7b0::,2a02:7b0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:7b8::,2a02:7b8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:7c0::,2a02:7c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7c8::,2a02:7c8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:7d0::,2a02:7d0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:7d8::,2a02:7d8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:7e0::,2a02:7e0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:7e8::,2a02:7e8:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:7f0::,2a02:7f0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:7f8::,2a02:7f8:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:800::,2a02:807:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:808::,2a02:808:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:810::,2a02:810:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:818::,2a02:81f:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:820::,2a02:820:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a02:828::,2a02:828:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:830::,2a02:830:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:838::,2a02:838:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:840::,2a02:840:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:848::,2a02:848:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:850::,2a02:850:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:858::,2a02:858:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:860::,2a02:860:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:868::,2a02:868:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:870::,2a02:870:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:878::,2a02:878:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:880::,2a02:880:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:888::,2a02:888:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:890::,2a02:890:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:898::,2a02:898:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:8a0::,2a02:8a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:8a8::,2a02:8a8:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:8b0::,2a02:8b0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:8b8::,2a02:8b8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:8c0::,2a02:8c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:8c8::,2a02:8c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:8d0::,2a02:8d1:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:8d8::,2a02:8d8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:8e0::,2a02:8e0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:8e8::,2a02:8e8:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:8f0::,2a02:8f0:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:8f8::,2a02:8f8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:900::,2a02:9ff:ffff:ffff:ffff:ffff:ffff:ffff,DJ +2a02:a00::,2a02:a00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:a08::,2a02:a08:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:a10::,2a02:a10:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:a18::,2a02:a18:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:a20::,2a02:a20:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:a28::,2a02:a28:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:a30::,2a02:a30:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a02:a38::,2a02:a38:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:a40::,2a02:a40:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:a48::,2a02:a48:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:a50::,2a02:a50:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:a58::,2a02:a58:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:a60::,2a02:a60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:a68::,2a02:a68:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:a70::,2a02:a70:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:a78::,2a02:a78:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:a80::,2a02:a80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:a88::,2a02:a88:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:a90::,2a02:a90:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:a98::,2a02:a98:ffff:ffff:ffff:ffff:ffff:ffff,UZ +2a02:aa0::,2a02:aa0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:aa8::,2a02:aa9:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:ab0::,2a02:ab0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:ab8::,2a02:ab8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:ac0::,2a02:ac0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:ac8::,2a02:ac8:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a02:ad0::,2a02:ad7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ad8::,2a02:ad8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ae0::,2a02:ae0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ae8::,2a02:aef:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:af0::,2a02:af0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:af8::,2a02:af8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b00::,2a02:b00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b08::,2a02:b08:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:b10::,2a02:b10:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b18::,2a02:b18:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:b20::,2a02:b20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:b28::,2a02:b28:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:b30::,2a02:b30:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:b38::,2a02:b38:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:b48::,2a02:b48:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:b50::,2a02:b50:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b58::,2a02:b58:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a02:b60::,2a02:b60:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a02:b70::,2a02:b70:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:b78::,2a02:b78:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b80::,2a02:b87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b88::,2a02:b88:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:b90::,2a02:b90:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:b98::,2a02:b98:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ba0::,2a02:ba0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:ba8::,2a02:ba8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:bb0::,2a02:bb0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:bb8::,2a02:bb8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:bc0::,2a02:bc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:bc8::,2a02:bc8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:bd0::,2a02:bd0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:bd8::,2a02:bd8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:be0::,2a02:be0:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:be8::,2a02:be8:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:bf0::,2a02:bf0:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a02:bf8::,2a02:bf8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c00::,2a02:c00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c08::,2a02:c08:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a02:c10::,2a02:c10:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:c18::,2a02:c18:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:c20::,2a02:c20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:c28::,2a02:c2f:ffff:ffff:ffff:ffff:ffff:ffff,JE +2a02:c30::,2a02:c30:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c38::,2a02:c38:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:c40::,2a02:c47:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:c48::,2a02:c48:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c50::,2a02:c50:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c58::,2a02:c58:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:c60::,2a02:c60:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:c68::,2a02:c68:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:c70::,2a02:c70:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:c78::,2a02:c7f:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c80::,2a02:c80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:c88::,2a02:c88:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:c90::,2a02:c90:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:c98::,2a02:c98:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ca0::,2a02:ca0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:ca8::,2a02:ca8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:cb0::,2a02:cb0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:cc0::,2a02:cc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:cc8::,2a02:cc9:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:cd0::,2a02:cd0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:cd8::,2a02:cd8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:ce0::,2a02:ce0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:ce8::,2a02:ce8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:cf0::,2a02:cf0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:d00::,2a02:d00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:d08::,2a02:d08:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:d10::,2a02:d10:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:d18::,2a02:d18:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a02:d20::,2a02:d20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d28::,2a02:d28:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:d30::,2a02:d30:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:d38::,2a02:d3f:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:d40::,2a02:d40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d48::,2a02:d48:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:d50::,2a02:d50:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:d58::,2a02:d5f:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:d60::,2a02:d60:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:d68::,2a02:d6f:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:d70::,2a02:d70:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:d78::,2a02:d78:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d80::,2a02:d80:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:d88::,2a02:d88:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:d90::,2a02:d90:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:d98::,2a02:d98:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:da8::,2a02:da8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:db0::,2a02:db0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:db8::,2a02:db8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:dc0::,2a02:dc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:dc8::,2a02:dc8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:dd0::,2a02:dd0:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a02:dd8::,2a02:ddf:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:de0::,2a02:de0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:de8::,2a02:de8:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a02:df0::,2a02:df0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:df8::,2a02:df8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:e00::,2a02:e00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:e08::,2a02:e08:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:e10::,2a02:e10:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:e20::,2a02:e27:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:e28::,2a02:e28:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:e30::,2a02:e30:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:e38::,2a02:e38:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:e40::,2a02:e40:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a02:e48::,2a02:e48:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a02:e50::,2a02:e50:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:e58::,2a02:e5f:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:e60::,2a02:e60:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:e68::,2a02:e68:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:e70::,2a02:e70:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:e80::,2a02:e80:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a02:e88::,2a02:e88:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:e90::,2a02:e90:ffff:ffff:ffff:ffff:ffff:ffff,FO +2a02:e98::,2a02:e98:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:ea0::,2a02:ea7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ea8::,2a02:ea8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:eb0::,2a02:eb0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:eb8::,2a02:eb8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:ec0::,2a02:ec0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:ec8::,2a02:ec8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:ed0::,2a02:ed0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:ed8::,2a02:ed8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:ee0::,2a02:ee0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:ef0::,2a02:ef0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:ef8::,2a02:ef8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f00::,2a02:f00:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:f08::,2a02:f08:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f10::,2a02:f10:ffff:ffff:ffff:ffff:ffff:ffff,UZ +2a02:f18::,2a02:f18:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:f20::,2a02:f20:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f28::,2a02:f28:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f30::,2a02:f30:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:f38::,2a02:f38:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f40::,2a02:f40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:f48::,2a02:f48:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a02:f50::,2a02:f50:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a02:f58::,2a02:f58:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:f60::,2a02:f60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:f68::,2a02:f6f:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:f70::,2a02:f70:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f78::,2a02:f7f:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:f80::,2a02:f80:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:f88::,2a02:f88:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a02:f90::,2a02:f90:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f98::,2a02:f98:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:fa0::,2a02:fa0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:fa8::,2a02:fa8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:fb0::,2a02:fb0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:fb8::,2a02:fb8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:fc0::,2a02:fc0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:fc8::,2a02:fc8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:fd0::,2a02:fd0:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a02:fd8::,2a02:fd8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:fe0::,2a02:fe7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:fe8::,2a02:fe8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:ff0::,2a02:ff0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:ff8::,2a02:ff8:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:1000::,2a02:103f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1200::,2a02:12ff:ffff:ffff:ffff:ffff:ffff:ffff,CI +2a02:1300::,2a02:1300:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a02:1308::,2a02:1308:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1310::,2a02:1310:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1318::,2a02:1318:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1320::,2a02:1320:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:1328::,2a02:1328:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1330::,2a02:1330:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:1338::,2a02:1338:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:1340::,2a02:1340:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1348::,2a02:1348:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1350::,2a02:1350:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1358::,2a02:1358:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:1360::,2a02:1360:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:1368::,2a02:1368:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:1370::,2a02:1370:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:1378::,2a02:1378:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1380::,2a02:1380:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:1388::,2a02:138f:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:1390::,2a02:1390:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:1398::,2a02:1398:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:13a0::,2a02:13a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:13a8::,2a02:13a8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:13b0::,2a02:13b0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:13b8::,2a02:13b8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:13c0::,2a02:13c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:13c8::,2a02:13c8:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:13d0::,2a02:13d0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:13d8::,2a02:13d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:13e0::,2a02:13e0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:13e8::,2a02:13e8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:13f0::,2a02:13f0:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:13f8::,2a02:13f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1400::,2a02:143f:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:1600::,2a02:1600:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:1608::,2a02:1608:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1610::,2a02:1610:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:1618::,2a02:1618:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a02:1620::,2a02:1620:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1628::,2a02:1628:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1630::,2a02:1630:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:1638::,2a02:1638:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:1640::,2a02:1640:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a02:1648::,2a02:1648:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1650::,2a02:1650:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:1658::,2a02:1658:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1660::,2a02:1660:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:1668::,2a02:1668:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:1670::,2a02:1670:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1678::,2a02:1678:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:1680::,2a02:1680:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:1688::,2a02:1688:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:1698::,2a02:1698:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:16a0::,2a02:16a0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:16a8::,2a02:16a8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:16b0::,2a02:16b0:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a02:16b8::,2a02:16b8:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:16c0::,2a02:16c0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:16c8::,2a02:16c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:16d0::,2a02:16d0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:16d8::,2a02:16d8:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a02:16e0::,2a02:16e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:16e8::,2a02:16e8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:16f0::,2a02:16f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:16f8::,2a02:16f8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1700::,2a02:1700:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1710::,2a02:1710:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1718::,2a02:1718:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a02:1720::,2a02:1720:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:1730::,2a02:1730:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:1738::,2a02:1738:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:1740::,2a02:1740:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:1748::,2a02:1748:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:1750::,2a02:1750:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:1758::,2a02:1758:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:1760::,2a02:1760:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:1768::,2a02:1768:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:1770::,2a02:1770:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:1778::,2a02:1778:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:1780::,2a02:1780:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:1788::,2a02:1788:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:1790::,2a02:1790:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:1798::,2a02:179f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:17a0::,2a02:17a0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:17a8::,2a02:17a8:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a02:17b0::,2a02:17b0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:17b8::,2a02:17b8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:17c0::,2a02:17c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:17c8::,2a02:17c8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:17d0::,2a02:17d0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:17d8::,2a02:17d8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:17e0::,2a02:17e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:17e8::,2a02:17e8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:17f0::,2a02:17f0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:17f8::,2a02:17f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:1800::,2a02:18ff:ffff:ffff:ffff:ffff:ffff:ffff,BF +2a02:2000::,2a02:20ff:ffff:ffff:ffff:ffff:ffff:ffff,DJ +2a02:2100::,2a02:2100:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2108::,2a02:2108:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:2110::,2a02:2110:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2118::,2a02:211f:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2120::,2a02:2123:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2140::,2a02:2140:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2148::,2a02:214f:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:2150::,2a02:2150:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2158::,2a02:2158:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:2160::,2a02:2160:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:2168::,2a02:216f:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2170::,2a02:2170:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2178::,2a02:2178:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2180::,2a02:2180:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2188::,2a02:2188:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2190::,2a02:2190:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2198::,2a02:2198:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:21a0::,2a02:21a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:21a8::,2a02:21a8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:21b0::,2a02:21b0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:21b8::,2a02:21b8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:21c0::,2a02:21c0:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a02:21c8::,2a02:21c8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:21d0::,2a02:21d0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:21d8::,2a02:21d8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:21e0::,2a02:21e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:21e8::,2a02:21e8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:21f0::,2a02:21f0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:21f8::,2a02:21f8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2200::,2a02:2200:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2208::,2a02:2208:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a02:2210::,2a02:2210:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2218::,2a02:2218:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2220::,2a02:2220:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:2228::,2a02:2228:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2230::,2a02:2230:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:2240::,2a02:2240:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2248::,2a02:2248:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:2250::,2a02:2250:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2258::,2a02:2258:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2260::,2a02:2260:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2268::,2a02:2268:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2270::,2a02:2270:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2278::,2a02:2278:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2280::,2a02:2280:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2288::,2a02:2288:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2290::,2a02:2290:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:2298::,2a02:2298:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:22a0::,2a02:22a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:22a8::,2a02:22a8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:22b0::,2a02:22b0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:22b8::,2a02:22b8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:22c0::,2a02:22c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:22c8::,2a02:22c8:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:22d0::,2a02:22d0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:22d8::,2a02:22d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:22e0::,2a02:22e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:22e8::,2a02:22e8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:22f0::,2a02:22f0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2300::,2a02:2300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2308::,2a02:2308:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2310::,2a02:2310:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2318::,2a02:2318:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2320::,2a02:2320:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2328::,2a02:2328:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2330::,2a02:2330:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a02:2338::,2a02:233f:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2340::,2a02:2340:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:2348::,2a02:2348:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:2350::,2a02:2350:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2358::,2a02:2358:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2360::,2a02:2360:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2368::,2a02:2368:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2378::,2a02:2378:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2380::,2a02:2380:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:2388::,2a02:2388:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2390::,2a02:2390:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a02:2398::,2a02:2398:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:23a0::,2a02:23a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:23a8::,2a02:23a8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:23b0::,2a02:23b0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:23b8::,2a02:23b8:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:23c0::,2a02:23c0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:23c8::,2a02:23c8:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:23d0::,2a02:23d0:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:23d8::,2a02:23d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:23e0::,2a02:23e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:23e8::,2a02:23e8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:23f0::,2a02:23f0:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a02:23f8::,2a02:23f8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2400::,2a02:2400:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2408::,2a02:2408:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2410::,2a02:2410:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:2420::,2a02:2420:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2428::,2a02:2428:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2430::,2a02:2430:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2438::,2a02:2438:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2440::,2a02:2440:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2448::,2a02:2448:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2450::,2a02:2457:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2458::,2a02:2458:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2460::,2a02:2460:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:2468::,2a02:2468:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2470::,2a02:2477:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2478::,2a02:2478:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2480::,2a02:2480:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2488::,2a02:2488:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2490::,2a02:2490:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:2498::,2a02:2498:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:24a0::,2a02:24a0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:24a8::,2a02:24a8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:24b0::,2a02:24b0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:24b8::,2a02:24bf:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:24c0::,2a02:24c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:24c8::,2a02:24c8:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:24d0::,2a02:24d0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:24d8::,2a02:24d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:24e0::,2a02:24e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:24e8::,2a02:24e8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:24f0::,2a02:24f0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:24f8::,2a02:24f8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:2500::,2a02:2500:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2508::,2a02:2508:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2510::,2a02:2510:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2518::,2a02:2518:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2520::,2a02:2520:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:2528::,2a02:252f:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:2530::,2a02:2530:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2538::,2a02:2538:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:2540::,2a02:2540:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2548::,2a02:2548:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2550::,2a02:2550:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2558::,2a02:2558:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a02:2560::,2a02:2560:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2568::,2a02:2568:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2578::,2a02:2578:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a02:2580::,2a02:2587:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:2588::,2a02:2588:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2590::,2a02:2590:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:2598::,2a02:2598:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:25a0::,2a02:25a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:25a8::,2a02:25af:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:25b0::,2a02:25b0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:25b8::,2a02:25b8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:25c0::,2a02:25c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:25c8::,2a02:25c8:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:25d0::,2a02:25d0:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:25d8::,2a02:25d8:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a02:25e0::,2a02:25e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:25e8::,2a02:25e8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:25f0::,2a02:25f0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:25f8::,2a02:25f8:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:2600::,2a02:2600:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:2608::,2a02:2608:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a02:2610::,2a02:2610:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2618::,2a02:2618:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2620::,2a02:2620:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2628::,2a02:2628:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:2630::,2a02:2630:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:2638::,2a02:2638:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2640::,2a02:2647:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2648::,2a02:2648:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2650::,2a02:2650:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2658::,2a02:2658:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2660::,2a02:2660:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:2668::,2a02:2668:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2670::,2a02:2670:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2678::,2a02:2678:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2680::,2a02:2680:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2688::,2a02:2688:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2690::,2a02:2690:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2698::,2a02:2698:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:26a0::,2a02:26a7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:26a8::,2a02:26a8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:26b0::,2a02:26b0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:26b8::,2a02:26b8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:26c0::,2a02:26c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:26c8::,2a02:26c8:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:26d0::,2a02:26d0:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a02:26d8::,2a02:26d8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:26e0::,2a02:26e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:26e8::,2a02:26e8:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:26f8::,2a02:26ff:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2700::,2a02:2700:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a02:2708::,2a02:2708:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2710::,2a02:2710:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2718::,2a02:271f:ffff:ffff:ffff:ffff:ffff:ffff,YE +2a02:2720::,2a02:2720:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:2728::,2a02:2728:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2730::,2a02:2730:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2738::,2a02:2738:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2740::,2a02:2740:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2748::,2a02:2748:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2750::,2a02:2750:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:2760::,2a02:2760:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2768::,2a02:2768:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2770::,2a02:2770:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2778::,2a02:2778:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2780::,2a02:2780:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2788::,2a02:2788:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:2790::,2a02:2790:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:2798::,2a02:2798:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:27a0::,2a02:27a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:27a8::,2a02:27af:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:27b0::,2a02:27b0:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a02:27b8::,2a02:27b8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:27c0::,2a02:27c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:27c8::,2a02:27c8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:27d0::,2a02:27d0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:27d8::,2a02:27d8:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:27e0::,2a02:27e0:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:27e8::,2a02:27e8:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:27f0::,2a02:27f0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:27f8::,2a02:27f8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2800::,2a02:2800:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2808::,2a02:2808:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2810::,2a02:2810:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2818::,2a02:2818:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2820::,2a02:2820:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:2828::,2a02:2828:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2830::,2a02:2830:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2838::,2a02:2838:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2840::,2a02:2840:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2848::,2a02:2848:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2850::,2a02:2850:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2858::,2a02:2858:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2860::,2a02:2860:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:2868::,2a02:2868:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:2870::,2a02:2870:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2878::,2a02:2878:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2880::,2a02:2880:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a02:2888::,2a02:2888:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2890::,2a02:2890:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2898::,2a02:2898:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:28a0::,2a02:28a0:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:28a8::,2a02:28a8:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:28b0::,2a02:28b7:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:28b8::,2a02:28bf:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a02:28c0::,2a02:28c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:28c8::,2a02:28c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:28d0::,2a02:28d0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:28d8::,2a02:28d8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:28e0::,2a02:28e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:28e8::,2a02:28e8:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:28f0::,2a02:28f0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:28f8::,2a02:28f8:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2900::,2a02:2900:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2908::,2a02:2908:ffff:ffff:ffff:ffff:ffff:ffff,OM +2a02:2910::,2a02:2910:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2918::,2a02:2918:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2920::,2a02:2920:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2928::,2a02:2928:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2930::,2a02:2930:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2938::,2a02:2938:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2940::,2a02:2940:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2948::,2a02:2948:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2950::,2a02:2950:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:2958::,2a02:2958:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2960::,2a02:2960:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:2968::,2a02:2968:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2970::,2a02:2970:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2978::,2a02:2978:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2980::,2a02:2980:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2988::,2a02:2988:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2990::,2a02:2990:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2998::,2a02:2998:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:29a0::,2a02:29a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:29a8::,2a02:29b0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:29b8::,2a02:29b8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:29c0::,2a02:29c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:29c8::,2a02:29c8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:29d0::,2a02:29d0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:29d8::,2a02:29d8:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:29e0::,2a02:29e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:29e8::,2a02:29ef:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a02:29f0::,2a02:29f0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:29f8::,2a02:29f8:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a02:2a00::,2a02:2a00:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:2a08::,2a02:2a08:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:2a10::,2a02:2a10:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2a18::,2a02:2a18:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2a20::,2a02:2a20:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2a28::,2a02:2a28:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2a30::,2a02:2a37:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2a38::,2a02:2a38:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2a40::,2a02:2a40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2a48::,2a02:2a48:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:2a50::,2a02:2a50:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a02:2a58::,2a02:2a58:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2a60::,2a02:2a60:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a02:2a68::,2a02:2a68:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2a70::,2a02:2a70:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:2a78::,2a02:2a78:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2a80::,2a02:2a80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2a88::,2a02:2a88:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2a90::,2a02:2a90:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:2a98::,2a02:2a98:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:2aa0::,2a02:2aa0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2aa8::,2a02:2aa8:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2ab0::,2a02:2ab0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2ab8::,2a02:2ab8:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2ac0::,2a02:2ac0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2ac8::,2a02:2ac8:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:2ad0::,2a02:2ad0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2ad8::,2a02:2ad8:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:2ae0::,2a02:2ae0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2ae8::,2a02:2ae8:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:2af0::,2a02:2af0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:2af8::,2a02:2af8:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:2b00::,2a02:2b00:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:2b08::,2a02:2b08:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2b10::,2a02:2b10:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:2b18::,2a02:2b18:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2b20::,2a02:2b20:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:2b28::,2a02:2b28:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:2b30::,2a02:2b30:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:2b38::,2a02:2b38:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2b40::,2a02:2b47:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:2b48::,2a02:2b48:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2b50::,2a02:2b50:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2b58::,2a02:2b58:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:2b80::,2a02:2b80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2b88::,2a02:2b88:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:2b90::,2a02:2b97:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2b98::,2a02:2b98:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:2ba0::,2a02:2ba0:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a02:2ba8::,2a02:2ba8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2bb0::,2a02:2bb0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:2bb8::,2a02:2bb8:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2bc0::,2a02:2bc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2be0::,2a02:2be0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2c00::,2a02:2c07:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:2c40::,2a02:2c40:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:2c60::,2a02:2c60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2c80::,2a02:2c80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2ca0::,2a02:2ca0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2cc0::,2a02:2cc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2ce0::,2a02:2ce0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:2d00::,2a02:2d00:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:2d20::,2a02:2d20:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:2d40::,2a02:2d40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2d60::,2a02:2d60:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2d80::,2a02:2d80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2da0::,2a02:2da0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:2dc0::,2a02:2dc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2de0::,2a02:2de0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:2e00::,2a02:2e1f:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2f00::,2a02:2f0f:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:2f80::,2a02:2f80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:2fa0::,2a02:2fa0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:2fc0::,2a02:2fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:2fe0::,2a02:2fe0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:3000::,2a02:31ff:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4000::,2a02:4000:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:4020::,2a02:4020:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:4040::,2a02:4040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4060::,2a02:4060:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:4080::,2a02:4080:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a02:40a0::,2a02:40a0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:40c0::,2a02:40c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:40e0::,2a02:40e0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:4100::,2a02:4100:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4120::,2a02:4120:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:4140::,2a02:4140:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:4160::,2a02:4160:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:4180::,2a02:4180:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a02:41a0::,2a02:41a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:41c0::,2a02:41c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:41e0::,2a02:41e0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:4200::,2a02:4200:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:4220::,2a02:4220:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:4240::,2a02:4240:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4260::,2a02:4260:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:4280::,2a02:4280:ffff:ffff:ffff:ffff:ffff:ffff,ME +2a02:42a0::,2a02:42a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:42c0::,2a02:42c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:42e0::,2a02:42e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:4300::,2a02:4300:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:4320::,2a02:4320:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:4340::,2a02:4340:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4360::,2a02:4360:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:43a0::,2a02:43a0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a02:43c0::,2a02:43c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:43e0::,2a02:43e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4420::,2a02:4420:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:4440::,2a02:4440:ffff:ffff:ffff:ffff:ffff:ffff,QA +2a02:4460::,2a02:4460:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:4480::,2a02:4480:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:44a0::,2a02:44a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:44c0::,2a02:44c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:44e0::,2a02:44e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4500::,2a02:4500:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4520::,2a02:4520:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a02:4540::,2a02:4540:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:4560::,2a02:4560:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:45a0::,2a02:45a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:45c0::,2a02:45c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:45e0::,2a02:45e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4600::,2a02:4600:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4620::,2a02:4620:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:4640::,2a02:4640:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4660::,2a02:4660:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4680::,2a02:4680:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:46a0::,2a02:46a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:46c0::,2a02:46c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:46e0::,2a02:46e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4700::,2a02:4700:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:4720::,2a02:4720:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4740::,2a02:4740:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4760::,2a02:4760:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:4780::,2a02:4780:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:47a0::,2a02:47a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:47c0::,2a02:47c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:47e0::,2a02:47e0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:4800::,2a02:4800:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:4820::,2a02:4820:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:4840::,2a02:4840:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a02:4860::,2a02:4860:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4880::,2a02:4880:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:48a0::,2a02:48a0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:48e0::,2a02:48e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4900::,2a02:4907:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:4940::,2a02:4940:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:4960::,2a02:4960:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:4980::,2a02:4980:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:49a0::,2a02:49a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:49c0::,2a02:49c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:49e0::,2a02:49e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4a00::,2a02:4a00:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:4a20::,2a02:4a20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4a40::,2a02:4a40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:4a60::,2a02:4a60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4aa0::,2a02:4aa0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4ac0::,2a02:4ac0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:4ae0::,2a02:4ae0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4b00::,2a02:4b07:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:4b40::,2a02:4b40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4b60::,2a02:4b60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:4b80::,2a02:4b80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4ba0::,2a02:4ba0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:4bc0::,2a02:4bc0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:4be0::,2a02:4be0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:4c00::,2a02:4c00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4c20::,2a02:4c20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4c40::,2a02:4c47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4c80::,2a02:4c80:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:4ca0::,2a02:4ca0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4cc0::,2a02:4cc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4ce0::,2a02:4ce0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4d00::,2a02:4d00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4d20::,2a02:4d20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4d40::,2a02:4d40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:4d60::,2a02:4d60:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a02:4d80::,2a02:4d80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4da0::,2a02:4da0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:4dc0::,2a02:4dc0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:4de0::,2a02:4de0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:4e20::,2a02:4e20:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4e40::,2a02:4e40:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:4e60::,2a02:4e60:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:4ea0::,2a02:4ea0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:4ec0::,2a02:4ec0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4ee0::,2a02:4ee0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:4f00::,2a02:4f00:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:4f20::,2a02:4f20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4f40::,2a02:4f40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:4f60::,2a02:4f60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:4f80::,2a02:4f80:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:4fa0::,2a02:4fa0:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a02:4fc0::,2a02:4fc0:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:4fe0::,2a02:4fe0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:5000::,2a02:5000:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5020::,2a02:5020:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5040::,2a02:5040:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:5060::,2a02:5060:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5080::,2a02:5080:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:50a0::,2a02:50a0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:50c0::,2a02:50c0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a02:50e0::,2a02:50e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5100::,2a02:5100:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5120::,2a02:5120:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:5140::,2a02:5140:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5160::,2a02:5160:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5180::,2a02:5180:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:51a0::,2a02:51a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:51c0::,2a02:51c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:51e0::,2a02:51e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5200::,2a02:5200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5220::,2a02:5220:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:5260::,2a02:5260:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:5280::,2a02:5280:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:52a0::,2a02:52a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:52e0::,2a02:52e0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5300::,2a02:5300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5320::,2a02:5320:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a02:5340::,2a02:5340:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:5360::,2a02:5360:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5380::,2a02:5380:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:53a0::,2a02:53a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:53c0::,2a02:53c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:53e0::,2a02:53e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:5400::,2a02:5400:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5420::,2a02:5420:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:5440::,2a02:5440:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:5460::,2a02:5460:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5480::,2a02:5480:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:54a0::,2a02:54a0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:54c0::,2a02:54c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:54e0::,2a02:54e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:5500::,2a02:5500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5520::,2a02:5520:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5540::,2a02:5540:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5560::,2a02:5560:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:5580::,2a02:5580:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a02:55a0::,2a02:55a0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:55c0::,2a02:55c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:55e0::,2a02:55e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:5600::,2a02:5600:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5620::,2a02:5620:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:5640::,2a02:5640:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:5660::,2a02:5660:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:5680::,2a02:5680:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:56a0::,2a02:56a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:56c0::,2a02:56c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:56e0::,2a02:56e0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5720::,2a02:5720:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a02:5740::,2a02:5740:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a02:5760::,2a02:5760:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5780::,2a02:5780:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:57a0::,2a02:57a0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:57c0::,2a02:57c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:57e0::,2a02:57e0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:5800::,2a02:5800:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5820::,2a02:5820:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5840::,2a02:5840:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5860::,2a02:5860:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5880::,2a02:5880:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:58a0::,2a02:58a0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:58c0::,2a02:58c0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:58e0::,2a02:58e0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5900::,2a02:5900:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:5920::,2a02:5920:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:5940::,2a02:5940:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:5960::,2a02:5960:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a02:5980::,2a02:5980:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:59a0::,2a02:59a0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:59c0::,2a02:59c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:59e0::,2a02:59e0:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:5a20::,2a02:5a20:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:5a40::,2a02:5a40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5a60::,2a02:5a60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5a80::,2a02:5a87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:5aa0::,2a02:5aa0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5ac0::,2a02:5ac0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:5ae0::,2a02:5ae0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5b00::,2a02:5b00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5b20::,2a02:5b20:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:5b40::,2a02:5b40:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:5b60::,2a02:5b60:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a02:5b80::,2a02:5b80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:5ba0::,2a02:5ba0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5bc0::,2a02:5bc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5be0::,2a02:5be0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5c20::,2a02:5c20:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:5c40::,2a02:5c40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5c60::,2a02:5c60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5ca0::,2a02:5ca0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:5cc0::,2a02:5cc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5ce0::,2a02:5ce0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5d00::,2a02:5d00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:5d20::,2a02:5d20:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:5d40::,2a02:5d40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5d60::,2a02:5d60:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5d80::,2a02:5d80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5da0::,2a02:5da0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:5dc0::,2a02:5dc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5de0::,2a02:5de0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:5e00::,2a02:5e00:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:5e40::,2a02:5e40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:5e60::,2a02:5e60:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:5e80::,2a02:5e80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:5ea0::,2a02:5ea0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5ec0::,2a02:5ec0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:5ee0::,2a02:5ee0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a02:5f00::,2a02:5f00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:5f20::,2a02:5f20:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:5f40::,2a02:5f40:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a02:5f60::,2a02:5f60:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:5f80::,2a02:5f80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:5fa0::,2a02:5fa0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:5fc0::,2a02:5fc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:5fe0::,2a02:5fe0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:6000::,2a02:6000:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:6020::,2a02:6020:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a02:6040::,2a02:6040:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:6060::,2a02:6060:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:60a0::,2a02:60a0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:60c0::,2a02:60c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:60e0::,2a02:60e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6100::,2a02:6100:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6120::,2a02:6120:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:6140::,2a02:6140:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6160::,2a02:6160:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6180::,2a02:6180:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:61a0::,2a02:61a0:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a02:61c0::,2a02:61c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:61e0::,2a02:61e0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:6200::,2a02:6207:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:6240::,2a02:6240:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:6260::,2a02:6260:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:6280::,2a02:6280:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:62a0::,2a02:62a0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:62c0::,2a02:62c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:62e0::,2a02:62e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6300::,2a02:6300:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:6320::,2a02:6320:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a02:6340::,2a02:6340:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:6360::,2a02:6360:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:6380::,2a02:6380:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:63a0::,2a02:63a0:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:63c0::,2a02:63c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:63e0::,2a02:63e0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:6400::,2a02:6400:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:6420::,2a02:6420:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:6440::,2a02:6440:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:6460::,2a02:6460:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:6480::,2a02:6480:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:64a0::,2a02:64a0:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:64c0::,2a02:64c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:64e0::,2a02:64e0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6500::,2a02:6500:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:6520::,2a02:6520:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:6540::,2a02:6540:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6560::,2a02:6560:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6580::,2a02:6580:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:65a0::,2a02:65a0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:65c0::,2a02:65c0:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a02:65e0::,2a02:65e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6600::,2a02:6600:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:6620::,2a02:6620:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6640::,2a02:6640:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:6660::,2a02:6660:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6680::,2a02:6680:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:66a0::,2a02:66a0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:66c0::,2a02:66c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:66e0::,2a02:66e0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:6700::,2a02:6700:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:6720::,2a02:6720:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:6740::,2a02:6740:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:6760::,2a02:6760:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6780::,2a02:6780:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:67a0::,2a02:67a0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a02:67c0::,2a02:67c0:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a02:67e0::,2a02:67e0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:6800::,2a02:6800:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:6820::,2a02:6820:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:6840::,2a02:6840:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6860::,2a02:6860:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:6880::,2a02:6880:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:68a0::,2a02:68a0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a02:68c0::,2a02:68c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:68e0::,2a02:68e0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6900::,2a02:6900:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:6920::,2a02:6920:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6940::,2a02:6940:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:6960::,2a02:6960:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6980::,2a02:6980:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:69a0::,2a02:69a0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:69c0::,2a02:69c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:69e0::,2a02:69e0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:6a00::,2a02:6a00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:6a20::,2a02:6a20:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6a40::,2a02:6a40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:6a60::,2a02:6a60:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:6a80::,2a02:6a80:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:6aa0::,2a02:6aa0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:6ac0::,2a02:6ac0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6ae0::,2a02:6ae0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:6b00::,2a02:6b00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6b20::,2a02:6b20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:6b40::,2a02:6b40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:6b60::,2a02:6b60:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6b80::,2a02:6b80:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a02:6ba0::,2a02:6ba0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6bc0::,2a02:6bc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6be0::,2a02:6be0:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:6c00::,2a02:6c00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6c20::,2a02:6c20:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:6c40::,2a02:6c40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6c60::,2a02:6c60:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:6c80::,2a02:6c80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6ca0::,2a02:6ca0:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:6cc0::,2a02:6cc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6ce0::,2a02:6ce0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:6d00::,2a02:6d00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6d40::,2a02:6d40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:6d80::,2a02:6d80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:6dc0::,2a02:6dc0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:6e00::,2a02:6e00:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:6e80::,2a02:6e80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:6ec0::,2a02:6ec0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:6f00::,2a02:6f00:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:6f40::,2a02:6f40:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:6f80::,2a02:6f80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:6fc0::,2a02:6fc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7000::,2a02:7007:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a02:7040::,2a02:7040:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:7080::,2a02:7080:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:70c0::,2a02:70c0:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a02:7100::,2a02:7100:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:7140::,2a02:7140:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7180::,2a02:7180:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:71c0::,2a02:71c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7200::,2a02:7200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:7240::,2a02:7240:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:7280::,2a02:7280:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:72c0::,2a02:72c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:7300::,2a02:7300:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a02:7340::,2a02:7340:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:7380::,2a02:7380:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:73c0::,2a02:73c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7440::,2a02:7440:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:7480::,2a02:7480:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:74c0::,2a02:74c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:7500::,2a02:7500:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a02:7540::,2a02:7540:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:7580::,2a02:7580:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:75c0::,2a02:75c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:7600::,2a02:7600:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:7640::,2a02:7640:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:7680::,2a02:7680:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:76c0::,2a02:76c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:7700::,2a02:7700:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7740::,2a02:7740:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a02:7780::,2a02:7780:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a02:77c0::,2a02:77c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7800::,2a02:7800:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:7840::,2a02:7840:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:7880::,2a02:7880:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:78c0::,2a02:78c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:7900::,2a02:7900:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:7940::,2a02:7940:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:7980::,2a02:7980:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a02:79c0::,2a02:79c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:7a00::,2a02:7a00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:7a80::,2a02:7a80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:7ac0::,2a02:7ac0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:7b00::,2a02:7b00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:7b40::,2a02:7b40:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:7b80::,2a02:7b80:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:7bc0::,2a02:7bc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:7c00::,2a02:7c00:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:7c40::,2a02:7c40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:7c80::,2a02:7c80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:7d00::,2a02:7d00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:7d40::,2a02:7d40:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:7d80::,2a02:7d80:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:7dc0::,2a02:7dc0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:7e00::,2a02:7e00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:7e40::,2a02:7e40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:7e80::,2a02:7e80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:7ec0::,2a02:7ec0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:7f00::,2a02:7f00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7f40::,2a02:7f40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:7f80::,2a02:7f80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:7fc0::,2a02:7fc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:8000::,2a02:81ff:ffff:ffff:ffff:ffff:ffff:ffff,DJ +2a02:8200::,2a02:821f:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:8300::,2a02:830f:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:8380::,2a02:838f:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:8400::,2a02:84ff:ffff:ffff:ffff:ffff:ffff:ffff,SX +2a02:8800::,2a02:88ff:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:9000::,2a02:91ff:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:a000::,2a02:a0ff:ffff:ffff:ffff:ffff:ffff:ffff,BF +2a02:a200::,2a02:a21f:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:a300::,2a02:a31f:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:a400::,2a02:a47f:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:a800::,2a02:a83f:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:aa00::,2a02:aa1f:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:ab00::,2a02:ab07:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a02:ab40::,2a02:ab47:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:ab80::,2a02:ab8f:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:ac00::,2a02:ac07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:ac40::,2a02:ac47:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:ac80::,2a02:ac87:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:acc0::,2a02:acc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ad40::,2a02:ad47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ad80::,2a02:ad87:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:adc0::,2a02:adc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ae00::,2a02:ae07:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a02:ae40::,2a02:ae47:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:ae80::,2a02:ae87:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:aec0::,2a02:aec7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:af00::,2a02:af07:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:af40::,2a02:af47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:af80::,2a02:af87:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:afc0::,2a02:afc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:b000::,2a02:b1ff:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:c000::,2a02:c007:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c080::,2a02:c087:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:c0c0::,2a02:c0c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:c100::,2a02:c107:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c140::,2a02:c147:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c180::,2a02:c187:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:c1c0::,2a02:c1c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c200::,2a02:c207:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c280::,2a02:c287:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:c2c0::,2a02:c2c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c300::,2a02:c307:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:c340::,2a02:c347:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:c380::,2a02:c381:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:c390::,2a02:c397:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:c3a0::,2a02:c3a3:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:c3c0::,2a02:c3c7:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a02:c400::,2a02:c407:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a02:c440::,2a02:c447:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:c480::,2a02:c487:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:c4c0::,2a02:c4c7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:c500::,2a02:c507:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:c540::,2a02:c547:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:c580::,2a02:c587:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:c5c0::,2a02:c5c7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:c600::,2a02:c607:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:c640::,2a02:c647:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:c680::,2a02:c681:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:c6a0::,2a02:c6a3:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c6c0::,2a02:c6c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c700::,2a02:c707:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:c740::,2a02:c747:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:c780::,2a02:c787:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a02:c7c0::,2a02:c7c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:c800::,2a02:c807:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c840::,2a02:c847:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:c880::,2a02:c887:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:c8c0::,2a02:c8c7:ffff:ffff:ffff:ffff:ffff:ffff,UZ +2a02:c900::,2a02:c907:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:c940::,2a02:c947:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:c980::,2a02:c987:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:c9c0::,2a02:c9c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ca00::,2a02:ca07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ca40::,2a02:ca47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ca80::,2a02:ca87:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:cac0::,2a02:cac7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:cb00::,2a02:cb07:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:cb40::,2a02:cb47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:cb80::,2a02:cb87:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:cbc0::,2a02:cbc3:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a02:cbe0::,2a02:cbe1:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:cbf0::,2a02:cbf1:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:cc00::,2a02:cc07:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:cc40::,2a02:cc47:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:cc80::,2a02:cc87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ccc0::,2a02:ccc7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:cd00::,2a02:cd07:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:cd40::,2a02:cd47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:cd80::,2a02:cd87:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:cdc0::,2a02:cdc7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:ce00::,2a02:ce07:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a02:ce40::,2a02:ce47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:ce80::,2a02:ce87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:cec0::,2a02:cec3:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:cee0::,2a02:cee3:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:cf00::,2a02:cf07:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:cf80::,2a02:cf87:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:cfc0::,2a02:cfc7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:d000::,2a02:d007:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:d040::,2a02:d047:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:d080::,2a02:d087:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a02:d0c0::,2a02:d0c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:d100::,2a02:d107:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:d140::,2a02:d147:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:d180::,2a02:d187:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d1c0::,2a02:d1c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:d200::,2a02:d207:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:d240::,2a02:d247:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a02:d280::,2a02:d287:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:d2c0::,2a02:d2c7:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:d300::,2a02:d307:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:d340::,2a02:d347:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:d380::,2a02:d387:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:d3c0::,2a02:d3c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:d400::,2a02:d407:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:d440::,2a02:d447:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:d480::,2a02:d487:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d4c0::,2a02:d4c3:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a02:d4e0::,2a02:d4e3:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d500::,2a02:d507:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:d540::,2a02:d547:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:d580::,2a02:d587:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:d5c0::,2a02:d5c7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:d600::,2a02:d607:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d640::,2a02:d647:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:d680::,2a02:d683:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:d6a0::,2a02:d6a3:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d6c0::,2a02:d6c7:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a02:d700::,2a02:d707:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:d740::,2a02:d747:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:d780::,2a02:d787:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:d7c0::,2a02:d7c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:d800::,2a02:d807:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:d840::,2a02:d847:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:d880::,2a02:d887:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:d8c0::,2a02:d8c7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:d900::,2a02:d907:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:d940::,2a02:d947:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a02:d980::,2a02:d987:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:d9c0::,2a02:d9c7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:da00::,2a02:da07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:da40::,2a02:da47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:da80::,2a02:da87:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:dac0::,2a02:dac7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:db00::,2a02:db07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:db40::,2a02:db47:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:db80::,2a02:db87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:dbc0::,2a02:dbc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:dc00::,2a02:dc07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:dc40::,2a02:dc47:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:dc80::,2a02:dc87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:dcc0::,2a02:dcc7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:dd00::,2a02:dd07:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a02:dd40::,2a02:dd47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:dd80::,2a02:dd87:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:ddc0::,2a02:ddc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:de00::,2a02:de07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:de40::,2a02:de47:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:de80::,2a02:de87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:dec0::,2a02:dec7:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a02:df00::,2a02:df07:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:df40::,2a02:df47:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:df80::,2a02:df87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:dfc0::,2a02:dfc7:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:e000::,2a02:e007:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:e040::,2a02:e047:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:e080::,2a02:e087:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a02:e0c0::,2a02:e0c7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:e100::,2a02:e107:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:e140::,2a02:e147:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:e180::,2a02:e187:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:e1c0::,2a02:e1c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:e200::,2a02:e203:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:e220::,2a02:e223:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:e240::,2a02:e247:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:e280::,2a02:e287:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:e2c0::,2a02:e2c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:e300::,2a02:e307:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a02:e340::,2a02:e347:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:e380::,2a02:e387:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:e3c0::,2a02:e3c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:e400::,2a02:e407:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:e440::,2a02:e447:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:e480::,2a02:e487:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:e4c0::,2a02:e4c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:e500::,2a02:e507:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:e540::,2a02:e547:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a02:e580::,2a02:e587:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:e5c0::,2a02:e5c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:e600::,2a02:e603:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:e620::,2a02:e623:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:e640::,2a02:e647:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:e680::,2a02:e687:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a02:e700::,2a02:e707:ffff:ffff:ffff:ffff:ffff:ffff,LY +2a02:e740::,2a02:e747:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:e780::,2a02:e787:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:e7c0::,2a02:e7c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:e800::,2a02:e807:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:e840::,2a02:e847:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:e880::,2a02:e887:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:e900::,2a02:e907:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a02:e940::,2a02:e947:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a02:e980::,2a02:e987:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a02:e9c0::,2a02:e9c7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:ea00::,2a02:ea07:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a02:ea40::,2a02:ea47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:ea80::,2a02:ea87:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:eac0::,2a02:eac7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:eb00::,2a02:eb07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:eb40::,2a02:eb47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:eb80::,2a02:eb87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ebc0::,2a02:ebc7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:ec00::,2a02:ec07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:ec40::,2a02:ec47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ec80::,2a02:ec87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:ecc0::,2a02:ecc7:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a02:ed00::,2a02:ed07:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:ed40::,2a02:ed47:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:ed80::,2a02:ed87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:edc0::,2a02:edc7:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:ee00::,2a02:ee07:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:ee40::,2a02:ee47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ee80::,2a02:ee87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:eec0::,2a02:eec7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:ef00::,2a02:ef07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ef40::,2a02:ef47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:ef80::,2a02:ef87:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:efc0::,2a02:efc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f000::,2a02:f007:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a02:f040::,2a02:f047:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a02:f080::,2a02:f083:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:f0a0::,2a02:f0a3:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f0c0::,2a02:f0c7:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a02:f100::,2a02:f107:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f140::,2a02:f147:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f180::,2a02:f187:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:f1c0::,2a02:f1c7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a02:f200::,2a02:f207:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f240::,2a02:f247:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:f280::,2a02:f287:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a02:f2c0::,2a02:f2c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f300::,2a02:f307:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:f340::,2a02:f347:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f380::,2a02:f387:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f3c0::,2a02:f3c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:f400::,2a02:f407:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a02:f440::,2a02:f447:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f480::,2a02:f487:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:f4c0::,2a02:f4c7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a02:f500::,2a02:f507:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f540::,2a02:f543:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f560::,2a02:f563:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f580::,2a02:f587:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a02:f5c0::,2a02:f5c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:f600::,2a02:f607:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:f640::,2a02:f647:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:f680::,2a02:f687:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f6c0::,2a02:f6c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f700::,2a02:f707:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a02:f740::,2a02:f747:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:f780::,2a02:f787:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:f7c0::,2a02:f7c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:f800::,2a02:f807:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a02:f840::,2a02:f847:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:f880::,2a02:f887:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:f8c0::,2a02:f8c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:f900::,2a02:f907:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a02:f940::,2a02:f947:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a02:f980::,2a02:f987:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:f9c0::,2a02:f9c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:fa00::,2a02:fa07:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a02:fa40::,2a02:fa47:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a02:fa80::,2a02:fa87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:fac0::,2a02:fac7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:fb00::,2a02:fb07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:fb40::,2a02:fb47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:fb80::,2a02:fb87:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:fbc0::,2a02:fbc7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a02:fc00::,2a02:fc07:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a02:fc40::,2a02:fc47:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:fc80::,2a02:fc87:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a02:fcc0::,2a02:fcc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:fd00::,2a02:fd07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:fd40::,2a02:fd47:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:fd80::,2a02:fd87:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a02:fdc0::,2a02:fdc7:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a02:fe00::,2a02:fe07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a02:fe40::,2a02:fe47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:fec0::,2a02:fec7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a02:ff00::,2a02:ff07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a02:ff40::,2a02:ff47:ffff:ffff:ffff:ffff:ffff:ffff,IM +2a02:ff80::,2a02:ff87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a02:ffc0::,2a02:ffc7:ffff:ffff:ffff:ffff:ffff:ffff,GI +2a03:40::,2a03:40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:80::,2a03:80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:c0::,2a03:c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:100::,2a03:100:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a03:140::,2a03:140:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:180::,2a03:180:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a03:1c0::,2a03:1c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:200::,2a03:200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:240::,2a03:247:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:280::,2a03:280:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a03:2c0::,2a03:2c0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:300::,2a03:300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:340::,2a03:340:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:380::,2a03:380:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:3c0::,2a03:3c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:400::,2a03:400:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:440::,2a03:440:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:480::,2a03:480:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4c0::,2a03:4c0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:500::,2a03:500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:540::,2a03:540:ffff:ffff:ffff:ffff:ffff:ffff,UZ +2a03:580::,2a03:580:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:5c0::,2a03:5c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:600::,2a03:600:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:640::,2a03:640:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:680::,2a03:680:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:6c0::,2a03:6c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:700::,2a03:700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:740::,2a03:740:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:780::,2a03:780:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:7c0::,2a03:7c0:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a03:800::,2a03:800:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:840::,2a03:840:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:880::,2a03:880:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:8c0::,2a03:8c0:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a03:900::,2a03:900:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:940::,2a03:940:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:980::,2a03:980:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a03:9c0::,2a03:9c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:a00::,2a03:a00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:a40::,2a03:a40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:a80::,2a03:a80:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a03:ac0::,2a03:ac0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:b00::,2a03:b00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:b40::,2a03:b40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:b80::,2a03:b80:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:bc0::,2a03:bc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:c00::,2a03:c00:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:c40::,2a03:c40:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a03:c80::,2a03:c80:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:cc0::,2a03:cc0:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:d00::,2a03:d00:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:d40::,2a03:d40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:d80::,2a03:d80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:dc0::,2a03:dc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:e00::,2a03:e00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:e40::,2a03:e40:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a03:e80::,2a03:e80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ec0::,2a03:ec0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:f00::,2a03:f07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:f40::,2a03:f40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:f80::,2a03:f87:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:fc0::,2a03:fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:1000::,2a03:1000:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:1040::,2a03:1040:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:1080::,2a03:1080:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a03:10c0::,2a03:10c3:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:1100::,2a03:1100:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:1140::,2a03:1140:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:1180::,2a03:1180:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:11c0::,2a03:11c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:1200::,2a03:1200:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:1240::,2a03:1240:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:1280::,2a03:1280:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:12c0::,2a03:12c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:1300::,2a03:1300:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a03:1340::,2a03:1340:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:1380::,2a03:1380:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:13c0::,2a03:13c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1400::,2a03:1400:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:1440::,2a03:1440:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:1480::,2a03:1480:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:14c0::,2a03:14c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1500::,2a03:1500:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:1540::,2a03:1540:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:1580::,2a03:1580:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:15c0::,2a03:15c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:1600::,2a03:1600:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:1640::,2a03:1640:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1680::,2a03:1680:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:16c0::,2a03:16c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:1700::,2a03:1707:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:1740::,2a03:1740:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1780::,2a03:1780:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:17c0::,2a03:17c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1800::,2a03:1800:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1840::,2a03:1840:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:1880::,2a03:1880:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:18c0::,2a03:18c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:1900::,2a03:1900:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a03:1940::,2a03:1940:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:1980::,2a03:1980:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:1a00::,2a03:1a00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:1a40::,2a03:1a40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:1a80::,2a03:1a80:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:1ac0::,2a03:1ac0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1b00::,2a03:1b00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:1b40::,2a03:1b40:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a03:1b80::,2a03:1b80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:1bc0::,2a03:1bc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:1c00::,2a03:1c00:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a03:1c40::,2a03:1c40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:1c80::,2a03:1c80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:1cc0::,2a03:1cc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:1d00::,2a03:1d00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:1d40::,2a03:1d40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:1d80::,2a03:1d80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a03:1dc0::,2a03:1dc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:1e00::,2a03:1e00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:1e40::,2a03:1e40:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:1e80::,2a03:1e80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:1ec0::,2a03:1ec0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:1f00::,2a03:1f00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:1f40::,2a03:1f40:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:1f80::,2a03:1f80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:2000::,2a03:2000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:2040::,2a03:2040:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:2080::,2a03:2080:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:20c0::,2a03:20c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:2100::,2a03:2100:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:2140::,2a03:2140:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:2180::,2a03:2180:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:21c0::,2a03:21c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:2200::,2a03:2200:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:2240::,2a03:2240:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:2280::,2a03:2280:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:22c0::,2a03:22c0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:2300::,2a03:2300:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a03:2340::,2a03:2340:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:2380::,2a03:2380:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:23c0::,2a03:23c0:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a03:2400::,2a03:2400:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:2440::,2a03:2440:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:2480::,2a03:2480:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:24c0::,2a03:24c0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:2500::,2a03:2500:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:2540::,2a03:2540:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:2580::,2a03:2580:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:25c0::,2a03:25c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:2600::,2a03:2600:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:2640::,2a03:2640:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:2680::,2a03:2680:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:26c0::,2a03:26c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:2700::,2a03:2700:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:2740::,2a03:2740:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:2780::,2a03:2780:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:27c0::,2a03:27c0:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a03:2800::,2a03:2800:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:2840::,2a03:2840:ffff:ffff:ffff:ffff:ffff:ffff,US +2a03:2880::,2a03:2880:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:28c0::,2a03:28c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:2900::,2a03:2900:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:2940::,2a03:2940:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a03:2980::,2a03:2980:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:29c0::,2a03:29c0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a03:2a00::,2a03:2a00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:2a40::,2a03:2a40:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a03:2a80::,2a03:2a80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:2ac0::,2a03:2ac0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:2b00::,2a03:2b00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:2b40::,2a03:2b40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:2b80::,2a03:2b80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:2bc0::,2a03:2bc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:2c00::,2a03:2c00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:2c40::,2a03:2c40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:2c80::,2a03:2c80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:2cc0::,2a03:2cc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:2d00::,2a03:2d00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:2d80::,2a03:2d80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:2dc0::,2a03:2dc0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:2e00::,2a03:2e00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:2e40::,2a03:2e40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:2ec0::,2a03:2ec0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:2f00::,2a03:2f00:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a03:2f40::,2a03:2f40:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:2f80::,2a03:2f80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:2fc0::,2a03:2fc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:3000::,2a03:3000:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a03:3040::,2a03:3040:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:30c0::,2a03:30c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:3100::,2a03:3100:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3140::,2a03:3140:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:3180::,2a03:3180:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:31c0::,2a03:31c0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:3200::,2a03:3200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3240::,2a03:3240:ffff:ffff:ffff:ffff:ffff:ffff,UZ +2a03:3280::,2a03:3280:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:32c0::,2a03:32c0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a03:3300::,2a03:3300:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:3340::,2a03:3340:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:3380::,2a03:3380:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:33c0::,2a03:33c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:3400::,2a03:3400:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:3440::,2a03:3440:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a03:3480::,2a03:3480:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:34c0::,2a03:34c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:3500::,2a03:3500:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:3540::,2a03:3540:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:3580::,2a03:3580:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a03:35c0::,2a03:35c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:3600::,2a03:3600:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:3640::,2a03:3640:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:3680::,2a03:3680:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:36c0::,2a03:36c0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:3700::,2a03:3700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:37c0::,2a03:37c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:3800::,2a03:3800:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:3840::,2a03:3840:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:3880::,2a03:3880:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:38c0::,2a03:38c0:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:3900::,2a03:3900:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:3940::,2a03:3940:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:3980::,2a03:3980:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a03:39c0::,2a03:39c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:3a00::,2a03:3a00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:3a40::,2a03:3a40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:3a80::,2a03:3a80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3ac0::,2a03:3ac0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:3b00::,2a03:3b00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:3b40::,2a03:3b40:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:3b80::,2a03:3b80:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:3bc0::,2a03:3bc0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:3c00::,2a03:3c00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:3c40::,2a03:3c40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:3c80::,2a03:3c80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:3cc0::,2a03:3cc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3d00::,2a03:3d00:ffff:ffff:ffff:ffff:ffff:ffff,AM +2a03:3d40::,2a03:3d40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3d80::,2a03:3d80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:3dc0::,2a03:3dc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3e00::,2a03:3e00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:3e40::,2a03:3e40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3e80::,2a03:3e80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:3ec0::,2a03:3ec0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:3f00::,2a03:3f00:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:3f40::,2a03:3f40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:3f80::,2a03:3f80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:3fc0::,2a03:3fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:4000::,2a03:4000:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:4040::,2a03:4040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:4080::,2a03:4080:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:40c0::,2a03:40c0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:4100::,2a03:4107:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:4140::,2a03:4140:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:4180::,2a03:4180:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:41c0::,2a03:41c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4200::,2a03:4200:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4240::,2a03:4240:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:4280::,2a03:4280:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a03:42c0::,2a03:42c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:4300::,2a03:4307:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4340::,2a03:4340:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:4380::,2a03:4380:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:43c0::,2a03:43c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:4400::,2a03:4400:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:4440::,2a03:4440:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:4480::,2a03:4480:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a03:44c0::,2a03:44c0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:4500::,2a03:4500:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4540::,2a03:4540:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:4580::,2a03:4580:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:45c0::,2a03:45c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:4600::,2a03:4600:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:4640::,2a03:4640:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4680::,2a03:4680:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:46c0::,2a03:46c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:4700::,2a03:4700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:4740::,2a03:4740:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:4780::,2a03:4780:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a03:47c0::,2a03:47c7:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a03:4800::,2a03:4800:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:4840::,2a03:4847:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a03:4880::,2a03:4880:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:48c0::,2a03:48c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:4900::,2a03:4900:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:4940::,2a03:4940:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:4980::,2a03:4980:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:49c0::,2a03:49c0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:4a00::,2a03:4a00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:4a40::,2a03:4a40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:4a80::,2a03:4a80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:4ac0::,2a03:4ac0:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a03:4b00::,2a03:4b00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:4b40::,2a03:4b40:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a03:4b80::,2a03:4b80:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a03:4bc0::,2a03:4bc0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:4c00::,2a03:4c07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:4c40::,2a03:4c40:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:4c80::,2a03:4c80:ffff:ffff:ffff:ffff:ffff:ffff,LI +2a03:4cc0::,2a03:4cc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4d00::,2a03:4d00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:4d40::,2a03:4d40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:4d80::,2a03:4d80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:4dc0::,2a03:4dc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:4e00::,2a03:4e00:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:4e40::,2a03:4e40:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:4e80::,2a03:4e80:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a03:4ec0::,2a03:4ec0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:4f00::,2a03:4f00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:4f40::,2a03:4f40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:4f80::,2a03:4f80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:5000::,2a03:5000:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:5040::,2a03:5040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5080::,2a03:5080:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:50c0::,2a03:50c0:ffff:ffff:ffff:ffff:ffff:ffff,GI +2a03:5100::,2a03:5100:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:5140::,2a03:5140:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:5180::,2a03:5180:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:51c0::,2a03:51c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:5200::,2a03:5200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5240::,2a03:5240:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5280::,2a03:5280:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:52c0::,2a03:52c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5300::,2a03:5307:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:5380::,2a03:5380:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:53c0::,2a03:53c0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:5400::,2a03:5400:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:5440::,2a03:5440:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:5480::,2a03:5480:ffff:ffff:ffff:ffff:ffff:ffff,LI +2a03:54c0::,2a03:54c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:5500::,2a03:5501:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:5540::,2a03:5540:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:5580::,2a03:5587:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:55c0::,2a03:55c0:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:5600::,2a03:5600:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5640::,2a03:5640:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a03:5680::,2a03:5680:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:56c0::,2a03:56c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:5700::,2a03:5700:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:5740::,2a03:5740:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:5780::,2a03:5780:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a03:57c0::,2a03:57c0:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:5800::,2a03:5800:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5840::,2a03:5840:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:5880::,2a03:5880:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a03:58c0::,2a03:58c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5900::,2a03:5907:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a03:5940::,2a03:5940:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:5980::,2a03:5980:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:59c0::,2a03:59c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:5a00::,2a03:5a07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5a80::,2a03:5a80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5ac0::,2a03:5ac0:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:5b00::,2a03:5b00:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:5b40::,2a03:5b40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:5b80::,2a03:5b80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5bc0::,2a03:5bc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:5c00::,2a03:5c00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:5c40::,2a03:5c40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:5c80::,2a03:5c80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5cc0::,2a03:5cc0:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a03:5d00::,2a03:5d07:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:5d40::,2a03:5d40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:5d80::,2a03:5d80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:5dc0::,2a03:5dc0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:5e40::,2a03:5e40:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:5e80::,2a03:5e80:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:5ec0::,2a03:5ec0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:5f00::,2a03:5f00:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:5f80::,2a03:5f80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:5fc0::,2a03:5fc0:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:6000::,2a03:6000:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:6040::,2a03:6040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:6080::,2a03:6087:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:60c0::,2a03:60c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:6100::,2a03:6100:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a03:6140::,2a03:6140:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:6180::,2a03:6180:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:61c0::,2a03:61c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:6200::,2a03:6200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:6240::,2a03:6240:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:62c0::,2a03:62c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:6300::,2a03:6300:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:6340::,2a03:6340:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a03:6380::,2a03:6380:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a03:63c0::,2a03:63c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:6400::,2a03:6400:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:6440::,2a03:6440:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:6480::,2a03:6480:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:64c0::,2a03:64c0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:6500::,2a03:6500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:6540::,2a03:6540:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:6580::,2a03:6580:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:65c0::,2a03:65c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:6600::,2a03:6600:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:6640::,2a03:6640:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:6680::,2a03:6680:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:66c0::,2a03:66c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:6700::,2a03:6707:ffff:ffff:ffff:ffff:ffff:ffff,KW +2a03:6740::,2a03:6740:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a03:6780::,2a03:6780:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:67c0::,2a03:67c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:6800::,2a03:6800:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:6840::,2a03:6840:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6880::,2a03:6880:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:68c0::,2a03:68c0:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a03:6900::,2a03:6900:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a03:6940::,2a03:6940:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:6980::,2a03:6980:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:69c0::,2a03:69c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6a00::,2a03:6a00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:6a40::,2a03:6a40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:6a80::,2a03:6a80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6ac0::,2a03:6ac0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a03:6b00::,2a03:6b00:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a03:6b40::,2a03:6b40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6b80::,2a03:6b80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:6bc0::,2a03:6bc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:6c00::,2a03:6c00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6c40::,2a03:6c40:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:6c80::,2a03:6c80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6cc0::,2a03:6cc0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:6d00::,2a03:6d00:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a03:6d40::,2a03:6d40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6d80::,2a03:6d80:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:6dc0::,2a03:6dc0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a03:6e00::,2a03:6e00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:6e40::,2a03:6e40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6e80::,2a03:6e80:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:6ec0::,2a03:6ec0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:6f00::,2a03:6f00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:6f40::,2a03:6f40:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:6f80::,2a03:6f87:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:6fc0::,2a03:6fc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:7000::,2a03:7000:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:7040::,2a03:7040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:7080::,2a03:7080:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:70c0::,2a03:70c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:7100::,2a03:7100:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:7140::,2a03:7140:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:7180::,2a03:7180:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a03:71c0::,2a03:71c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:7200::,2a03:7200:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:7240::,2a03:7240:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:7280::,2a03:7280:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:72c0::,2a03:72c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:7300::,2a03:7300:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:7340::,2a03:7340:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7380::,2a03:7380:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:73c0::,2a03:73c0:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a03:7400::,2a03:7400:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:7440::,2a03:7440:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:7480::,2a03:7480:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:74c0::,2a03:74c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:7500::,2a03:7500:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7540::,2a03:7540:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:7580::,2a03:7580:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:75c0::,2a03:75c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:7640::,2a03:7640:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:7680::,2a03:7680:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:76c0::,2a03:76c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:7700::,2a03:7700:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7740::,2a03:7740:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a03:7780::,2a03:7780:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:77c0::,2a03:77c0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a03:7800::,2a03:7800:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:7840::,2a03:7840:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7880::,2a03:7880:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7900::,2a03:7900:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:7940::,2a03:7940:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:79c0::,2a03:79c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:7a00::,2a03:7a00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:7a40::,2a03:7a40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7a80::,2a03:7a80:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a03:7b00::,2a03:7b00:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:7b40::,2a03:7b40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:7b80::,2a03:7b80:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:7bc0::,2a03:7bc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7c00::,2a03:7c00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:7c40::,2a03:7c40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7c80::,2a03:7c80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:7cc0::,2a03:7cc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7d00::,2a03:7d00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:7d40::,2a03:7d40:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:7dc0::,2a03:7dc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:7e00::,2a03:7e00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:7e40::,2a03:7e40:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:7e80::,2a03:7e80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:7ec0::,2a03:7ec0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:7f00::,2a03:7f00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:7f40::,2a03:7f40:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:7f80::,2a03:7f80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:7fc0::,2a03:7fc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:8000::,2a03:8000:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:8040::,2a03:8040:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:8080::,2a03:8080:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:80c0::,2a03:80c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8100::,2a03:8100:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:8140::,2a03:8140:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8180::,2a03:8180:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:81c0::,2a03:81c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8200::,2a03:8200:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8240::,2a03:8240:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:8280::,2a03:8280:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:82c0::,2a03:82c0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:8300::,2a03:8300:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:8340::,2a03:8340:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:8380::,2a03:8380:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:83c0::,2a03:83c0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:8400::,2a03:8400:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8440::,2a03:8440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8480::,2a03:8480:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a03:84c0::,2a03:84c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8500::,2a03:8500:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:8540::,2a03:8540:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:8580::,2a03:8580:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:85c0::,2a03:85c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:8600::,2a03:8600:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:8640::,2a03:8640:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8680::,2a03:8680:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:86c0::,2a03:86c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:8700::,2a03:8700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8740::,2a03:8740:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8780::,2a03:8780:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:87c0::,2a03:87c0:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a03:8800::,2a03:8800:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:8840::,2a03:8840:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8880::,2a03:8880:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:88c0::,2a03:88c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:8900::,2a03:8900:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:8940::,2a03:8940:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:8980::,2a03:8980:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:89c0::,2a03:89c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:8a00::,2a03:8a00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8a40::,2a03:8a40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:8a80::,2a03:8a80:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:8b00::,2a03:8b00:ffff:ffff:ffff:ffff:ffff:ffff,SM +2a03:8b40::,2a03:8b40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:8b80::,2a03:8b80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:8bc0::,2a03:8bc0:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a03:8c00::,2a03:8c00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8c40::,2a03:8c40:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:8c80::,2a03:8c87:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:8cc0::,2a03:8cc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8d00::,2a03:8d00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:8d40::,2a03:8d40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:8dc0::,2a03:8dc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:8e00::,2a03:8e00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:8e40::,2a03:8e40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:8e80::,2a03:8e80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:8ec0::,2a03:8ec0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:8f00::,2a03:8f07:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:8f40::,2a03:8f40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:8f80::,2a03:8f80:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:8fc0::,2a03:8fc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:9000::,2a03:9000:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:9040::,2a03:9040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9080::,2a03:9080:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:90c0::,2a03:90c0:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:9100::,2a03:9100:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:9140::,2a03:9140:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:9180::,2a03:9180:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:91c0::,2a03:91c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:9240::,2a03:9240:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a03:9280::,2a03:9280:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:92c0::,2a03:92c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:9300::,2a03:9300:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:9340::,2a03:9340:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:9380::,2a03:9380:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:93c0::,2a03:93c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:9400::,2a03:9400:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:9440::,2a03:9440:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:9480::,2a03:9480:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:94c0::,2a03:94c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9500::,2a03:9500:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:9540::,2a03:9540:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:9580::,2a03:9580:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:95c0::,2a03:95c0:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a03:9600::,2a03:9600:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9640::,2a03:9640:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a03:9680::,2a03:9680:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a03:96c0::,2a03:96c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:9700::,2a03:9700:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:9740::,2a03:9740:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:9780::,2a03:9780:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:97c0::,2a03:97c1:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a03:9800::,2a03:9807:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9840::,2a03:9840:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:9880::,2a03:9880:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:98c0::,2a03:98c7:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a03:9900::,2a03:9900:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:9940::,2a03:9940:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:9980::,2a03:9980:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:99c0::,2a03:99c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9a00::,2a03:9a00:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:9a40::,2a03:9a40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:9a80::,2a03:9a80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:9ac0::,2a03:9ac0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:9b00::,2a03:9b00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:9b40::,2a03:9b40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:9b80::,2a03:9b80:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:9bc0::,2a03:9bc0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:9c00::,2a03:9c00:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:9c40::,2a03:9c40:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a03:9c80::,2a03:9c80:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a03:9cc0::,2a03:9cc7:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:9d00::,2a03:9d00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:9d40::,2a03:9d40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:9d80::,2a03:9d80:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a03:9dc0::,2a03:9dc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9e00::,2a03:9e00:ffff:ffff:ffff:ffff:ffff:ffff,IM +2a03:9e40::,2a03:9e47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:9e80::,2a03:9e80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9ec0::,2a03:9ec0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9f00::,2a03:9f00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:9f40::,2a03:9f40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:9f80::,2a03:9f80:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:a000::,2a03:a000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:a040::,2a03:a040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:a080::,2a03:a080:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:a0c0::,2a03:a0c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:a100::,2a03:a100:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a03:a140::,2a03:a140:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:a180::,2a03:a180:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:a1c0::,2a03:a1c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:a200::,2a03:a200:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a03:a240::,2a03:a240:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:a280::,2a03:a280:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:a2c0::,2a03:a2c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:a300::,2a03:a300:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a03:a340::,2a03:a340:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:a380::,2a03:a380:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:a3c0::,2a03:a3c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:a400::,2a03:a400:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:a440::,2a03:a440:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:a480::,2a03:a480:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:a4c0::,2a03:a4c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:a500::,2a03:a500:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:a540::,2a03:a540:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:a580::,2a03:a580:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:a5c0::,2a03:a5c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:a600::,2a03:a600:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:a640::,2a03:a640:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:a680::,2a03:a680:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:a6c0::,2a03:a6c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:a740::,2a03:a740:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:a780::,2a03:a780:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:a7c0::,2a03:a7c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:a800::,2a03:a800:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:a840::,2a03:a840:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:a8c0::,2a03:a8c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:a900::,2a03:a900:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:a940::,2a03:a940:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:a980::,2a03:a980:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:a9c0::,2a03:a9c0:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:aa00::,2a03:aa00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:aa40::,2a03:aa40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:aa80::,2a03:aa80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:aac0::,2a03:aac0:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a03:ab00::,2a03:ab00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:ab40::,2a03:ab40:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:ab80::,2a03:ab80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:abc0::,2a03:abc7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a03:ac00::,2a03:ac00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ac40::,2a03:ac40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:ac80::,2a03:ac80:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:acc0::,2a03:acc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ad00::,2a03:ad00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:ad40::,2a03:ad40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ad80::,2a03:ad80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:adc0::,2a03:adc0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:ae00::,2a03:ae00:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:ae40::,2a03:ae40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:ae80::,2a03:ae80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:aec0::,2a03:aec0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:af00::,2a03:af00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:af40::,2a03:af40:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a03:af80::,2a03:af80:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:afc0::,2a03:afc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:b000::,2a03:b000:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:b040::,2a03:b040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:b080::,2a03:b080:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a03:b0c0::,2a03:b0c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:b100::,2a03:b100:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:b140::,2a03:b140:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:b180::,2a03:b180:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a03:b1c0::,2a03:b1c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:b200::,2a03:b207:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:b240::,2a03:b240:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:b280::,2a03:b280:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:b300::,2a03:b300:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:b340::,2a03:b340:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:b380::,2a03:b380:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:b3c0::,2a03:b3c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:b400::,2a03:b400:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:b440::,2a03:b440:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:b480::,2a03:b480:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:b4c0::,2a03:b4c0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:b500::,2a03:b500:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a03:b540::,2a03:b540:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:b580::,2a03:b580:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:b5c0::,2a03:b5c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:b600::,2a03:b600:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:b640::,2a03:b640:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a03:b680::,2a03:b680:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:b6c0::,2a03:b6c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:b700::,2a03:b700:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:b740::,2a03:b740:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:b780::,2a03:b780:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:b7c0::,2a03:b7c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:b800::,2a03:b800:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:b840::,2a03:b840:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:b880::,2a03:b887:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:b8c0::,2a03:b8c0:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a03:b900::,2a03:b900:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:b940::,2a03:b940:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:b980::,2a03:b980:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:b9c0::,2a03:b9c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:ba00::,2a03:ba07:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:ba40::,2a03:ba40:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a03:ba80::,2a03:ba80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:bac0::,2a03:bac0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:bb00::,2a03:bb00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:bb40::,2a03:bb40:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a03:bb80::,2a03:bb80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:bbc0::,2a03:bbc0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:bc00::,2a03:bc00:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:bc40::,2a03:bc40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:bc80::,2a03:bc80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:bcc0::,2a03:bcc0:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a03:bd00::,2a03:bd00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:bd40::,2a03:bd47:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a03:bd80::,2a03:bd80:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:bdc0::,2a03:bdc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:be00::,2a03:be00:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:be40::,2a03:be40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:be80::,2a03:be80:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:bec0::,2a03:bec0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:bf00::,2a03:bf00:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:bf40::,2a03:bf40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:bf80::,2a03:bf80:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:bfc0::,2a03:bfc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:c000::,2a03:c007:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:c040::,2a03:c040:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:c080::,2a03:c080:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a03:c0c0::,2a03:c0c0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:c100::,2a03:c100:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:c140::,2a03:c140:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a03:c180::,2a03:c180:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:c1c0::,2a03:c1c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:c200::,2a03:c200:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:c240::,2a03:c240:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a03:c280::,2a03:c280:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:c2c0::,2a03:c2c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:c300::,2a03:c300:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:c340::,2a03:c340:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a03:c380::,2a03:c380:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:c3c0::,2a03:c3c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:c400::,2a03:c400:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:c440::,2a03:c440:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:c480::,2a03:c480:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a03:c4c0::,2a03:c4c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:c500::,2a03:c500:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:c540::,2a03:c540:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:c580::,2a03:c580:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:c5c0::,2a03:c5c0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a03:c600::,2a03:c600:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:c640::,2a03:c640:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:c680::,2a03:c680:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:c6c0::,2a03:c6c0:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:c700::,2a03:c700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:c740::,2a03:c740:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a03:c780::,2a03:c780:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:c7c0::,2a03:c7c7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:c800::,2a03:c800:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a03:c840::,2a03:c840:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a03:c880::,2a03:c880:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:c8c0::,2a03:c8c0:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:c900::,2a03:c900:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:c940::,2a03:c940:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:c980::,2a03:c980:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:c9c0::,2a03:c9c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:ca00::,2a03:ca00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:ca40::,2a03:ca40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:ca80::,2a03:ca87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:cac0::,2a03:cac0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a03:cb00::,2a03:cb00:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a03:cb40::,2a03:cb40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:cb80::,2a03:cb80:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a03:cbc0::,2a03:cbc7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:cc00::,2a03:cc00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:cc40::,2a03:cc40:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:cc80::,2a03:cc80:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a03:ccc0::,2a03:ccc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:cd00::,2a03:cd00:ffff:ffff:ffff:ffff:ffff:ffff,US +2a03:cd40::,2a03:cd40:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:cd80::,2a03:cd80:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a03:cdc0::,2a03:cdc0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:ce00::,2a03:ce00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:ce40::,2a03:ce47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:ce80::,2a03:ce80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:cf00::,2a03:cf00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:cf40::,2a03:cf40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:cf80::,2a03:cf80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:cfc0::,2a03:cfc0:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:d000::,2a03:d000:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:d040::,2a03:d040:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:d080::,2a03:d080:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:d0c0::,2a03:d0c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:d100::,2a03:d100:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:d140::,2a03:d140:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:d180::,2a03:d180:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:d1c0::,2a03:d1c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:d200::,2a03:d200:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:d280::,2a03:d280:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:d2c0::,2a03:d2c0:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:d300::,2a03:d300:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:d340::,2a03:d340:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:d380::,2a03:d380:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:d3c0::,2a03:d3c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:d400::,2a03:d400:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:d440::,2a03:d440:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:d480::,2a03:d480:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:d4c0::,2a03:d4c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:d500::,2a03:d500:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:d540::,2a03:d540:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:d580::,2a03:d587:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:d5c0::,2a03:d5c0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a03:d600::,2a03:d600:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:d640::,2a03:d640:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:d680::,2a03:d680:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:d6c0::,2a03:d6c0:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a03:d700::,2a03:d700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:d740::,2a03:d740:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:d780::,2a03:d780:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:d7c0::,2a03:d7c7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:d800::,2a03:d800:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:d840::,2a03:d840:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:d880::,2a03:d880:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:d8c0::,2a03:d8c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:d900::,2a03:d900:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:d940::,2a03:d940:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:d980::,2a03:d980:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:d9c0::,2a03:d9c0:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:da00::,2a03:da00:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:da40::,2a03:da40:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:da80::,2a03:da80:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:dac0::,2a03:dac0:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a03:db00::,2a03:db00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:db40::,2a03:db47:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a03:db80::,2a03:db80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:dbc0::,2a03:dbc0:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:dc00::,2a03:dc00:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:dc40::,2a03:dc40:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a03:dc80::,2a03:dc80:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:dcc0::,2a03:dcc0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:dd00::,2a03:dd00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:dd40::,2a03:dd40:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:dd80::,2a03:dd87:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a03:ddc0::,2a03:ddc0:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:de00::,2a03:de00:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:de40::,2a03:de40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:de80::,2a03:de80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:dec0::,2a03:dec0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:df00::,2a03:df00:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:df40::,2a03:df40:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a03:df80::,2a03:df80:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a03:dfc0::,2a03:dfc0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:e000::,2a03:e000:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:e040::,2a03:e040:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e080::,2a03:e080:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:e0c0::,2a03:e0c0:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:e100::,2a03:e100:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:e140::,2a03:e140:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e180::,2a03:e180:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a03:e1c0::,2a03:e1c0:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:e200::,2a03:e200:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:e240::,2a03:e240:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:e280::,2a03:e280:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:e2c0::,2a03:e2c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e340::,2a03:e340:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e380::,2a03:e380:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a03:e3c0::,2a03:e3c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:e400::,2a03:e400:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e440::,2a03:e440:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:e480::,2a03:e480:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e4c0::,2a03:e4c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e500::,2a03:e500:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a03:e540::,2a03:e540:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e580::,2a03:e587:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:e600::,2a03:e600:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:e640::,2a03:e640:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:e680::,2a03:e680:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:e6c0::,2a03:e6c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e700::,2a03:e700:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:e740::,2a03:e740:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:e780::,2a03:e780:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e7c0::,2a03:e7c0:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a03:e800::,2a03:e800:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:e880::,2a03:e880:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:e8c0::,2a03:e8c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:e900::,2a03:e900:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:e940::,2a03:e940:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a03:e980::,2a03:e980:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a03:e9c0::,2a03:e9c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:ea00::,2a03:ea00:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a03:ea40::,2a03:ea40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:ea80::,2a03:ea80:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:eac0::,2a03:eac0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:eb00::,2a03:eb00:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a03:eb40::,2a03:eb40:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:eb80::,2a03:eb80:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a03:ebc0::,2a03:ebc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:ec00::,2a03:ec00:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a03:ec40::,2a03:ec40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:ec80::,2a03:ec80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ecc0::,2a03:ecc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ed00::,2a03:ed00:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:ed40::,2a03:ed40:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:ed80::,2a03:ed80:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:edc0::,2a03:edc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ee00::,2a03:ee00:ffff:ffff:ffff:ffff:ffff:ffff,FO +2a03:ee40::,2a03:ee40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:ee80::,2a03:ee80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:eec0::,2a03:eec0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:ef00::,2a03:ef00:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:ef40::,2a03:ef40:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a03:ef80::,2a03:ef80:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a03:efc0::,2a03:efc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:f000::,2a03:f000:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a03:f040::,2a03:f040:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a03:f080::,2a03:f080:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:f0c0::,2a03:f0c0:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:f100::,2a03:f100:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:f140::,2a03:f140:ffff:ffff:ffff:ffff:ffff:ffff,NC +2a03:f180::,2a03:f180:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a03:f1c0::,2a03:f1c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:f200::,2a03:f200:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:f280::,2a03:f280:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:f2c0::,2a03:f2c0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:f300::,2a03:f300:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a03:f340::,2a03:f340:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a03:f380::,2a03:f380:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:f3c0::,2a03:f3c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:f400::,2a03:f400:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a03:f440::,2a03:f440:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:f480::,2a03:f480:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a03:f4c0::,2a03:f4c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:f500::,2a03:f500:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:f540::,2a03:f540:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:f580::,2a03:f580:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:f5c0::,2a03:f5c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:f600::,2a03:f600:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a03:f640::,2a03:f640:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:f680::,2a03:f680:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a03:f6c0::,2a03:f6c0:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a03:f700::,2a03:f700:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:f740::,2a03:f740:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a03:f780::,2a03:f780:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a03:f7c0::,2a03:f7c0:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:f800::,2a03:f800:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a03:f840::,2a03:f840:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:f880::,2a03:f880:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:f8c0::,2a03:f8c0:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a03:f900::,2a03:f907:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:f940::,2a03:f940:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a03:f980::,2a03:f980:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a03:f9c0::,2a03:f9c0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:fa00::,2a03:fa00:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:fa40::,2a03:fa40:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a03:fa80::,2a03:fa80:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a03:fac0::,2a03:fac0:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a03:fb00::,2a03:fb00:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:fb40::,2a03:fb40:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:fb80::,2a03:fb80:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a03:fbc0::,2a03:fbc0:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:fc00::,2a03:fc07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a03:fc40::,2a03:fc40:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a03:fc80::,2a03:fc80:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:fcc0::,2a03:fcc0:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:fd40::,2a03:fd40:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a03:fdc0::,2a03:fdc0:ffff:ffff:ffff:ffff:ffff:ffff,GL +2a03:fe00::,2a03:fe00:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a03:fe40::,2a03:fe40:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a03:fe80::,2a03:fe80:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a03:ff40::,2a03:ff40:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a03:ffc0::,2a03:ffc0:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a04::,2a04:7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:40::,2a04:47:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:80::,2a04:87:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:c0::,2a04:c7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:100::,2a04:107:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:140::,2a04:147:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:180::,2a04:187:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1c0::,2a04:1c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:200::,2a04:207:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:240::,2a04:247:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:280::,2a04:287:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:2c0::,2a04:2c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:300::,2a04:307:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:340::,2a04:347:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:380::,2a04:387:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:3c0::,2a04:3c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:400::,2a04:407:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:440::,2a04:447:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:480::,2a04:487:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:4c0::,2a04:4c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:500::,2a04:507:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:540::,2a04:547:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:580::,2a04:587:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5c0::,2a04:5c3:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:5e0::,2a04:5e3:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:600::,2a04:607:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:640::,2a04:647:ffff:ffff:ffff:ffff:ffff:ffff,VA +2a04:680::,2a04:687:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:6c0::,2a04:6c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:700::,2a04:707:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:740::,2a04:747:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:780::,2a04:787:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:7c0::,2a04:7c7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:800::,2a04:807:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:840::,2a04:847:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:880::,2a04:887:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:8c0::,2a04:8c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:900::,2a04:907:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a04:940::,2a04:947:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a04:980::,2a04:987:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:9c0::,2a04:9c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:a00::,2a04:a07:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a04:a40::,2a04:a47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:a80::,2a04:a87:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:ac0::,2a04:ac7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:b00::,2a04:b07:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:b40::,2a04:b47:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:b80::,2a04:b87:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:bc0::,2a04:bc7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:c00::,2a04:c07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:c40::,2a04:c47:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:c80::,2a04:c87:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:cc0::,2a04:cc7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:d00::,2a04:d07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:d40::,2a04:d47:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:d80::,2a04:d87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:dc0::,2a04:dc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:e00::,2a04:e07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:e40::,2a04:e47:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:e80::,2a04:e87:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:ec0::,2a04:ec7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:f00::,2a04:f07:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:f40::,2a04:f47:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:f80::,2a04:f87:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:fc0::,2a04:fc7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:1000::,2a04:1007:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1040::,2a04:1047:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:1080::,2a04:1087:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:10c0::,2a04:10c7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:1100::,2a04:1103:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:1120::,2a04:1123:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:1140::,2a04:1143:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1160::,2a04:1161:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:1170::,2a04:1171:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1180::,2a04:1187:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:11c0::,2a04:11c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1200::,2a04:1207:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:1240::,2a04:1247:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:1280::,2a04:1287:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:12c0::,2a04:12c7:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:1300::,2a04:1307:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1340::,2a04:1347:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:1380::,2a04:1387:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:13c0::,2a04:13c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1400::,2a04:1407:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1440::,2a04:1447:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:1480::,2a04:1487:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a04:14c0::,2a04:14c7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:1500::,2a04:1507:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1540::,2a04:1547:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:1580::,2a04:1587:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:15c0::,2a04:15c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1600::,2a04:1607:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:1640::,2a04:1647:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1680::,2a04:1687:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:16c0::,2a04:16c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:1700::,2a04:1707:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1740::,2a04:1747:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:1780::,2a04:1787:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:17c0::,2a04:17c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:1800::,2a04:1807:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:1840::,2a04:1847:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1880::,2a04:1887:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:18c0::,2a04:18c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:1900::,2a04:1907:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:1940::,2a04:1947:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1980::,2a04:1987:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:19c0::,2a04:19c7:ffff:ffff:ffff:ffff:ffff:ffff,PS +2a04:1a00::,2a04:1a07:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:1a40::,2a04:1a47:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:1a80::,2a04:1a87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1ac0::,2a04:1ac7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:1b00::,2a04:1b07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:1b40::,2a04:1b47:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:1b80::,2a04:1b87:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:1bc0::,2a04:1bc7:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:1c00::,2a04:1c07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1c40::,2a04:1c47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:1c80::,2a04:1c87:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:1cc0::,2a04:1cc7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:1d00::,2a04:1d07:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:1d40::,2a04:1d47:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:1d80::,2a04:1d87:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:1dc0::,2a04:1dc7:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a04:1e00::,2a04:1e07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1e40::,2a04:1e47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:1e80::,2a04:1e87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:1ec0::,2a04:1ec7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:1f00::,2a04:1f03:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:1f20::,2a04:1f23:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:1f40::,2a04:1f47:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:1f80::,2a04:1f87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:1fc0::,2a04:1fc7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:2000::,2a04:2007:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:2040::,2a04:2047:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:2080::,2a04:2087:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:20c0::,2a04:20c7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:2100::,2a04:2107:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:2140::,2a04:2147:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2180::,2a04:2187:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a04:21c0::,2a04:21c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2200::,2a04:2207:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:2240::,2a04:2247:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a04:2280::,2a04:2287:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:22c0::,2a04:22c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:2300::,2a04:2307:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:2340::,2a04:2347:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2380::,2a04:2387:ffff:ffff:ffff:ffff:ffff:ffff,HU +2a04:2400::,2a04:241f:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:2500::,2a04:2507:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:2540::,2a04:2547:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:2580::,2a04:2587:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:25c0::,2a04:25c7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:2600::,2a04:2607:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a04:2640::,2a04:2647:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:2680::,2a04:2687:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:26c0::,2a04:26c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:2700::,2a04:2707:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:2740::,2a04:2747:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:2780::,2a04:2787:ffff:ffff:ffff:ffff:ffff:ffff,TJ +2a04:27c0::,2a04:27c7:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a04:2800::,2a04:2807:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:2840::,2a04:2847:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2880::,2a04:2883:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:28a0::,2a04:28a0:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a04:28b0::,2a04:28b1:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:28c0::,2a04:28c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:2900::,2a04:2907:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2940::,2a04:2947:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:2980::,2a04:2987:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a04:29c0::,2a04:29c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:2a00::,2a04:2a07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2a40::,2a04:2a47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:2a80::,2a04:2a87:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:2ac0::,2a04:2ac7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2b00::,2a04:2b07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2b40::,2a04:2b47:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:2b80::,2a04:2b87:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:2bc0::,2a04:2bc7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:2c00::,2a04:2c07:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:2c80::,2a04:2c87:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:2cc0::,2a04:2cc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:2d00::,2a04:2d07:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a04:2d40::,2a04:2d47:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:2d80::,2a04:2d87:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:2dc0::,2a04:2dc7:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:2e00::,2a04:2e07:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:2e40::,2a04:2e47:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a04:2e80::,2a04:2e87:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a04:2ec0::,2a04:2ec7:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a04:2f00::,2a04:2f07:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:2f40::,2a04:2f47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:2f80::,2a04:2f87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:2fc0::,2a04:2fc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:3000::,2a04:3007:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:3040::,2a04:3047:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a04:3080::,2a04:3087:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a04:30c0::,2a04:30c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:3100::,2a04:3107:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:3140::,2a04:3147:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:3180::,2a04:3187:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:31c0::,2a04:31c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:3200::,2a04:3207:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:3240::,2a04:3247:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:3280::,2a04:3287:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:32c0::,2a04:32c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:3300::,2a04:3307:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:3340::,2a04:3347:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a04:3380::,2a04:3387:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:33c0::,2a04:33c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:3400::,2a04:3407:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:3440::,2a04:3447:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:3480::,2a04:3487:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:34c0::,2a04:34c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:3500::,2a04:3507:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:3540::,2a04:3547:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:3580::,2a04:3587:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:35c0::,2a04:35c7:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:3600::,2a04:3607:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:3640::,2a04:3647:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:3680::,2a04:3687:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:36c0::,2a04:36c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:3700::,2a04:3707:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:3740::,2a04:3747:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:3780::,2a04:3787:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:3800::,2a04:3807:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:3840::,2a04:3847:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:3880::,2a04:3883:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:38a0::,2a04:38a3:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:38c0::,2a04:38c7:ffff:ffff:ffff:ffff:ffff:ffff,JE +2a04:3900::,2a04:3907:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:3940::,2a04:3947:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:3980::,2a04:3987:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:39c0::,2a04:39c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:3a00::,2a04:3a07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:3a40::,2a04:3a40:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:3a50::,2a04:3a51:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:3a60::,2a04:3a63:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:3a80::,2a04:3a87:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a04:3ac0::,2a04:3ac7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:3b00::,2a04:3b07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:3b40::,2a04:3b47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:3b80::,2a04:3b87:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:3bc0::,2a04:3bc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:3c00::,2a04:3c07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:3c40::,2a04:3c47:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:3c80::,2a04:3c87:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:3cc0::,2a04:3cc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:3d00::,2a04:3d07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:3d40::,2a04:3d47:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:3d80::,2a04:3d87:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:3dc0::,2a04:3dc7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:3e00::,2a04:3e07:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a04:3e40::,2a04:3e47:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:3e80::,2a04:3e87:ffff:ffff:ffff:ffff:ffff:ffff,BA +2a04:3ec0::,2a04:3ec7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:3f00::,2a04:3f07:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:3f40::,2a04:3f47:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:3f80::,2a04:3f87:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:3fc0::,2a04:3fc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4000::,2a04:4007:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:4040::,2a04:4047:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4080::,2a04:4087:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:40c0::,2a04:40c7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:4100::,2a04:4107:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4140::,2a04:4147:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:4180::,2a04:4187:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:41c0::,2a04:41c7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:4200::,2a04:4207:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:4240::,2a04:4247:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:4280::,2a04:4287:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:42c0::,2a04:42c7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:4300::,2a04:4307:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4340::,2a04:4347:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:4380::,2a04:4387:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:43c0::,2a04:43c7:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a04:4400::,2a04:4407:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:4440::,2a04:4447:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4480::,2a04:4487:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:44c0::,2a04:44c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:4500::,2a04:4507:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:4540::,2a04:4547:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:4580::,2a04:4587:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:45c0::,2a04:45c7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:4600::,2a04:4607:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4640::,2a04:4647:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:4680::,2a04:4687:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:46c0::,2a04:46c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:4700::,2a04:4703:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:4720::,2a04:4723:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:4740::,2a04:4747:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:4780::,2a04:4787:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a04:47c0::,2a04:47c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4800::,2a04:4807:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:4840::,2a04:4847:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:4880::,2a04:4887:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:48c0::,2a04:48c7:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a04:4900::,2a04:4907:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:4940::,2a04:4947:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:4980::,2a04:4987:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:49c0::,2a04:49c7:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a04:4a00::,2a04:4a07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:4a40::,2a04:4a47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4a80::,2a04:4a87:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:4b00::,2a04:4b07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:4b40::,2a04:4b47:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:4b80::,2a04:4b87:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a04:4bc0::,2a04:4bc7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:4c00::,2a04:4c07:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:4c40::,2a04:4c47:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:4c80::,2a04:4c87:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:4cc0::,2a04:4cc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:4d00::,2a04:4d07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:4d40::,2a04:4d47:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:4d80::,2a04:4d87:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:4dc0::,2a04:4dc7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:4e00::,2a04:4e07:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a04:4e80::,2a04:4e87:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:4ec0::,2a04:4ec7:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:4f00::,2a04:4f07:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:4f40::,2a04:4f47:ffff:ffff:ffff:ffff:ffff:ffff,KZ +2a04:4f80::,2a04:4f87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:4fc0::,2a04:4fc3:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:4fe0::,2a04:4fe3:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5200::,2a04:5207:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:5240::,2a04:5247:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:5280::,2a04:5287:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:52c0::,2a04:52c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:5300::,2a04:5307:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:5340::,2a04:5347:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5380::,2a04:5387:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:53c0::,2a04:53c7:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a04:5400::,2a04:5407:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:5440::,2a04:5447:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:5480::,2a04:5487:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:54c0::,2a04:54c7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:5500::,2a04:5507:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:5540::,2a04:5547:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:5580::,2a04:5587:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:55c0::,2a04:55c7:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a04:5600::,2a04:5607:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a04:5640::,2a04:5647:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:5680::,2a04:5687:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:56c0::,2a04:56c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:5700::,2a04:5707:ffff:ffff:ffff:ffff:ffff:ffff,LI +2a04:5740::,2a04:5747:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5780::,2a04:5787:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:57c0::,2a04:57c7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:5800::,2a04:5807:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:5880::,2a04:5887:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:58c0::,2a04:58c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:5900::,2a04:5907:ffff:ffff:ffff:ffff:ffff:ffff,AL +2a04:5940::,2a04:5947:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:5980::,2a04:5987:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:59c0::,2a04:59c7:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a04:5a00::,2a04:5a07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5a40::,2a04:5a47:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:5a80::,2a04:5a87:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a04:5ac0::,2a04:5ac7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:5b00::,2a04:5b07:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:5b40::,2a04:5b47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5b80::,2a04:5b87:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:5bc0::,2a04:5bc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:5c00::,2a04:5c07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:5c40::,2a04:5c47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:5c80::,2a04:5c87:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:5cc0::,2a04:5cc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5d00::,2a04:5d07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:5d40::,2a04:5d47:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:5d80::,2a04:5d87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5dc0::,2a04:5dc7:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:5e00::,2a04:5e07:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:5e40::,2a04:5e47:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a04:5e80::,2a04:5e87:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:5ec0::,2a04:5ec7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:5f00::,2a04:5f07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:5f40::,2a04:5f47:ffff:ffff:ffff:ffff:ffff:ffff,LV +2a04:5f80::,2a04:5f87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:6000::,2a04:6007:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:6040::,2a04:6047:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:6080::,2a04:6087:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:60c0::,2a04:60c7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:6100::,2a04:6107:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:6180::,2a04:6187:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:6200::,2a04:6207:ffff:ffff:ffff:ffff:ffff:ffff,JO +2a04:6240::,2a04:6247:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:6280::,2a04:6287:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:62c0::,2a04:62c7:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:6300::,2a04:6307:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:6340::,2a04:6347:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:6380::,2a04:6387:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:63c0::,2a04:63c7:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a04:6400::,2a04:6407:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:6440::,2a04:6447:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:6480::,2a04:6487:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:64c0::,2a04:64c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:6500::,2a04:6507:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a04:6540::,2a04:6547:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:6580::,2a04:6587:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:65c0::,2a04:65c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:6600::,2a04:6607:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:6640::,2a04:6647:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:6650::,2a04:6651:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:6680::,2a04:6687:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:66c0::,2a04:66c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:6700::,2a04:6707:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a04:6740::,2a04:6747:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:6780::,2a04:6787:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:67c0::,2a04:67c7:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:6800::,2a04:6807:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:6840::,2a04:6847:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:6880::,2a04:6887:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:68c0::,2a04:68c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:6900::,2a04:6907:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:6940::,2a04:6947:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:6980::,2a04:6987:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:69c0::,2a04:69c7:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a04:6a00::,2a04:6a07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:6a40::,2a04:6a47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:6a80::,2a04:6a87:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:6ac0::,2a04:6ac7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:6b00::,2a04:6b07:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:6b40::,2a04:6b47:ffff:ffff:ffff:ffff:ffff:ffff,GG +2a04:6b80::,2a04:6b87:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:6bc0::,2a04:6bc7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:6c00::,2a04:6c07:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:6c40::,2a04:6c47:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:6c80::,2a04:6c87:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:6cc0::,2a04:6cc7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:6d00::,2a04:6d07:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:6d40::,2a04:6d47:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:6d80::,2a04:6d87:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a04:6dc0::,2a04:6dc7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:6e00::,2a04:6e07:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:6e40::,2a04:6e47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:6e80::,2a04:6e87:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:6ec0::,2a04:6ec7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:6f00::,2a04:6f07:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:6f40::,2a04:6f47:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:6f80::,2a04:6f83:ffff:ffff:ffff:ffff:ffff:ffff,QA +2a04:6fa0::,2a04:6fa1:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:6fb0::,2a04:6fb1:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:6fc0::,2a04:6fc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:7000::,2a04:7007:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a04:7040::,2a04:7047:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:7080::,2a04:7087:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a04:70c0::,2a04:70c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:7100::,2a04:7107:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:7140::,2a04:7147:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:7180::,2a04:7187:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:71c0::,2a04:71c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:7200::,2a04:7207:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:7240::,2a04:7247:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:7280::,2a04:7287:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:72c0::,2a04:72c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:7300::,2a04:7307:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:7340::,2a04:7347:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:7380::,2a04:7387:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:73c0::,2a04:73c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:7400::,2a04:7407:ffff:ffff:ffff:ffff:ffff:ffff,ME +2a04:7440::,2a04:7447:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:7480::,2a04:7487:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:74c0::,2a04:74c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:7500::,2a04:7507:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:7540::,2a04:7547:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:7580::,2a04:7587:ffff:ffff:ffff:ffff:ffff:ffff,MD +2a04:75c0::,2a04:75c7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:7600::,2a04:7607:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:7640::,2a04:7647:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:7680::,2a04:7687:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:76c0::,2a04:76c7:ffff:ffff:ffff:ffff:ffff:ffff,US +2a04:7700::,2a04:7707:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:7740::,2a04:7747:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:7780::,2a04:7787:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:77c0::,2a04:77c7:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:7800::,2a04:7807:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:7840::,2a04:7847:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:7880::,2a04:7887:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:78c0::,2a04:78c3:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:78e0::,2a04:78e3:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:7900::,2a04:7907:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:7940::,2a04:7947:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:7980::,2a04:7987:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:79c0::,2a04:79c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:7a00::,2a04:7a07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:7a40::,2a04:7a47:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:7a80::,2a04:7a87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:7ac0::,2a04:7ac7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:7b40::,2a04:7b47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:7b80::,2a04:7b87:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:7bc0::,2a04:7bc7:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a04:7c00::,2a04:7c07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:7c40::,2a04:7c47:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:7c80::,2a04:7c87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:7cc0::,2a04:7cc7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:7d00::,2a04:7d07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:7d40::,2a04:7d47:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:7d80::,2a04:7d87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:7dc0::,2a04:7dc7:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:7e00::,2a04:7e07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:7e40::,2a04:7e47:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:7e80::,2a04:7e87:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a04:7ec0::,2a04:7ec7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:7f00::,2a04:7f07:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:7f40::,2a04:7f47:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:7f80::,2a04:7f87:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:7fc0::,2a04:7fc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:8000::,2a04:8007:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:8040::,2a04:8047:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:8080::,2a04:8087:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:80c0::,2a04:80c7:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a04:8100::,2a04:8107:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:8140::,2a04:8147:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:8180::,2a04:8181:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a04:8190::,2a04:8191:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:81a0::,2a04:81a3:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:81c0::,2a04:81c7:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a04:8200::,2a04:8207:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:8240::,2a04:8247:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8280::,2a04:8287:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:82c0::,2a04:82c7:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:8300::,2a04:8307:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a04:8340::,2a04:8347:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:8380::,2a04:8387:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a04:83c0::,2a04:83c7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:8400::,2a04:8407:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:8440::,2a04:8447:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:8480::,2a04:8487:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:84c0::,2a04:84c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:8500::,2a04:8507:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:8540::,2a04:8547:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:8580::,2a04:8587:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:85c0::,2a04:85c7:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:8600::,2a04:8607:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:8640::,2a04:8647:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:8680::,2a04:8687:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:86c0::,2a04:86c7:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a04:8700::,2a04:8707:ffff:ffff:ffff:ffff:ffff:ffff,MT +2a04:8740::,2a04:8747:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:8780::,2a04:8787:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:87c0::,2a04:87c7:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:8800::,2a04:8807:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:8840::,2a04:8847:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:8880::,2a04:8887:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:88c0::,2a04:88c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8900::,2a04:8907:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:8940::,2a04:8947:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a04:8980::,2a04:8987:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:89c0::,2a04:89c7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:8a00::,2a04:8a07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8a40::,2a04:8a47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8a80::,2a04:8a87:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a04:8ac0::,2a04:8ac7:ffff:ffff:ffff:ffff:ffff:ffff,BH +2a04:8b00::,2a04:8b07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:8b40::,2a04:8b47:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:8b80::,2a04:8b87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:8bc0::,2a04:8bc7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:8c00::,2a04:8c07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8c40::,2a04:8c47:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8c80::,2a04:8c87:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a04:8cc0::,2a04:8cc7:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:8d00::,2a04:8d07:ffff:ffff:ffff:ffff:ffff:ffff,MK +2a04:8d40::,2a04:8d47:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:8d80::,2a04:8d87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:8dc0::,2a04:8dc7:ffff:ffff:ffff:ffff:ffff:ffff,LU +2a04:8e00::,2a04:8e07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:8e40::,2a04:8e47:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:8e80::,2a04:8e81:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:8e90::,2a04:8e91:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:8ea0::,2a04:8ea3:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8f00::,2a04:8f07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:8f40::,2a04:8f47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:8f80::,2a04:8f87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:8fc0::,2a04:8fc7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:9000::,2a04:9007:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:9040::,2a04:9047:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:9080::,2a04:9087:ffff:ffff:ffff:ffff:ffff:ffff,SY +2a04:90c0::,2a04:90c7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:9100::,2a04:9107:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:9140::,2a04:9147:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:9180::,2a04:9187:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:91c0::,2a04:91c7:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:9240::,2a04:9247:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:9280::,2a04:9287:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:92c0::,2a04:92c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9300::,2a04:9307:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:9340::,2a04:9347:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9380::,2a04:9387:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:93c0::,2a04:93c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:9400::,2a04:9407:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:9440::,2a04:9447:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:9480::,2a04:9487:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:94e0::,2a04:94e3:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9500::,2a04:9507:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:9540::,2a04:9547:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:9580::,2a04:9587:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:95c0::,2a04:95c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9600::,2a04:9607:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9640::,2a04:9647:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:9680::,2a04:9687:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:96c0::,2a04:96c7:ffff:ffff:ffff:ffff:ffff:ffff,CY +2a04:9700::,2a04:9707:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9740::,2a04:9747:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:9780::,2a04:9787:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:97c0::,2a04:97c7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:9800::,2a04:9807:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:9840::,2a04:9847:ffff:ffff:ffff:ffff:ffff:ffff,IS +2a04:9880::,2a04:9887:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:98c0::,2a04:98c7:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:9900::,2a04:9907:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:9940::,2a04:9947:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a04:9980::,2a04:9987:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:99c0::,2a04:99c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:9a00::,2a04:9a07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:9a40::,2a04:9a47:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:9a80::,2a04:9a87:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:9ac0::,2a04:9ac7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:9b00::,2a04:9b07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9b40::,2a04:9b47:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a04:9b80::,2a04:9b87:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:9bc0::,2a04:9bc7:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:9c00::,2a04:9c07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:9c40::,2a04:9c47:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:9c80::,2a04:9c87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9cc0::,2a04:9cc7:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a04:9d00::,2a04:9d07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:9d40::,2a04:9d47:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:9d80::,2a04:9d87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:9dc0::,2a04:9dc7:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:9e00::,2a04:9e07:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:9e40::,2a04:9e47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:9e80::,2a04:9e87:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:9ec0::,2a04:9ec7:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:9f00::,2a04:9f07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:9f40::,2a04:9f47:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:9f80::,2a04:9f87:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:a000::,2a04:a007:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:a040::,2a04:a047:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:a080::,2a04:a087:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:a0c0::,2a04:a0c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:a100::,2a04:a107:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:a140::,2a04:a147:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:a180::,2a04:a187:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:a1c0::,2a04:a1c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:a200::,2a04:a207:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:a240::,2a04:a247:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:a280::,2a04:a287:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:a2c0::,2a04:a2c7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:a300::,2a04:a307:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:a340::,2a04:a347:ffff:ffff:ffff:ffff:ffff:ffff,SM +2a04:a380::,2a04:a387:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:a3c0::,2a04:a3c7:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:a400::,2a04:a407:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:a440::,2a04:a440:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:a450::,2a04:a451:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:a460::,2a04:a461:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:a470::,2a04:a471:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:a480::,2a04:a487:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:a4c0::,2a04:a4c7:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:a500::,2a04:a507:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:a540::,2a04:a547:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:a580::,2a04:a587:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:a5c0::,2a04:a5c7:ffff:ffff:ffff:ffff:ffff:ffff,GR +2a04:a600::,2a04:a607:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:a640::,2a04:a647:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:a680::,2a04:a687:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:a6c0::,2a04:a6c7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:a700::,2a04:a707:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:a740::,2a04:a747:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:a780::,2a04:a787:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:a7c0::,2a04:a7c7:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a04:a800::,2a04:a807:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:a840::,2a04:a847:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:a880::,2a04:a887:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:a8c0::,2a04:a8c7:ffff:ffff:ffff:ffff:ffff:ffff,US +2a04:a900::,2a04:a907:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:a940::,2a04:a947:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:a980::,2a04:a987:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:a9c0::,2a04:a9c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:aa00::,2a04:aa07:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:aa40::,2a04:aa47:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:aa80::,2a04:aa87:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a04:aac0::,2a04:aac7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:ab00::,2a04:ab07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:ab40::,2a04:ab47:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:ab80::,2a04:ab87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:abc0::,2a04:abc7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:ac00::,2a04:ac07:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:ac40::,2a04:ac47:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:ac80::,2a04:ac87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:acc0::,2a04:acc7:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:ad00::,2a04:ad07:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:ad40::,2a04:ad47:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:ad80::,2a04:ad87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:adc0::,2a04:adc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:ae00::,2a04:ae3f:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:b000::,2a04:b007:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b040::,2a04:b047:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:b080::,2a04:b087:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:b0c0::,2a04:b0c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:b100::,2a04:b107:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:b140::,2a04:b147:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:b180::,2a04:b187:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:b1c0::,2a04:b1c7:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:b200::,2a04:b207:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:b240::,2a04:b247:ffff:ffff:ffff:ffff:ffff:ffff,IM +2a04:b280::,2a04:b287:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:b2c0::,2a04:b2c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b300::,2a04:b307:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:b340::,2a04:b347:ffff:ffff:ffff:ffff:ffff:ffff,KG +2a04:b380::,2a04:b387:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:b3c0::,2a04:b3c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b400::,2a04:b407:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:b440::,2a04:b447:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b480::,2a04:b487:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:b4c0::,2a04:b4c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:b500::,2a04:b507:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:b540::,2a04:b547:ffff:ffff:ffff:ffff:ffff:ffff,SK +2a04:b580::,2a04:b587:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:b5c0::,2a04:b5c7:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:b600::,2a04:b607:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:b640::,2a04:b647:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:b680::,2a04:b687:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b6c0::,2a04:b6c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b700::,2a04:b707:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:b740::,2a04:b747:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:b780::,2a04:b787:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b7c0::,2a04:b7c7:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a04:b800::,2a04:b807:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:b840::,2a04:b847:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:b880::,2a04:b887:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:b8c0::,2a04:b8c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:b900::,2a04:b907:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:b940::,2a04:b947:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:b980::,2a04:b987:ffff:ffff:ffff:ffff:ffff:ffff,HR +2a04:b9c0::,2a04:b9c7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:ba00::,2a04:ba07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:ba40::,2a04:ba47:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:ba80::,2a04:ba87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:bac0::,2a04:bac7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:bb00::,2a04:bb07:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:bb40::,2a04:bb47:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:bb80::,2a04:bb87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:bbc0::,2a04:bbc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:bc00::,2a04:bc07:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:bc40::,2a04:bc47:ffff:ffff:ffff:ffff:ffff:ffff,UA +2a04:bc80::,2a04:bc87:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:bcc0::,2a04:bcc7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:bd00::,2a04:bd07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:bd40::,2a04:bd47:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:bd80::,2a04:bd87:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:bdc0::,2a04:bdc7:ffff:ffff:ffff:ffff:ffff:ffff,BE +2a04:be00::,2a04:be03:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:be20::,2a04:be23:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:be40::,2a04:be47:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:be80::,2a04:be87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:bec0::,2a04:bec7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:bf00::,2a04:bf07:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:bf40::,2a04:bf47:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:bf80::,2a04:bf87:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:bfc0::,2a04:bfc7:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:c000::,2a04:c007:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:c040::,2a04:c047:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:c080::,2a04:c087:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:c0c0::,2a04:c0c7:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:c100::,2a04:c107:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:c140::,2a04:c147:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:c180::,2a04:c187:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a04:c1c0::,2a04:c1c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:c200::,2a04:c207:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a04:c240::,2a04:c247:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:c280::,2a04:c287:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:c2c0::,2a04:c2c7:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a04:c300::,2a04:c307:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:c340::,2a04:c347:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:c380::,2a04:c387:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:c3c0::,2a04:c3c7:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:c400::,2a04:c407:ffff:ffff:ffff:ffff:ffff:ffff,OM +2a04:c440::,2a04:c447:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:c480::,2a04:c487:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:c4c0::,2a04:c4c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:c500::,2a04:c507:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:c540::,2a04:c547:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:c580::,2a04:c587:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:c5c0::,2a04:c5c7:ffff:ffff:ffff:ffff:ffff:ffff,US +2a04:c600::,2a04:c607:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:c640::,2a04:c647:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:c680::,2a04:c687:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:c6c0::,2a04:c6c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:c740::,2a04:c747:ffff:ffff:ffff:ffff:ffff:ffff,CZ +2a04:c780::,2a04:c787:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:c800::,2a04:c807:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:c840::,2a04:c847:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a04:c880::,2a04:c887:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:c8c0::,2a04:c8c7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:c900::,2a04:c907:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:c940::,2a04:c947:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:c980::,2a04:c987:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:c9c0::,2a04:c9c7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:ca00::,2a04:ca07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:ca40::,2a04:ca47:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:ca80::,2a04:ca87:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:cac0::,2a04:cac7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:cb00::,2a04:cb07:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:cb40::,2a04:cb47:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:cb80::,2a04:cb87:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a04:cbc0::,2a04:cbc7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:cc00::,2a04:cc07:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:cc40::,2a04:cc47:ffff:ffff:ffff:ffff:ffff:ffff,BY +2a04:cc80::,2a04:cc87:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:ccc0::,2a04:ccc7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:cd00::,2a04:cd07:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:cd40::,2a04:cd47:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:cd80::,2a04:cd87:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:cdc0::,2a04:cdc7:ffff:ffff:ffff:ffff:ffff:ffff,PL +2a04:ce00::,2a04:ce07:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a04:ce40::,2a04:ce47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:ce80::,2a04:ce87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:cec0::,2a04:cec7:ffff:ffff:ffff:ffff:ffff:ffff,FR +2a04:cf00::,2a04:cf07:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:cf40::,2a04:cf47:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:cf80::,2a04:cf87:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a04:cfc0::,2a04:cfc7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:d000::,2a04:d007:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:d040::,2a04:d047:ffff:ffff:ffff:ffff:ffff:ffff,GE +2a04:d080::,2a04:d087:ffff:ffff:ffff:ffff:ffff:ffff,RS +2a04:d0c0::,2a04:d0c7:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:d100::,2a04:d107:ffff:ffff:ffff:ffff:ffff:ffff,IQ +2a04:d140::,2a04:d147:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:d180::,2a04:d187:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:d1c0::,2a04:d1c7:ffff:ffff:ffff:ffff:ffff:ffff,LB +2a04:d200::,2a04:d207:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:d240::,2a04:d247:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:d280::,2a04:d287:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:d2c0::,2a04:d2c7:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:d300::,2a04:d307:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:d340::,2a04:d347:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:d380::,2a04:d387:ffff:ffff:ffff:ffff:ffff:ffff,AZ +2a04:d3c0::,2a04:d3c7:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:d400::,2a04:d407:ffff:ffff:ffff:ffff:ffff:ffff,EE +2a04:d440::,2a04:d447:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:d480::,2a04:d487:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:d4c0::,2a04:d4c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:d500::,2a04:d507:ffff:ffff:ffff:ffff:ffff:ffff,FI +2a04:d540::,2a04:d547:ffff:ffff:ffff:ffff:ffff:ffff,AT +2a04:d580::,2a04:d587:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:d5c0::,2a04:d5c7:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:d600::,2a04:d607:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:d640::,2a04:d647:ffff:ffff:ffff:ffff:ffff:ffff,IE +2a04:d680::,2a04:d687:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:d6c0::,2a04:d6c7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:d700::,2a04:d707:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:d740::,2a04:d747:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:d780::,2a04:d787:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:d7c0::,2a04:d7c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:d800::,2a04:d807:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:d840::,2a04:d847:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:d880::,2a04:d887:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:d8c0::,2a04:d8c7:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:d900::,2a04:d907:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:d940::,2a04:d947:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:d980::,2a04:d987:ffff:ffff:ffff:ffff:ffff:ffff,IL +2a04:d9c0::,2a04:d9c7:ffff:ffff:ffff:ffff:ffff:ffff,RO +2a04:da00::,2a04:da07:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a04:da40::,2a04:da47:ffff:ffff:ffff:ffff:ffff:ffff,IR +2a04:da80::,2a04:da87:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:dac0::,2a04:dac7:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:db00::,2a04:db07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:db40::,2a04:db47:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a04:db80::,2a04:db87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:dbc0::,2a04:dbc3:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:dc00::,2a04:dc07:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:dc40::,2a04:dc47:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:dc80::,2a04:dc87:ffff:ffff:ffff:ffff:ffff:ffff,NO +2a04:dcc0::,2a04:dcc7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:dd00::,2a04:dd07:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a04:dd40::,2a04:dd47:ffff:ffff:ffff:ffff:ffff:ffff,SI +2a04:dd80::,2a04:dd87:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:ddc0::,2a04:ddc7:ffff:ffff:ffff:ffff:ffff:ffff,SE +2a04:de00::,2a04:de07:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:de40::,2a04:de47:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:de80::,2a04:de87:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:dec0::,2a04:dec7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:df00::,2a04:df07:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a04:df40::,2a04:df47:ffff:ffff:ffff:ffff:ffff:ffff,LT +2a04:df80::,2a04:df87:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:dfc0::,2a04:dfc7:ffff:ffff:ffff:ffff:ffff:ffff,DE +2a04:e040::,2a04:e047:ffff:ffff:ffff:ffff:ffff:ffff,PT +2a04:e080::,2a04:e087:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:e0c0::,2a04:e0c7:ffff:ffff:ffff:ffff:ffff:ffff,SA +2a04:e100::,2a04:e107:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:e140::,2a04:e147:ffff:ffff:ffff:ffff:ffff:ffff,GB +2a04:e180::,2a04:e187:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:e1c0::,2a04:e1c7:ffff:ffff:ffff:ffff:ffff:ffff,NL +2a04:e200::,2a04:e207:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:e240::,2a04:e247:ffff:ffff:ffff:ffff:ffff:ffff,IT +2a04:e280::,2a04:e287:ffff:ffff:ffff:ffff:ffff:ffff,TR +2a04:e2c0::,2a04:e2c7:ffff:ffff:ffff:ffff:ffff:ffff,ES +2a04:e300::,2a04:e307:ffff:ffff:ffff:ffff:ffff:ffff,CH +2a04:e340::,2a04:e347:ffff:ffff:ffff:ffff:ffff:ffff,AE +2a04:e380::,2a04:e387:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:e3c0::,2a04:e3c7:ffff:ffff:ffff:ffff:ffff:ffff,DK +2a04:e400::,2a04:e407:ffff:ffff:ffff:ffff:ffff:ffff,BG +2a04:e440::,2a04:e447:ffff:ffff:ffff:ffff:ffff:ffff,RU +2a04:e480::,2a04:e487:ffff:ffff:ffff:ffff:ffff:ffff,IT +2c0e::,2c0e:fff:ffff:ffff:ffff:ffff:ffff:ffff,EG +2c0e:2000::,2c0e:200f:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f600::,2c0f:f600:ffff:ffff:ffff:ffff:ffff:ffff,GN +2c0f:f608::,2c0f:f608:ffff:ffff:ffff:ffff:ffff:ffff,RE +2c0f:f610::,2c0f:f610:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f618::,2c0f:f618:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:f620::,2c0f:f620:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:f628::,2c0f:f628:ffff:ffff:ffff:ffff:ffff:ffff,RW +2c0f:f630::,2c0f:f630:ffff:ffff:ffff:ffff:ffff:ffff,BJ +2c0f:f638::,2c0f:f638:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:f640::,2c0f:f640:ffff:ffff:ffff:ffff:ffff:ffff,GA +2c0f:f648::,2c0f:f648:ffff:ffff:ffff:ffff:ffff:ffff,TD +2c0f:f650::,2c0f:f650:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f658::,2c0f:f658:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:f660::,2c0f:f660:ffff:ffff:ffff:ffff:ffff:ffff,CM +2c0f:f668::,2c0f:f668:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f670::,2c0f:f670:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:f678::,2c0f:f678:ffff:ffff:ffff:ffff:ffff:ffff,BW +2c0f:f680::,2c0f:f680:ffff:ffff:ffff:ffff:ffff:ffff,SC +2c0f:f688::,2c0f:f688:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:f690::,2c0f:f690:ffff:ffff:ffff:ffff:ffff:ffff,SS +2c0f:f698::,2c0f:f698:ffff:ffff:ffff:ffff:ffff:ffff,TN +2c0f:f6a0::,2c0f:f6a0:ffff:ffff:ffff:ffff:ffff:ffff,CM +2c0f:f6a8::,2c0f:f6a8:ffff:ffff:ffff:ffff:ffff:ffff,BI +2c0f:f6b0::,2c0f:f6b0:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:f6b8::,2c0f:f6b8:ffff:ffff:ffff:ffff:ffff:ffff,SO +2c0f:f6c0::,2c0f:f6c0:ffff:ffff:ffff:ffff:ffff:ffff,CG +2c0f:f6c8::,2c0f:f6c8:ffff:ffff:ffff:ffff:ffff:ffff,CM +2c0f:f6d0::,2c0f:f6d0:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:f6d8::,2c0f:f6d8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f6e0::,2c0f:f6e0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f6e8::,2c0f:f6e8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f6f0::,2c0f:f6f0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f6f8::,2c0f:f6f8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f700::,2c0f:f700:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f708::,2c0f:f708:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f800::,2c0f:f80f:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f810::,2c0f:f810:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:f818::,2c0f:f818:ffff:ffff:ffff:ffff:ffff:ffff,BJ +2c0f:f820::,2c0f:f820:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:f828::,2c0f:f828:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:f830::,2c0f:f830:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2c0f:f838::,2c0f:f838:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f840::,2c0f:f840:ffff:ffff:ffff:ffff:ffff:ffff,GQ +2c0f:f848::,2c0f:f848:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:f850::,2c0f:f850:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f858::,2c0f:f858:ffff:ffff:ffff:ffff:ffff:ffff,DZ +2c0f:f860::,2c0f:f860:ffff:ffff:ffff:ffff:ffff:ffff,RW +2c0f:f870::,2c0f:f870:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:f878::,2c0f:f878:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:f880::,2c0f:f880:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:f888::,2c0f:f888:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:f890::,2c0f:f890:ffff:ffff:ffff:ffff:ffff:ffff,GM +2c0f:f898::,2c0f:f898:ffff:ffff:ffff:ffff:ffff:ffff,MU +2c0f:f8a0::,2c0f:f8a0:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:f8a8::,2c0f:f8a8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f8b0::,2c0f:f8b0:ffff:ffff:ffff:ffff:ffff:ffff,BF +2c0f:f8b8::,2c0f:f8b8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f8c0::,2c0f:f8c0:ffff:ffff:ffff:ffff:ffff:ffff,GQ +2c0f:f8c8::,2c0f:f8c8:ffff:ffff:ffff:ffff:ffff:ffff,NE +2c0f:f8d0::,2c0f:f8d0:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:f8d8::,2c0f:f8d8:ffff:ffff:ffff:ffff:ffff:ffff,BW +2c0f:f8e0::,2c0f:f8e0:ffff:ffff:ffff:ffff:ffff:ffff,MU +2c0f:f8e8::,2c0f:f8e8:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:f8f0::,2c0f:f8f0:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2c0f:f8f8::,2c0f:f8f8:ffff:ffff:ffff:ffff:ffff:ffff,SO +2c0f:f900::,2c0f:f900:ffff:ffff:ffff:ffff:ffff:ffff,ML +2c0f:f908::,2c0f:f908:ffff:ffff:ffff:ffff:ffff:ffff,BI +2c0f:f918::,2c0f:f918:ffff:ffff:ffff:ffff:ffff:ffff,RE +2c0f:f920::,2c0f:f920:ffff:ffff:ffff:ffff:ffff:ffff,CG +2c0f:f928::,2c0f:f928:ffff:ffff:ffff:ffff:ffff:ffff,GW +2c0f:f930::,2c0f:f930:ffff:ffff:ffff:ffff:ffff:ffff,LR +2c0f:f938::,2c0f:f938:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:f940::,2c0f:f940:ffff:ffff:ffff:ffff:ffff:ffff,DZ +2c0f:f948::,2c0f:f948:ffff:ffff:ffff:ffff:ffff:ffff,GA +2c0f:f950::,2c0f:f950:ffff:ffff:ffff:ffff:ffff:ffff,SS +2c0f:f958::,2c0f:f958:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f960::,2c0f:f960:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:f968::,2c0f:f968:ffff:ffff:ffff:ffff:ffff:ffff,MZ +2c0f:f970::,2c0f:f970:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f978::,2c0f:f978:ffff:ffff:ffff:ffff:ffff:ffff,CD +2c0f:f980::,2c0f:f980:ffff:ffff:ffff:ffff:ffff:ffff,NA +2c0f:f988::,2c0f:f988:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f990::,2c0f:f990:ffff:ffff:ffff:ffff:ffff:ffff,GN +2c0f:f998::,2c0f:f998:ffff:ffff:ffff:ffff:ffff:ffff,MR +2c0f:f9a0::,2c0f:f9a0:ffff:ffff:ffff:ffff:ffff:ffff,MW +2c0f:f9a8::,2c0f:f9a8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f9b0::,2c0f:f9b0:ffff:ffff:ffff:ffff:ffff:ffff,GA +2c0f:f9b8::,2c0f:f9b8:ffff:ffff:ffff:ffff:ffff:ffff,MU +2c0f:f9c0::,2c0f:f9c0:ffff:ffff:ffff:ffff:ffff:ffff,BW +2c0f:f9c8::,2c0f:f9c8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f9d0::,2c0f:f9d0:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:f9d8::,2c0f:f9d8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f9e0::,2c0f:f9e0:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:f9e8::,2c0f:f9e8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:f9f0::,2c0f:f9f0:ffff:ffff:ffff:ffff:ffff:ffff,MG +2c0f:f9f8::,2c0f:f9f8:ffff:ffff:ffff:ffff:ffff:ffff,BJ +2c0f:fa00::,2c0f:fa00:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:fa08::,2c0f:fa08:ffff:ffff:ffff:ffff:ffff:ffff,CD +2c0f:fa10::,2c0f:fa10:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fa18::,2c0f:fa18:ffff:ffff:ffff:ffff:ffff:ffff,MA +2c0f:fa20::,2c0f:fa20:ffff:ffff:ffff:ffff:ffff:ffff,SS +2c0f:fa28::,2c0f:fa28:ffff:ffff:ffff:ffff:ffff:ffff,MG +2c0f:fa38::,2c0f:fa38:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:fa40::,2c0f:fa40:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fa48::,2c0f:fa48:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fa58::,2c0f:fa58:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fa60::,2c0f:fa60:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:fa68::,2c0f:fa68:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:fa70::,2c0f:fa70:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:fa78::,2c0f:fa78:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fa80::,2c0f:fa80:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:fa88::,2c0f:fa88:ffff:ffff:ffff:ffff:ffff:ffff,ST +2c0f:fa90::,2c0f:fa90:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fa98::,2c0f:fa98:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2c0f:faa0::,2c0f:faa7:ffff:ffff:ffff:ffff:ffff:ffff,SD +2c0f:fab0::,2c0f:fabf:ffff:ffff:ffff:ffff:ffff:ffff,TN +2c0f:fac0::,2c0f:fac0:ffff:ffff:ffff:ffff:ffff:ffff,MW +2c0f:fac8::,2c0f:fac8:ffff:ffff:ffff:ffff:ffff:ffff,BW +2c0f:fad0::,2c0f:fad0:ffff:ffff:ffff:ffff:ffff:ffff,RW +2c0f:fad8::,2c0f:fad8:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fae0::,2c0f:fae0:ffff:ffff:ffff:ffff:ffff:ffff,CM +2c0f:fae8::,2c0f:fae8:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:faf0::,2c0f:faf0:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:faf8::,2c0f:faf8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fb00::,2c0f:fb00:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fb08::,2c0f:fb08:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fb10::,2c0f:fb10:ffff:ffff:ffff:ffff:ffff:ffff,LY +2c0f:fb18::,2c0f:fb18:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fb20::,2c0f:fb20:ffff:ffff:ffff:ffff:ffff:ffff,MA +2c0f:fb28::,2c0f:fb28:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fb30::,2c0f:fb30:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fb38::,2c0f:fb38:ffff:ffff:ffff:ffff:ffff:ffff,SO +2c0f:fb40::,2c0f:fb40:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fb48::,2c0f:fb48:ffff:ffff:ffff:ffff:ffff:ffff,MZ +2c0f:fb50::,2c0f:fb50:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fb58::,2c0f:fb58:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:fb60::,2c0f:fb60:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fb68::,2c0f:fb68:ffff:ffff:ffff:ffff:ffff:ffff,LS +2c0f:fb70::,2c0f:fb70:ffff:ffff:ffff:ffff:ffff:ffff,AO +2c0f:fb78::,2c0f:fb78:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fb80::,2c0f:fb80:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fb88::,2c0f:fb88:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fb90::,2c0f:fb90:ffff:ffff:ffff:ffff:ffff:ffff,MZ +2c0f:fb98::,2c0f:fb98:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fba0::,2c0f:fba0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fba8::,2c0f:fba8:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fbb0::,2c0f:fbb0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fbb8::,2c0f:fbb8:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fbc0::,2c0f:fbc0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fbc8::,2c0f:fbc8:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fbd0::,2c0f:fbd0:ffff:ffff:ffff:ffff:ffff:ffff,GN +2c0f:fbd8::,2c0f:fbd8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fbe0::,2c0f:fc1f:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fc40::,2c0f:fc40:ffff:ffff:ffff:ffff:ffff:ffff,EG +2c0f:fc48::,2c0f:fc48:ffff:ffff:ffff:ffff:ffff:ffff,MW +2c0f:fc50::,2c0f:fc50:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2c0f:fc58::,2c0f:fc58:ffff:ffff:ffff:ffff:ffff:ffff,MW +2c0f:fc60::,2c0f:fc61:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fc68::,2c0f:fc68:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fc70::,2c0f:fc70:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fc78::,2c0f:fc78:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2c0f:fc80::,2c0f:fc80:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fc88::,2c0f:fc89:ffff:ffff:ffff:ffff:ffff:ffff,EG +2c0f:fc90::,2c0f:fc90:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fc98::,2c0f:fc98:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fca0::,2c0f:fca0:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:fca8::,2c0f:fca8:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:fcb0::,2c0f:fcb0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fcb8::,2c0f:fcb8:ffff:ffff:ffff:ffff:ffff:ffff,GM +2c0f:fcc8::,2c0f:fcc8:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fcd0::,2c0f:fcd0:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fcd8::,2c0f:fcd8:ffff:ffff:ffff:ffff:ffff:ffff,SO +2c0f:fce0::,2c0f:fce0:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fce8::,2c0f:fce8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fcf0::,2c0f:fcf0:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fcf8::,2c0f:fcf8:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:fd00::,2c0f:fd00:ffff:ffff:ffff:ffff:ffff:ffff,LS +2c0f:fd08::,2c0f:fd08:ffff:ffff:ffff:ffff:ffff:ffff,GM +2c0f:fd10::,2c0f:fd10:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fd18::,2c0f:fd18:ffff:ffff:ffff:ffff:ffff:ffff,SC +2c0f:fd20::,2c0f:fd20:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fd28::,2c0f:fd28:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fd30::,2c0f:fd30:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fd38::,2c0f:fd38:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fd40::,2c0f:fd40:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fd48::,2c0f:fd48:ffff:ffff:ffff:ffff:ffff:ffff,ZW +2c0f:fd50::,2c0f:fd50:ffff:ffff:ffff:ffff:ffff:ffff,MW +2c0f:fd58::,2c0f:fd58:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fd60::,2c0f:fd60:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fd68::,2c0f:fd68:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fd70::,2c0f:fd70:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fd78::,2c0f:fd78:ffff:ffff:ffff:ffff:ffff:ffff,BI +2c0f:fd80::,2c0f:fd80:ffff:ffff:ffff:ffff:ffff:ffff,BF +2c0f:fd88::,2c0f:fd88:ffff:ffff:ffff:ffff:ffff:ffff,GH +2c0f:fd90::,2c0f:fd90:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fd98::,2c0f:fd98:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fda0::,2c0f:fda0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fda8::,2c0f:fda8:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fdb0::,2c0f:fdb0:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fdb8::,2c0f:fdb8:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fdc0::,2c0f:fdc0:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fdc8::,2c0f:fdc8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fdd0::,2c0f:fdd0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fdd8::,2c0f:fdd8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fde0::,2c0f:fde0:ffff:ffff:ffff:ffff:ffff:ffff,MW +2c0f:fde8::,2c0f:fde8:ffff:ffff:ffff:ffff:ffff:ffff,MW +2c0f:fdf0::,2c0f:fdf0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fdf8::,2c0f:fdf8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fe08::,2c0f:fe08:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fe10::,2c0f:fe10:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fe18::,2c0f:fe18:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fe20::,2c0f:fe20:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fe28::,2c0f:fe28:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fe30::,2c0f:fe30:ffff:ffff:ffff:ffff:ffff:ffff,MU +2c0f:fe38::,2c0f:fe38:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fe40::,2c0f:fe40:ffff:ffff:ffff:ffff:ffff:ffff,MU +2c0f:fe48::,2c0f:fe48:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fe50::,2c0f:fe50:ffff:ffff:ffff:ffff:ffff:ffff,DZ +2c0f:fe58::,2c0f:fe58:ffff:ffff:ffff:ffff:ffff:ffff,LS +2c0f:fe60::,2c0f:fe60:ffff:ffff:ffff:ffff:ffff:ffff,RW +2c0f:fe68::,2c0f:fe68:ffff:ffff:ffff:ffff:ffff:ffff,MU +2c0f:fe70::,2c0f:fe70:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fe78::,2c0f:fe78:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fe80::,2c0f:fe80:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fe88::,2c0f:fe88:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:fe90::,2c0f:fe90:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fe98::,2c0f:fe98:ffff:ffff:ffff:ffff:ffff:ffff,TZ +2c0f:fea0::,2c0f:fea0:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fea8::,2c0f:fea8:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:feb0::,2c0f:feb1:ffff:ffff:ffff:ffff:ffff:ffff,MU +2c0f:feb8::,2c0f:feb8:ffff:ffff:ffff:ffff:ffff:ffff,ZM +2c0f:fec0::,2c0f:fec0:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:fec8::,2c0f:fec8:ffff:ffff:ffff:ffff:ffff:ffff,SD +2c0f:fed8::,2c0f:fed8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:fee0::,2c0f:fee0:ffff:ffff:ffff:ffff:ffff:ffff,EG +2c0f:fef0::,2c0f:fef0:ffff:ffff:ffff:ffff:ffff:ffff,SC +2c0f:fef8::,2c0f:fef8:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:ff00::,2c0f:ff00:ffff:ffff:ffff:ffff:ffff:ffff,BW +2c0f:ff08::,2c0f:ff08:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ff10::,2c0f:ff10:ffff:ffff:ffff:ffff:ffff:ffff,CD +2c0f:ff18::,2c0f:ff18:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:ff20::,2c0f:ff20:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:ff28::,2c0f:ff28:ffff:ffff:ffff:ffff:ffff:ffff,SD +2c0f:ff30::,2c0f:ff30:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ff40::,2c0f:ff80:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ff88::,2c0f:ff88:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:ff90::,2c0f:ff90:ffff:ffff:ffff:ffff:ffff:ffff,KE +2c0f:ff98::,2c0f:ff98:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:ffa0::,2c0f:ffa0:ffff:ffff:ffff:ffff:ffff:ffff,UG +2c0f:ffa8::,2c0f:ffa8:ffff:ffff:ffff:ffff:ffff:ffff,LS +2c0f:ffb0::,2c0f:ffb0:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:ffb8::,2c0f:ffb8:ffff:ffff:ffff:ffff:ffff:ffff,SD +2c0f:ffc0::,2c0f:ffc0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ffc8::,2c0f:ffc8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ffd0::,2c0f:ffd0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ffd8::,2c0f:ffd8:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ffe0::,2c0f:ffe0:ffff:ffff:ffff:ffff:ffff:ffff,ZA +2c0f:ffe8::,2c0f:ffe8:ffff:ffff:ffff:ffff:ffff:ffff,NG +2c0f:fff0::,2c0f:fff0:ffff:ffff:ffff:ffff:ffff:ffff,NG diff --git a/src/config/include.am b/src/config/include.am new file mode 100644 index 0000000000..35961b829a --- /dev/null +++ b/src/config/include.am @@ -0,0 +1,16 @@ +confdir = $(sysconfdir)/tor + +tordatadir = $(datadir)/tor + +EXTRA_DIST+= src/config/geoip src/config/geoip6 +# fallback-consensus + +conf_DATA = src/config/torrc.sample + +tordata_DATA = src/config/geoip src/config/geoip6 +# fallback_consensus + +# If we don't have it, fake it. +src_config_fallback-consensus: + touch src/config/fallback-consensus + diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in index a1a08aa8f9..c667efc5c9 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 22 April 2012 for Tor 0.2.3.14-alpha. +## Last updated 12 September 2012 for Tor 0.2.4.3-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 @@ -16,7 +16,7 @@ ## configure one below. Set "SocksPort 0" if you plan to run Tor only ## as a relay, and not make any local application connections yourself. #SocksPort 9050 # Default: Bind to localhost:9050 for local connections. -#SocksPort 192.168.0.1:9100 # Bind to this adddress:port too. +#SocksPort 192.168.0.1:9100 # Bind to this address:port too. ## Entry policies to allow/deny SOCKS requests based on IP address. ## First entry that matches wins. If no SocksPolicy is set, we accept diff --git a/src/common/OpenBSD_malloc_Linux.c b/src/ext/OpenBSD_malloc_Linux.c index da82729811..da82729811 100644 --- a/src/common/OpenBSD_malloc_Linux.c +++ b/src/ext/OpenBSD_malloc_Linux.c diff --git a/src/ext/README b/src/ext/README new file mode 100644 index 0000000000..58ba7f699d --- /dev/null +++ b/src/ext/README @@ -0,0 +1,44 @@ + +OpenBSD_malloc_Linux.c: + + The OpenBSD malloc implementation, ported to Linux. Used only when + --enable-openbsd-malloc is passed to the configure script. + +strlcat.c +strlcpy.c + + Implementations of strlcat and strlcpy, the more sane replacements + for strcat and strcpy. These are nonstandard, and some libc + implementations refuse to add them for religious reasons. + +eventdns.[ch] + + A fork of Libevent's DNS implementation, used by Tor when Libevent + 2.0 or later is not available. Once Libevent 2.0 is required, we + should throw this away; it has diverged from evdns.[ch], and is + no longer easily mergeable. + +ht.h + + An implementation of a hash table in the style of Niels Provos's + tree.h. Shared with Libevent. + +tinytest.[ch] +tinytest_demos.c +tinytest_macros.h + + A unit testing framework. https://github.com/nmathewson/tinytest + +tor_queue.h + + A copy of sys/queue.h from OpenBSD. We keep our own copy rather + than using sys/queue.h, since some platforms don't have a + sys/queue.h, and the ones that do have diverged in incompatible + ways. (CIRCLEQ or no CIRCLEQ? SIMPLQ or STAILQ?) We also rename + the identifiers with a TOR_ prefix to avoid conflicts with + the system headers. + +curve25519_donna/*.c + + A copy of Adam Langley's curve25519-donna mostly-portable + implementations of curve25519. diff --git a/src/ext/curve25519_donna/README b/src/ext/curve25519_donna/README new file mode 100644 index 0000000000..9f77bd7d95 --- /dev/null +++ b/src/ext/curve25519_donna/README @@ -0,0 +1,44 @@ +See http://code.google.com/p/curve25519-donna/ for details. + +BUILDING: + +If you run `make`, two .a archives will be built, similar to djb's curve25519 +code. Alternatively, read on: + +The C implementation is contained within curve25519-donna.c. It has no external +dependancies and is BSD licenced. You can copy/include/link it directly in with +your program. Recommended C flags: -O2 + +The x86-64 bit implementation is contained within curve25519-donna-x86-64.c and +curve25519-donna-x86-64.s. Build like this: + +% cpp curve25519-donna-x86-64.s > curve25519-donna-x86-64.s.pp +% as -o curve25519-donna-x86-64.s.o curve25519-donna-x86-64.s.pp +% gcc -O2 -c curve25519-donna-x86-64.c + +Then the two .o files can be linked in + +USAGE: + +The usage is exactly the same as djb's code (as described at +http://cr.yp.to/ecdh.html) expect that the function is called curve25519_donna. + +In short, + +To generate a private key, generate 32 random bytes and: + + mysecret[0] &= 248; + mysecret[31] &= 127; + mysecret[31] |= 64; + +To generate the public key, just do + + static const uint8_t basepoint[32] = {9}; + curve25519_donna(mypublic, mysecret, basepoint); + +To generate an agreed key do: + uint8_t shared_key[32]; + curve25519_donna(shared_key, mysecret, theirpublic); + +And hash the shared_key with a cryptographic hash function before using. + diff --git a/src/ext/curve25519_donna/curve25519-donna-c64.c b/src/ext/curve25519_donna/curve25519-donna-c64.c new file mode 100644 index 0000000000..b68ff3695a --- /dev/null +++ b/src/ext/curve25519_donna/curve25519-donna-c64.c @@ -0,0 +1,451 @@ +/* Copyright 2008, Google Inc. + * All rights reserved. + * + * Code released into the public domain. + * + * curve25519-donna: Curve25519 elliptic curve, public key function + * + * http://code.google.com/p/curve25519-donna/ + * + * Adam Langley <agl@imperialviolet.org> + * + * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to> + * + * More information about curve25519 can be found here + * http://cr.yp.to/ecdh.html + * + * djb's sample implementation of curve25519 is written in a special assembly + * language called qhasm and uses the floating point registers. + * + * This is, almost, a clean room reimplementation from the curve25519 paper. It + * uses many of the tricks described therein. Only the crecip function is taken + * from the sample implementation. + */ + +#include "orconfig.h" + +#include <string.h> +#include "torint.h" + +typedef uint8_t u8; +typedef uint64_t limb; +typedef limb felem[5]; +// This is a special gcc mode for 128-bit integers. It's implemented on 64-bit +// platforms only as far as I know. +typedef unsigned uint128_t __attribute__((mode(TI))); + +#undef force_inline +#define force_inline __attribute__((always_inline)) + +/* Sum two numbers: output += in */ +static inline void force_inline +fsum(limb *output, const limb *in) { + output[0] += in[0]; + output[1] += in[1]; + output[2] += in[2]; + output[3] += in[3]; + output[4] += in[4]; +} + +/* Find the difference of two numbers: output = in - output + * (note the order of the arguments!) + * + * Assumes that out[i] < 2**52 + * On return, out[i] < 2**55 + */ +static inline void force_inline +fdifference_backwards(felem out, const felem in) { + /* 152 is 19 << 3 */ + static const limb two54m152 = (((limb)1) << 54) - 152; + static const limb two54m8 = (((limb)1) << 54) - 8; + + out[0] = in[0] + two54m152 - out[0]; + out[1] = in[1] + two54m8 - out[1]; + out[2] = in[2] + two54m8 - out[2]; + out[3] = in[3] + two54m8 - out[3]; + out[4] = in[4] + two54m8 - out[4]; +} + +/* Multiply a number by a scalar: output = in * scalar */ +static inline void force_inline +fscalar_product(felem output, const felem in, const limb scalar) { + uint128_t a; + + a = ((uint128_t) in[0]) * scalar; + output[0] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[1]) * scalar + ((limb) (a >> 51)); + output[1] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[2]) * scalar + ((limb) (a >> 51)); + output[2] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[3]) * scalar + ((limb) (a >> 51)); + output[3] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[4]) * scalar + ((limb) (a >> 51)); + output[4] = ((limb)a) & 0x7ffffffffffff; + + output[0] += (a >> 51) * 19; +} + +/* Multiply two numbers: output = in2 * in + * + * output must be distinct to both inputs. The inputs are reduced coefficient + * form, the output is not. + * + * Assumes that in[i] < 2**55 and likewise for in2. + * On return, output[i] < 2**52 + */ +static inline void force_inline +fmul(felem output, const felem in2, const felem in) { + uint128_t t[5]; + limb r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; + + r0 = in[0]; + r1 = in[1]; + r2 = in[2]; + r3 = in[3]; + r4 = in[4]; + + s0 = in2[0]; + s1 = in2[1]; + s2 = in2[2]; + s3 = in2[3]; + s4 = in2[4]; + + t[0] = ((uint128_t) r0) * s0; + t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0; + t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1; + t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1; + t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2; + + r4 *= 19; + r1 *= 19; + r2 *= 19; + r3 *= 19; + + t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2; + t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3; + t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4; + t[3] += ((uint128_t) r4) * s4; + + r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51); + t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51); + t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51); + t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51); + t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff; + r2 += c; + + output[0] = r0; + output[1] = r1; + output[2] = r2; + output[3] = r3; + output[4] = r4; +} + +static inline void force_inline +fsquare_times(felem output, const felem in, limb count) { + uint128_t t[5]; + limb r0,r1,r2,r3,r4,c; + limb d0,d1,d2,d4,d419; + + r0 = in[0]; + r1 = in[1]; + r2 = in[2]; + r3 = in[3]; + r4 = in[4]; + + do { + d0 = r0 * 2; + d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; + d4 = d419 * 2; + + t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); + t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); + t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); + t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); + t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); + + r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51); + t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51); + t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51); + t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51); + t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff; + r2 += c; + } while(--count); + + output[0] = r0; + output[1] = r1; + output[2] = r2; + output[3] = r3; + output[4] = r4; +} + +/* Load a little-endian 64-bit number */ +static limb +load_limb(const u8 *in) { + return + ((limb)in[0]) | + (((limb)in[1]) << 8) | + (((limb)in[2]) << 16) | + (((limb)in[3]) << 24) | + (((limb)in[4]) << 32) | + (((limb)in[5]) << 40) | + (((limb)in[6]) << 48) | + (((limb)in[7]) << 56); +} + +static void +store_limb(u8 *out, limb in) { + out[0] = in & 0xff; + out[1] = (in >> 8) & 0xff; + out[2] = (in >> 16) & 0xff; + out[3] = (in >> 24) & 0xff; + out[4] = (in >> 32) & 0xff; + out[5] = (in >> 40) & 0xff; + out[6] = (in >> 48) & 0xff; + out[7] = (in >> 56) & 0xff; +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +static void +fexpand(limb *output, const u8 *in) { + output[0] = load_limb(in) & 0x7ffffffffffff; + output[1] = (load_limb(in+6) >> 3) & 0x7ffffffffffff; + output[2] = (load_limb(in+12) >> 6) & 0x7ffffffffffff; + output[3] = (load_limb(in+19) >> 1) & 0x7ffffffffffff; + output[4] = (load_limb(in+24) >> 12) & 0x7ffffffffffff; +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +static void +fcontract(u8 *output, const felem input) { + uint128_t t[5]; + + t[0] = input[0]; + t[1] = input[1]; + t[2] = input[2]; + t[3] = input[3]; + t[4] = input[4]; + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff; + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff; + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + + t[0] += 19; + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff; + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + + t[0] += 0x8000000000000 - 19; + t[1] += 0x8000000000000 - 1; + t[2] += 0x8000000000000 - 1; + t[3] += 0x8000000000000 - 1; + t[4] += 0x8000000000000 - 1; + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[4] &= 0x7ffffffffffff; + + store_limb(output, t[0] | (t[1] << 51)); + store_limb(output+8, (t[1] >> 13) | (t[2] << 38)); + store_limb(output+16, (t[2] >> 26) | (t[3] << 25)); + store_limb(output+24, (t[3] >> 39) | (t[4] << 12)); +} + +/* Input: Q, Q', Q-Q' + * Output: 2Q, Q+Q' + * + * x2 z3: long form + * x3 z3: long form + * x z: short form, destroyed + * xprime zprime: short form, destroyed + * qmqp: short form, preserved + */ +static void +fmonty(limb *x2, limb *z2, /* output 2Q */ + limb *x3, limb *z3, /* output Q + Q' */ + limb *x, limb *z, /* input Q */ + limb *xprime, limb *zprime, /* input Q' */ + const limb *qmqp /* input Q - Q' */) { + limb origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5], + zzprime[5], zzzprime[5]; + + memcpy(origx, x, 5 * sizeof(limb)); + fsum(x, z); + fdifference_backwards(z, origx); // does x - z + + memcpy(origxprime, xprime, sizeof(limb) * 5); + fsum(xprime, zprime); + fdifference_backwards(zprime, origxprime); + fmul(xxprime, xprime, z); + fmul(zzprime, x, zprime); + memcpy(origxprime, xxprime, sizeof(limb) * 5); + fsum(xxprime, zzprime); + fdifference_backwards(zzprime, origxprime); + fsquare_times(x3, xxprime, 1); + fsquare_times(zzzprime, zzprime, 1); + fmul(z3, zzzprime, qmqp); + + fsquare_times(xx, x, 1); + fsquare_times(zz, z, 1); + fmul(x2, xx, zz); + fdifference_backwards(zz, xx); // does zz = xx - zz + fscalar_product(zzz, zz, 121665); + fsum(zzz, xx); + fmul(z2, zz, zzz); +} + +// ----------------------------------------------------------------------------- +// Maybe swap the contents of two limb arrays (@a and @b), each @len elements +// long. Perform the swap iff @swap is non-zero. +// +// This function performs the swap without leaking any side-channel +// information. +// ----------------------------------------------------------------------------- +static void +swap_conditional(limb a[5], limb b[5], limb iswap) { + unsigned i; + const limb swap = -iswap; + + for (i = 0; i < 5; ++i) { + const limb x = swap & (a[i] ^ b[i]); + a[i] ^= x; + b[i] ^= x; + } +} + +/* Calculates nQ where Q is the x-coordinate of a point on the curve + * + * resultx/resultz: the x coordinate of the resulting curve point (short form) + * n: a little endian, 32-byte number + * q: a point of the curve (short form) + */ +static void +cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { + limb a[5] = {0}, b[5] = {1}, c[5] = {1}, d[5] = {0}; + limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; + limb e[5] = {0}, f[5] = {1}, g[5] = {0}, h[5] = {1}; + limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; + + unsigned i, j; + + memcpy(nqpqx, q, sizeof(limb) * 5); + + for (i = 0; i < 32; ++i) { + u8 byte = n[31 - i]; + for (j = 0; j < 8; ++j) { + const limb bit = byte >> 7; + + swap_conditional(nqx, nqpqx, bit); + swap_conditional(nqz, nqpqz, bit); + fmonty(nqx2, nqz2, + nqpqx2, nqpqz2, + nqx, nqz, + nqpqx, nqpqz, + q); + swap_conditional(nqx2, nqpqx2, bit); + swap_conditional(nqz2, nqpqz2, bit); + + t = nqx; + nqx = nqx2; + nqx2 = t; + t = nqz; + nqz = nqz2; + nqz2 = t; + t = nqpqx; + nqpqx = nqpqx2; + nqpqx2 = t; + t = nqpqz; + nqpqz = nqpqz2; + nqpqz2 = t; + + byte <<= 1; + } + } + + memcpy(resultx, nqx, sizeof(limb) * 5); + memcpy(resultz, nqz, sizeof(limb) * 5); +} + + +// ----------------------------------------------------------------------------- +// Shamelessly copied from djb's code, tightened a little +// ----------------------------------------------------------------------------- +static void +crecip(felem out, const felem z) { + felem a,t0,b,c; + + /* 2 */ fsquare_times(a, z, 1); // a = 2 + /* 8 */ fsquare_times(t0, a, 2); + /* 9 */ fmul(b, t0, z); // b = 9 + /* 11 */ fmul(a, b, a); // a = 11 + /* 22 */ fsquare_times(t0, a, 1); + /* 2^5 - 2^0 = 31 */ fmul(b, t0, b); + /* 2^10 - 2^5 */ fsquare_times(t0, b, 5); + /* 2^10 - 2^0 */ fmul(b, t0, b); + /* 2^20 - 2^10 */ fsquare_times(t0, b, 10); + /* 2^20 - 2^0 */ fmul(c, t0, b); + /* 2^40 - 2^20 */ fsquare_times(t0, c, 20); + /* 2^40 - 2^0 */ fmul(t0, t0, c); + /* 2^50 - 2^10 */ fsquare_times(t0, t0, 10); + /* 2^50 - 2^0 */ fmul(b, t0, b); + /* 2^100 - 2^50 */ fsquare_times(t0, b, 50); + /* 2^100 - 2^0 */ fmul(c, t0, b); + /* 2^200 - 2^100 */ fsquare_times(t0, c, 100); + /* 2^200 - 2^0 */ fmul(t0, t0, c); + /* 2^250 - 2^50 */ fsquare_times(t0, t0, 50); + /* 2^250 - 2^0 */ fmul(t0, t0, b); + /* 2^255 - 2^5 */ fsquare_times(t0, t0, 5); + /* 2^255 - 21 */ fmul(out, t0, a); +} + +int curve25519_donna(u8 *, const u8 *, const u8 *); + +int +curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { + limb bp[5], x[5], z[5], zmone[5]; + uint8_t e[32]; + int i; + + for (i = 0;i < 32;++i) e[i] = secret[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fexpand(bp, basepoint); + cmult(x, z, e, bp); + crecip(zmone, z); + fmul(z, x, zmone); + fcontract(mypublic, z); + return 0; +} diff --git a/src/ext/curve25519_donna/curve25519-donna.c b/src/ext/curve25519_donna/curve25519-donna.c new file mode 100644 index 0000000000..5c6821ccd8 --- /dev/null +++ b/src/ext/curve25519_donna/curve25519-donna.c @@ -0,0 +1,732 @@ +/* Copyright 2008, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * curve25519-donna: Curve25519 elliptic curve, public key function + * + * http://code.google.com/p/curve25519-donna/ + * + * Adam Langley <agl@imperialviolet.org> + * + * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to> + * + * More information about curve25519 can be found here + * http://cr.yp.to/ecdh.html + * + * djb's sample implementation of curve25519 is written in a special assembly + * language called qhasm and uses the floating point registers. + * + * This is, almost, a clean room reimplementation from the curve25519 paper. It + * uses many of the tricks described therein. Only the crecip function is taken + * from the sample implementation. + */ + +#include "orconfig.h" + +#include <string.h> +#include "torint.h" + +typedef uint8_t u8; +typedef int32_t s32; +typedef int64_t limb; + +/* Field element representation: + * + * Field elements are written as an array of signed, 64-bit limbs, least + * significant first. The value of the field element is: + * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ... + * + * i.e. the limbs are 26, 25, 26, 25, ... bits wide. + */ + +/* Sum two numbers: output += in */ +static void fsum(limb *output, const limb *in) { + unsigned i; + for (i = 0; i < 10; i += 2) { + output[0+i] = (output[0+i] + in[0+i]); + output[1+i] = (output[1+i] + in[1+i]); + } +} + +/* Find the difference of two numbers: output = in - output + * (note the order of the arguments!) + */ +static void fdifference(limb *output, const limb *in) { + unsigned i; + for (i = 0; i < 10; ++i) { + output[i] = (in[i] - output[i]); + } +} + +/* Multiply a number by a scalar: output = in * scalar */ +static void fscalar_product(limb *output, const limb *in, const limb scalar) { + unsigned i; + for (i = 0; i < 10; ++i) { + output[i] = in[i] * scalar; + } +} + +/* Multiply two numbers: output = in2 * in + * + * output must be distinct to both inputs. The inputs are reduced coefficient + * form, the output is not. + */ +static void fproduct(limb *output, const limb *in2, const limb *in) { + output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); + output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + + ((limb) ((s32) in2[1])) * ((s32) in[0]); + output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[2]) + + ((limb) ((s32) in2[2])) * ((s32) in[0]); + output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + + ((limb) ((s32) in2[2])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[0]); + output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + + 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[1])) + + ((limb) ((s32) in2[0])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[0]); + output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[0]); + output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[1])) + + ((limb) ((s32) in2[2])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[2]) + + ((limb) ((s32) in2[0])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[0]); + output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[0]); + output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) + + 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[1])) + + ((limb) ((s32) in2[2])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[2]) + + ((limb) ((s32) in2[0])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[0]); + output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[4]) + + ((limb) ((s32) in2[3])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[0]); + output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) + + ((limb) ((s32) in2[3])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[1])) + + ((limb) ((s32) in2[4])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[4]) + + ((limb) ((s32) in2[2])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[2]); + output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[5]) + + ((limb) ((s32) in2[4])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[4]) + + ((limb) ((s32) in2[3])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[2]); + output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) + + 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[5]) + + ((limb) ((s32) in2[3])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[3])) + + ((limb) ((s32) in2[4])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[4]); + output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[6]) + + ((limb) ((s32) in2[5])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[5]) + + ((limb) ((s32) in2[4])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[4]); + output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) + + ((limb) ((s32) in2[5])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[5])) + + ((limb) ((s32) in2[6])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[6]); + output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[7]) + + ((limb) ((s32) in2[6])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[6]); + output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[7])); + output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[8]); + output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); +} + +/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */ +static void freduce_degree(limb *output) { + /* Each of these shifts and adds ends up multiplying the value by 19. */ + output[8] += output[18] << 4; + output[8] += output[18] << 1; + output[8] += output[18]; + output[7] += output[17] << 4; + output[7] += output[17] << 1; + output[7] += output[17]; + output[6] += output[16] << 4; + output[6] += output[16] << 1; + output[6] += output[16]; + output[5] += output[15] << 4; + output[5] += output[15] << 1; + output[5] += output[15]; + output[4] += output[14] << 4; + output[4] += output[14] << 1; + output[4] += output[14]; + output[3] += output[13] << 4; + output[3] += output[13] << 1; + output[3] += output[13]; + output[2] += output[12] << 4; + output[2] += output[12] << 1; + output[2] += output[12]; + output[1] += output[11] << 4; + output[1] += output[11] << 1; + output[1] += output[11]; + output[0] += output[10] << 4; + output[0] += output[10] << 1; + output[0] += output[10]; +} + +#if (-1 & 3) != 3 +#error "This code only works on a two's complement system" +#endif + +/* return v / 2^26, using only shifts and adds. */ +static inline limb +div_by_2_26(const limb v) +{ + /* High word of v; no shift needed*/ + const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); + /* Set to all 1s if v was negative; else set to 0s. */ + const int32_t sign = ((int32_t) highword) >> 31; + /* Set to 0x3ffffff if v was negative; else set to 0. */ + const int32_t roundoff = ((uint32_t) sign) >> 6; + /* Should return v / (1<<26) */ + return (v + roundoff) >> 26; +} + +/* return v / (2^25), using only shifts and adds. */ +static inline limb +div_by_2_25(const limb v) +{ + /* High word of v; no shift needed*/ + const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); + /* Set to all 1s if v was negative; else set to 0s. */ + const int32_t sign = ((int32_t) highword) >> 31; + /* Set to 0x1ffffff if v was negative; else set to 0. */ + const int32_t roundoff = ((uint32_t) sign) >> 7; + /* Should return v / (1<<25) */ + return (v + roundoff) >> 25; +} + +static inline s32 +div_s32_by_2_25(const s32 v) +{ + const s32 roundoff = ((uint32_t)(v >> 31)) >> 7; + return (v + roundoff) >> 25; +} + +/* Reduce all coefficients of the short form input so that |x| < 2^26. + * + * On entry: |output[i]| < 2^62 + */ +static void freduce_coefficients(limb *output) { + unsigned i; + + output[10] = 0; + + for (i = 0; i < 10; i += 2) { + limb over = div_by_2_26(output[i]); + output[i] -= over << 26; + output[i+1] += over; + + over = div_by_2_25(output[i+1]); + output[i+1] -= over << 25; + output[i+2] += over; + } + /* Now |output[10]| < 2 ^ 38 and all other coefficients are reduced. */ + output[0] += output[10] << 4; + output[0] += output[10] << 1; + output[0] += output[10]; + + output[10] = 0; + + /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19 * 2^38 + * So |over| will be no more than 77825 */ + { + limb over = div_by_2_26(output[0]); + output[0] -= over << 26; + output[1] += over; + } + + /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 77825 + * So |over| will be no more than 1. */ + { + /* output[1] fits in 32 bits, so we can use div_s32_by_2_25 here. */ + s32 over32 = div_s32_by_2_25((s32) output[1]); + output[1] -= over32 << 25; + output[2] += over32; + } + + /* Finally, output[0,1,3..9] are reduced, and output[2] is "nearly reduced": + * we have |output[2]| <= 2^26. This is good enough for all of our math, + * but it will require an extra freduce_coefficients before fcontract. */ +} + +/* A helpful wrapper around fproduct: output = in * in2. + * + * output must be distinct to both inputs. The output is reduced degree and + * reduced coefficient. + */ +static void +fmul(limb *output, const limb *in, const limb *in2) { + limb t[19]; + fproduct(t, in, in2); + freduce_degree(t); + freduce_coefficients(t); + memcpy(output, t, sizeof(limb) * 10); +} + +static void fsquare_inner(limb *output, const limb *in) { + output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); + output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); + output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + + ((limb) ((s32) in[0])) * ((s32) in[2])); + output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + + ((limb) ((s32) in[0])) * ((s32) in[3])); + output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + + 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + + 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); + output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + + ((limb) ((s32) in[1])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[5])); + output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + + ((limb) ((s32) in[2])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[6]) + + 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); + output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + + ((limb) ((s32) in[2])) * ((s32) in[5]) + + ((limb) ((s32) in[1])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[7])); + output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + + 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[5]))); + output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + + ((limb) ((s32) in[3])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[8]) + + ((limb) ((s32) in[0])) * ((s32) in[9])); + output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + + ((limb) ((s32) in[4])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[9]))); + output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + + ((limb) ((s32) in[4])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[8]) + + ((limb) ((s32) in[2])) * ((s32) in[9])); + output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + + 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[9]))); + output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + + ((limb) ((s32) in[5])) * ((s32) in[8]) + + ((limb) ((s32) in[4])) * ((s32) in[9])); + output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + + ((limb) ((s32) in[6])) * ((s32) in[8]) + + 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); + output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + + ((limb) ((s32) in[6])) * ((s32) in[9])); + output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + + 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); + output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); + output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); +} + +static void +fsquare(limb *output, const limb *in) { + limb t[19]; + fsquare_inner(t, in); + freduce_degree(t); + freduce_coefficients(t); + memcpy(output, t, sizeof(limb) * 10); +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +static void +fexpand(limb *output, const u8 *input) { +#define F(n,start,shift,mask) \ + output[n] = ((((limb) input[start + 0]) | \ + ((limb) input[start + 1]) << 8 | \ + ((limb) input[start + 2]) << 16 | \ + ((limb) input[start + 3]) << 24) >> shift) & mask; + F(0, 0, 0, 0x3ffffff); + F(1, 3, 2, 0x1ffffff); + F(2, 6, 3, 0x3ffffff); + F(3, 9, 5, 0x1ffffff); + F(4, 12, 6, 0x3ffffff); + F(5, 16, 0, 0x1ffffff); + F(6, 19, 1, 0x3ffffff); + F(7, 22, 3, 0x1ffffff); + F(8, 25, 4, 0x3ffffff); + F(9, 28, 6, 0x1ffffff); +#undef F +} + +#if (-32 >> 1) != -16 +#error "This code only works when >> does sign-extension on negative numbers" +#endif + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +static void +fcontract(u8 *output, limb *input) { + int i; + int j; + + for (j = 0; j < 2; ++j) { + for (i = 0; i < 9; ++i) { + if ((i & 1) == 1) { + /* This calculation is a time-invariant way to make input[i] positive + by borrowing from the next-larger limb. + */ + const s32 mask = (s32)(input[i]) >> 31; + const s32 carry = -(((s32)(input[i]) & mask) >> 25); + input[i] = (s32)(input[i]) + (carry << 25); + input[i+1] = (s32)(input[i+1]) - carry; + } else { + const s32 mask = (s32)(input[i]) >> 31; + const s32 carry = -(((s32)(input[i]) & mask) >> 26); + input[i] = (s32)(input[i]) + (carry << 26); + input[i+1] = (s32)(input[i+1]) - carry; + } + } + { + const s32 mask = (s32)(input[9]) >> 31; + const s32 carry = -(((s32)(input[9]) & mask) >> 25); + input[9] = (s32)(input[9]) + (carry << 25); + input[0] = (s32)(input[0]) - (carry * 19); + } + } + + /* The first borrow-propagation pass above ended with every limb + except (possibly) input[0] non-negative. + + Since each input limb except input[0] is decreased by at most 1 + by a borrow-propagation pass, the second borrow-propagation pass + could only have wrapped around to decrease input[0] again if the + first pass left input[0] negative *and* input[1] through input[9] + were all zero. In that case, input[1] is now 2^25 - 1, and this + last borrow-propagation step will leave input[1] non-negative. + */ + { + const s32 mask = (s32)(input[0]) >> 31; + const s32 carry = -(((s32)(input[0]) & mask) >> 26); + input[0] = (s32)(input[0]) + (carry << 26); + input[1] = (s32)(input[1]) - carry; + } + + /* Both passes through the above loop, plus the last 0-to-1 step, are + necessary: if input[9] is -1 and input[0] through input[8] are 0, + negative values will remain in the array until the end. + */ + + input[1] <<= 2; + input[2] <<= 3; + input[3] <<= 5; + input[4] <<= 6; + input[6] <<= 1; + input[7] <<= 3; + input[8] <<= 4; + input[9] <<= 6; +#define F(i, s) \ + output[s+0] |= input[i] & 0xff; \ + output[s+1] = (input[i] >> 8) & 0xff; \ + output[s+2] = (input[i] >> 16) & 0xff; \ + output[s+3] = (input[i] >> 24) & 0xff; + output[0] = 0; + output[16] = 0; + F(0,0); + F(1,3); + F(2,6); + F(3,9); + F(4,12); + F(5,16); + F(6,19); + F(7,22); + F(8,25); + F(9,28); +#undef F +} + +/* Input: Q, Q', Q-Q' + * Output: 2Q, Q+Q' + * + * x2 z3: long form + * x3 z3: long form + * x z: short form, destroyed + * xprime zprime: short form, destroyed + * qmqp: short form, preserved + */ +static void fmonty(limb *x2, limb *z2, /* output 2Q */ + limb *x3, limb *z3, /* output Q + Q' */ + limb *x, limb *z, /* input Q */ + limb *xprime, limb *zprime, /* input Q' */ + const limb *qmqp /* input Q - Q' */) { + limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], + zzprime[19], zzzprime[19], xxxprime[19]; + + memcpy(origx, x, 10 * sizeof(limb)); + fsum(x, z); + fdifference(z, origx); // does x - z + + memcpy(origxprime, xprime, sizeof(limb) * 10); + fsum(xprime, zprime); + fdifference(zprime, origxprime); + fproduct(xxprime, xprime, z); + fproduct(zzprime, x, zprime); + freduce_degree(xxprime); + freduce_coefficients(xxprime); + freduce_degree(zzprime); + freduce_coefficients(zzprime); + memcpy(origxprime, xxprime, sizeof(limb) * 10); + fsum(xxprime, zzprime); + fdifference(zzprime, origxprime); + fsquare(xxxprime, xxprime); + fsquare(zzzprime, zzprime); + fproduct(zzprime, zzzprime, qmqp); + freduce_degree(zzprime); + freduce_coefficients(zzprime); + memcpy(x3, xxxprime, sizeof(limb) * 10); + memcpy(z3, zzprime, sizeof(limb) * 10); + + fsquare(xx, x); + fsquare(zz, z); + fproduct(x2, xx, zz); + freduce_degree(x2); + freduce_coefficients(x2); + fdifference(zz, xx); // does zz = xx - zz + memset(zzz + 10, 0, sizeof(limb) * 9); + fscalar_product(zzz, zz, 121665); + /* No need to call freduce_degree here: + fscalar_product doesn't increase the degree of its input. */ + freduce_coefficients(zzz); + fsum(zzz, xx); + fproduct(z2, zz, zzz); + freduce_degree(z2); + freduce_coefficients(z2); +} + +/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave + * them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid + * side-channel attacks. + * + * NOTE that this function requires that 'iswap' be 1 or 0; other values give + * wrong results. Also, the two limb arrays must be in reduced-coefficient, + * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped, + * and all all values in a[0..9],b[0..9] must have magnitude less than + * INT32_MAX. + */ +static void +swap_conditional(limb a[19], limb b[19], limb iswap) { + unsigned i; + const s32 swap = (s32) -iswap; + + for (i = 0; i < 10; ++i) { + const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) ); + a[i] = ((s32)a[i]) ^ x; + b[i] = ((s32)b[i]) ^ x; + } +} + +/* Calculates nQ where Q is the x-coordinate of a point on the curve + * + * resultx/resultz: the x coordinate of the resulting curve point (short form) + * n: a little endian, 32-byte number + * q: a point of the curve (short form) + */ +static void +cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { + limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; + limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; + limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; + limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; + + unsigned i, j; + + memcpy(nqpqx, q, sizeof(limb) * 10); + + for (i = 0; i < 32; ++i) { + u8 byte = n[31 - i]; + for (j = 0; j < 8; ++j) { + const limb bit = byte >> 7; + + swap_conditional(nqx, nqpqx, bit); + swap_conditional(nqz, nqpqz, bit); + fmonty(nqx2, nqz2, + nqpqx2, nqpqz2, + nqx, nqz, + nqpqx, nqpqz, + q); + swap_conditional(nqx2, nqpqx2, bit); + swap_conditional(nqz2, nqpqz2, bit); + + t = nqx; + nqx = nqx2; + nqx2 = t; + t = nqz; + nqz = nqz2; + nqz2 = t; + t = nqpqx; + nqpqx = nqpqx2; + nqpqx2 = t; + t = nqpqz; + nqpqz = nqpqz2; + nqpqz2 = t; + + byte <<= 1; + } + } + + memcpy(resultx, nqx, sizeof(limb) * 10); + memcpy(resultz, nqz, sizeof(limb) * 10); +} + +// ----------------------------------------------------------------------------- +// Shamelessly copied from djb's code +// ----------------------------------------------------------------------------- +static void +crecip(limb *out, const limb *z) { + limb z2[10]; + limb z9[10]; + limb z11[10]; + limb z2_5_0[10]; + limb z2_10_0[10]; + limb z2_20_0[10]; + limb z2_50_0[10]; + limb z2_100_0[10]; + limb t0[10]; + limb t1[10]; + int i; + + /* 2 */ fsquare(z2,z); + /* 4 */ fsquare(t1,z2); + /* 8 */ fsquare(t0,t1); + /* 9 */ fmul(z9,t0,z); + /* 11 */ fmul(z11,z9,z2); + /* 22 */ fsquare(t0,z11); + /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); + + /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); + /* 2^7 - 2^2 */ fsquare(t1,t0); + /* 2^8 - 2^3 */ fsquare(t0,t1); + /* 2^9 - 2^4 */ fsquare(t1,t0); + /* 2^10 - 2^5 */ fsquare(t0,t1); + /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); + + /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); + /* 2^12 - 2^2 */ fsquare(t1,t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); + + /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); + /* 2^22 - 2^2 */ fsquare(t1,t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); + + /* 2^41 - 2^1 */ fsquare(t1,t0); + /* 2^42 - 2^2 */ fsquare(t0,t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); + + /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); + /* 2^52 - 2^2 */ fsquare(t1,t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); + + /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); + /* 2^102 - 2^2 */ fsquare(t0,t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); + + /* 2^201 - 2^1 */ fsquare(t0,t1); + /* 2^202 - 2^2 */ fsquare(t1,t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); + + /* 2^251 - 2^1 */ fsquare(t1,t0); + /* 2^252 - 2^2 */ fsquare(t0,t1); + /* 2^253 - 2^3 */ fsquare(t1,t0); + /* 2^254 - 2^4 */ fsquare(t0,t1); + /* 2^255 - 2^5 */ fsquare(t1,t0); + /* 2^255 - 21 */ fmul(out,t1,z11); +} + +int curve25519_donna(u8 *, const u8 *, const u8 *); + +int +curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { + limb bp[10], x[10], z[11], zmone[10]; + uint8_t e[32]; + int i; + + for (i = 0; i < 32; ++i) e[i] = secret[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fexpand(bp, basepoint); + cmult(x, z, e, bp); + crecip(zmone, z); + fmul(z, x, zmone); + freduce_coefficients(z); + fcontract(mypublic, z); + return 0; +} diff --git a/src/or/eventdns.c b/src/ext/eventdns.c index 768693aba6..66280cccdb 100644 --- a/src/or/eventdns.c +++ b/src/ext/eventdns.c @@ -130,7 +130,7 @@ typedef int socklen_t; #define mm_realloc(x,y) tor_realloc((x),(y)) #define mm_free(x) tor_free(x) #define mm_strdup(x) tor_strdup(x) -#define _mm_free(x) _tor_free(x) +#define _mm_free(x) tor_free_(x) #undef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) @@ -368,7 +368,11 @@ error_is_eagain(int err) #define CLOSE_SOCKET(x) closesocket(x) #else #define last_error(sock) (errno) +#if EAGAIN != EWOULDBLOCK +#define error_is_eagain(err) ((err) == EAGAIN || (err) == EWOULDBLOCK) +#else #define error_is_eagain(err) ((err) == EAGAIN) +#endif #define CLOSE_SOCKET(x) close(x) #endif @@ -423,9 +427,9 @@ evdns_set_log_fn(evdns_debug_log_fn_type fn) #define EVDNS_LOG_CHECK #endif -static void _evdns_log(int warn, const char *fmt, ...) EVDNS_LOG_CHECK; +static void evdns_log(int warn, const char *fmt, ...) EVDNS_LOG_CHECK; static void -_evdns_log(int warn, const char *fmt, ...) +evdns_log(int warn, const char *fmt, ...) { va_list args; static char buf[512]; @@ -442,8 +446,6 @@ _evdns_log(int warn, const char *fmt, ...) va_end(args); } -#define log _evdns_log - static int sockaddr_eq(const struct sockaddr *sa1, const struct sockaddr *sa2, int include_port) @@ -530,7 +532,7 @@ nameserver_probe_failed(struct nameserver *const ns) { ns->failed_times++; if (add_timeout_event(ns, (struct timeval *) timeout) < 0) { - log(EVDNS_LOG_WARN, + evdns_log(EVDNS_LOG_WARN, "Error from libevent when adding timer event for %s", debug_ntop((struct sockaddr *)&ns->address)); /* ???? Do more? */ @@ -546,19 +548,19 @@ nameserver_failed(struct nameserver *const ns, const char *msg) { /* then don't do anything */ if (!ns->state) return; - log(EVDNS_LOG_WARN, "Nameserver %s has failed: %s", + evdns_log(EVDNS_LOG_WARN, "Nameserver %s has failed: %s", debug_ntop((struct sockaddr *)&ns->address), msg); global_good_nameservers--; assert(global_good_nameservers >= 0); if (global_good_nameservers == 0) { - log(EVDNS_LOG_WARN, "All nameservers have failed"); + evdns_log(EVDNS_LOG_WARN, "All nameservers have failed"); } ns->state = 0; ns->failed_times = 1; if (add_timeout_event(ns, (struct timeval *) &global_nameserver_timeouts[0]) < 0) { - log(EVDNS_LOG_WARN, + evdns_log(EVDNS_LOG_WARN, "Error from libevent when adding timer event for %s", debug_ntop((struct sockaddr *)&ns->address)); /* ???? Do more? */ @@ -589,7 +591,7 @@ nameserver_failed(struct nameserver *const ns, const char *msg) { static void nameserver_up(struct nameserver *const ns) { if (ns->state) return; - log(EVDNS_LOG_WARN, "Nameserver %s is back up", + evdns_log(EVDNS_LOG_WARN, "Nameserver %s is back up", debug_ntop((struct sockaddr *)&ns->address)); del_timeout_event(ns); ns->state = 1; @@ -620,7 +622,7 @@ request_finished(struct evdns_request *const req, struct evdns_request **head) { } } - log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx", + evdns_log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx", (unsigned long) req); del_timeout_event(req); @@ -772,7 +774,7 @@ reply_handle(struct evdns_request *const req, u16 flags, u32 ttl, struct reply * * confusing." Treat this as a timeout, not a failure. */ /*XXXX refactor the parts of */ - log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver %s; " + evdns_log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver %s; " "will allow the request to time out.", debug_ntop((struct sockaddr *)&req->ns->address)); break; @@ -1264,7 +1266,7 @@ nameserver_read(struct nameserver *ns) { } /* XXX Match port too? */ if (!sockaddr_eq(sa, (struct sockaddr*)&ns->address, 0)) { - log(EVDNS_LOG_WARN, + evdns_log(EVDNS_LOG_WARN, "Address mismatch on received DNS packet. Address was %s", debug_ntop(sa)); return; @@ -1290,7 +1292,7 @@ server_port_read(struct evdns_server_port *s) { if (r < 0) { int err = last_error(s->socket); if (error_is_eagain(err)) return; - log(EVDNS_LOG_WARN, "Error %s (%d) while reading request.", + evdns_log(EVDNS_LOG_WARN, "Error %s (%d) while reading request.", tor_socket_strerror(err), err); return; } @@ -1310,7 +1312,7 @@ server_port_flush(struct evdns_server_port *port) int err = last_error(port->socket); if (error_is_eagain(err)) return; - log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", tor_socket_strerror(err), err); + evdns_log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", tor_socket_strerror(err), err); } if (server_request_free(req)) { /* we released the last reference to req->port. */ @@ -1327,7 +1329,7 @@ server_port_flush(struct evdns_server_port *port) event_set(&port->event, port->socket, EV_READ | EV_PERSIST, server_port_ready_callback, port); if (event_add(&port->event, NULL) < 0) { - log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server."); + evdns_log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server."); /* ???? Do more? */ } } @@ -1345,7 +1347,7 @@ nameserver_write_waiting(struct nameserver *ns, char waiting) { event_set(&ns->event, ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST, nameserver_ready_callback, ns); if (event_add(&ns->event, NULL) < 0) { - log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s", + evdns_log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s", debug_ntop((struct sockaddr *)&ns->address)); /* ???? Do more? */ } @@ -1855,7 +1857,7 @@ evdns_server_request_respond(struct evdns_server_request *_req, int err) event_set(&port->event, port->socket, (port->closing?0:EV_READ) | EV_WRITE | EV_PERSIST, server_port_ready_callback, port); if (event_add(&port->event, NULL) < 0) { - log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server"); + evdns_log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server"); } } @@ -1991,7 +1993,7 @@ evdns_request_timeout_callback(int fd, short events, void *arg) { (void) fd; (void) events; - log(EVDNS_LOG_DEBUG, "Request %lx timed out", (unsigned long) arg); + evdns_log(EVDNS_LOG_DEBUG, "Request %lx timed out", (unsigned long) arg); req->ns->timedout++; if (req->ns->timedout > global_max_nameserver_timeout) { @@ -2070,11 +2072,11 @@ evdns_request_transmit(struct evdns_request *req) { * and make us retransmit the request anyway. */ default: /* transmitted; we need to check for timeout. */ - log(EVDNS_LOG_DEBUG, + evdns_log(EVDNS_LOG_DEBUG, "Setting timeout for request %lx", (unsigned long) req); if (add_timeout_event(req, &global_timeout) < 0) { - log(EVDNS_LOG_WARN, + evdns_log(EVDNS_LOG_WARN, "Error from libevent when adding timer for request %lx", (unsigned long) req); /* ???? Do more? */ @@ -2122,7 +2124,7 @@ nameserver_send_probe(struct nameserver *const ns) { addr = mm_malloc(sizeof(struct sockaddr_storage)); memcpy(addr, &ns->address, sizeof(struct sockaddr_storage)); - log(EVDNS_LOG_DEBUG, "Sending probe to %s", debug_ntop((struct sockaddr *)&ns->address)); + evdns_log(EVDNS_LOG_DEBUG, "Sending probe to %s", debug_ntop((struct sockaddr *)&ns->address)); req = request_new(TYPE_A, "www.google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_callback, addr); if (!req) { @@ -2278,14 +2280,14 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, if (server) { do { if (sockaddr_eq(address, (struct sockaddr *)&server->address, 1)) { - log(EVDNS_LOG_DEBUG, "Duplicate nameserver."); + evdns_log(EVDNS_LOG_DEBUG, "Duplicate nameserver."); return 3; } server = server->next; } while (server != started_at); } if (addrlen > (int)sizeof(ns->address)) { - log(EVDNS_LOG_DEBUG, "Addrlen %d too long.", (int)addrlen); + evdns_log(EVDNS_LOG_DEBUG, "Addrlen %d too long.", (int)addrlen); return 2; } @@ -2304,21 +2306,26 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, ioctlsocket(ns->socket, FIONBIO, &nonblocking); } #else - fcntl(ns->socket, F_SETFL, O_NONBLOCK); + if (fcntl(ns->socket, F_SETFL, O_NONBLOCK) == -1) { + evdns_log(EVDNS_LOG_WARN, "Error %s (%d) while settings file status flags.", + tor_socket_strerror(errno), errno); + err = 2; + goto out2; + } #endif 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."); + evdns_log(EVDNS_LOG_DEBUG, "Couldn't bind to outgoing address."); err = 2; goto out2; } } if (connect(ns->socket, address, addrlen) != 0) { - log(EVDNS_LOG_DEBUG, "Couldn't open socket to nameserver."); + evdns_log(EVDNS_LOG_DEBUG, "Couldn't open socket to nameserver."); err = 2; goto out2; } @@ -2327,12 +2334,12 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, ns->state = 1; event_set(&ns->event, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns); if (event_add(&ns->event, NULL) < 0) { - log(EVDNS_LOG_DEBUG, "Couldn't add event for nameserver."); + evdns_log(EVDNS_LOG_DEBUG, "Couldn't add event for nameserver."); err = 2; goto out2; } - log(EVDNS_LOG_DEBUG, "Added nameserver %s", debug_ntop(address)); + evdns_log(EVDNS_LOG_DEBUG, "Added nameserver %s", debug_ntop(address)); /* insert this nameserver into the list of them */ if (!server_head) { @@ -2356,7 +2363,7 @@ out2: out1: CLEAR(ns); mm_free(ns); - log(EVDNS_LOG_WARN, "Unable to add nameserver %s: error %d", debug_ntop(address), err); + evdns_log(EVDNS_LOG_WARN, "Unable to add nameserver %s: error %d", debug_ntop(address), err); return err; } @@ -2389,18 +2396,18 @@ evdns_nameserver_ip_add(const char *ip_as_string) { * ipv4 */ - log(EVDNS_LOG_DEBUG, "Trying to add nameserver <%s>", ip_as_string); + evdns_log(EVDNS_LOG_DEBUG, "Trying to add nameserver <%s>", ip_as_string); cp = strchr(ip_as_string, ':'); if (*ip_as_string == '[') { size_t len; if (!(cp = strchr(ip_as_string, ']'))) { - log(EVDNS_LOG_DEBUG, "Nameserver missing closing ]"); + evdns_log(EVDNS_LOG_DEBUG, "Nameserver missing closing ]"); return 4; } len = cp-(ip_as_string + 1); if (len > sizeof(buf)-1) { - log(EVDNS_LOG_DEBUG, "[Nameserver] does not fit in buffer."); + evdns_log(EVDNS_LOG_DEBUG, "[Nameserver] does not fit in buffer."); return 4; } memcpy(buf, ip_as_string+1, len); @@ -2418,7 +2425,7 @@ evdns_nameserver_ip_add(const char *ip_as_string) { } else if (cp) { is_ipv6 = 0; if (cp - ip_as_string > (int)sizeof(buf)-1) { - log(EVDNS_LOG_DEBUG, "Nameserver does not fit in buffer."); + evdns_log(EVDNS_LOG_DEBUG, "Nameserver does not fit in buffer."); return 4; } memcpy(buf, ip_as_string, cp-ip_as_string); @@ -2436,7 +2443,7 @@ evdns_nameserver_ip_add(const char *ip_as_string) { } else { port = strtoint(port_part); if (port <= 0 || port > 65535) { - log(EVDNS_LOG_DEBUG, "Nameserver port <%s> out of range", + evdns_log(EVDNS_LOG_DEBUG, "Nameserver port <%s> out of range", port_part); return 4; } @@ -2453,7 +2460,7 @@ evdns_nameserver_ip_add(const char *ip_as_string) { sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(port); if (1 != tor_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr)) { - log(EVDNS_LOG_DEBUG, "inet_pton(%s) failed", addr_part); + evdns_log(EVDNS_LOG_DEBUG, "inet_pton(%s) failed", addr_part); return 4; } return _evdns_nameserver_add_impl((struct sockaddr*)&sin6, @@ -2467,7 +2474,7 @@ evdns_nameserver_ip_add(const char *ip_as_string) { sin.sin_family = AF_INET; sin.sin_port = htons(port); if (!inet_aton(addr_part, &sin.sin_addr)) { - log(EVDNS_LOG_DEBUG, "inet_pton(%s) failed", addr_part); + evdns_log(EVDNS_LOG_DEBUG, "inet_pton(%s) failed", addr_part); return 4; } return _evdns_nameserver_add_impl((struct sockaddr*)&sin, @@ -2590,7 +2597,7 @@ request_submit(struct evdns_request *const req) { /* exported function */ int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr) { - log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); + evdns_log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); if (flags & DNS_QUERY_NO_SEARCH) { struct evdns_request *const req = request_new(TYPE_A, name, flags, callback, ptr); @@ -2606,7 +2613,7 @@ int evdns_resolve_ipv4(const char *name, int flags, /* exported function */ int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr) { - log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); + evdns_log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); if (flags & DNS_QUERY_NO_SEARCH) { struct evdns_request *const req = request_new(TYPE_AAAA, name, flags, callback, ptr); @@ -2630,7 +2637,7 @@ int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_ty (int)(u8)((a>>8 )&0xff), (int)(u8)((a>>16)&0xff), (int)(u8)((a>>24)&0xff)); - log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); + evdns_log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); req = request_new(TYPE_PTR, buf, flags, callback, ptr); if (!req) return 1; request_submit(req); @@ -2654,7 +2661,7 @@ int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callb } assert(cp + strlen("ip6.arpa") < buf+sizeof(buf)); memcpy(cp, "ip6.arpa", strlen("ip6.arpa")+1); - log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); + evdns_log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); req = request_new(TYPE_PTR, buf, flags, callback, ptr); if (!req) return 1; request_submit(req); @@ -2870,7 +2877,7 @@ search_try_next(struct evdns_request *const req) { if (string_num_dots(req->search_origname) < req->search_state->ndots) { /* yep, we need to try it raw */ struct evdns_request *const newreq = request_new(req->request_type, req->search_origname, req->search_flags, req->user_callback, req->user_pointer); - log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", req->search_origname); + evdns_log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", req->search_origname); if (newreq) { request_submit(newreq); return 0; @@ -2881,7 +2888,7 @@ search_try_next(struct evdns_request *const req) { new_name = search_make_new(req->search_state, req->search_index, req->search_origname); if (!new_name) return 1; - log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, req->search_index); + evdns_log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, req->search_index); newreq = request_new(req->request_type, new_name, req->search_flags, req->user_callback, req->user_pointer); mm_free(new_name); if (!newreq) return 1; @@ -2951,7 +2958,7 @@ evdns_set_option(const char *option, const char *val, int flags) const int ndots = strtoint(val); if (ndots == -1) return -1; if (!(flags & DNS_OPTION_SEARCH)) return 0; - log(EVDNS_LOG_DEBUG, "Setting ndots to %d", ndots); + evdns_log(EVDNS_LOG_DEBUG, "Setting ndots to %d", ndots); if (!global_search_state) global_search_state = search_state_new(); if (!global_search_state) return -1; global_search_state->ndots = ndots; @@ -2959,20 +2966,20 @@ evdns_set_option(const char *option, const char *val, int flags) const int timeout = strtoint(val); if (timeout == -1) return -1; if (!(flags & DNS_OPTION_MISC)) return 0; - log(EVDNS_LOG_DEBUG, "Setting timeout to %d", timeout); + evdns_log(EVDNS_LOG_DEBUG, "Setting timeout to %d", timeout); global_timeout.tv_sec = timeout; } else if (!strncmp(option, "max-timeouts:", 12)) { const int maxtimeout = strtoint_clipped(val, 1, 255); if (maxtimeout == -1) return -1; if (!(flags & DNS_OPTION_MISC)) return 0; - log(EVDNS_LOG_DEBUG, "Setting maximum allowed timeouts to %d", + evdns_log(EVDNS_LOG_DEBUG, "Setting maximum allowed timeouts to %d", maxtimeout); global_max_nameserver_timeout = maxtimeout; } else if (!strncmp(option, "max-inflight:", 13)) { const int maxinflight = strtoint_clipped(val, 1, 65000); if (maxinflight == -1) return -1; if (!(flags & DNS_OPTION_MISC)) return 0; - log(EVDNS_LOG_DEBUG, "Setting maximum inflight requests to %d", + evdns_log(EVDNS_LOG_DEBUG, "Setting maximum inflight requests to %d", maxinflight); global_max_requests_inflight = maxinflight; } else if (!strncmp(option, "attempts:", 9)) { @@ -2980,12 +2987,12 @@ evdns_set_option(const char *option, const char *val, int flags) if (retries == -1) return -1; if (retries > 255) retries = 255; if (!(flags & DNS_OPTION_MISC)) return 0; - log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries); + evdns_log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries); global_max_retransmits = retries; } else if (!strncmp(option, "randomize-case:", 15)) { int randcase = strtoint(val); if (!(flags & DNS_OPTION_MISC)) return 0; - log(EVDNS_LOG_DEBUG, "Setting randomize_case to %d", randcase); + evdns_log(EVDNS_LOG_DEBUG, "Setting randomize_case to %d", randcase); global_randomize_case = randcase; } return 0; @@ -3043,7 +3050,7 @@ evdns_resolv_conf_parse(int flags, const char *const filename) { char *start; int err = 0; - log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename); + evdns_log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename); fd = tor_open_cloexec(filename, O_RDONLY, 0); if (fd < 0) { @@ -3142,13 +3149,13 @@ load_nameservers_with_getnetworkparams(void) GetNetworkParams_fn_t fn; if (!(handle = load_windows_system_library(TEXT("iphlpapi.dll")))) { - log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll"); + evdns_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, TEXT("GetNetworkParams")))) { - log(EVDNS_LOG_WARN, "Could not get address of function."); + evdns_log(EVDNS_LOG_WARN, "Could not get address of function."); /* same as above */ status = -1; goto done; @@ -3169,7 +3176,7 @@ load_nameservers_with_getnetworkparams(void) fixed = buf; r = fn(fixed, &size); if (r != ERROR_SUCCESS) { - log(EVDNS_LOG_DEBUG, "fn() failed."); + evdns_log(EVDNS_LOG_DEBUG, "fn() failed."); status = -1; goto done; } @@ -3181,12 +3188,12 @@ load_nameservers_with_getnetworkparams(void) while (ns) { r = evdns_nameserver_ip_add_line(ns->IpAddress.String); if (r) { - log(EVDNS_LOG_DEBUG,"Could not add nameserver %s to list, " + evdns_log(EVDNS_LOG_DEBUG,"Could not add nameserver %s to list, " "error: %d; status: %d", (ns->IpAddress.String),(int)GetLastError(), r); status = r; } else { - log(EVDNS_LOG_DEBUG,"Successfully added %s as nameserver",ns->IpAddress.String); + evdns_log(EVDNS_LOG_DEBUG,"Successfully added %s as nameserver",ns->IpAddress.String); added_any++; } @@ -3194,7 +3201,7 @@ load_nameservers_with_getnetworkparams(void) } if (!added_any) { - log(EVDNS_LOG_DEBUG, "No nameservers added."); + evdns_log(EVDNS_LOG_DEBUG, "No nameservers added."); if (status == 0) status = -1; } else { @@ -3250,10 +3257,10 @@ load_nameservers_from_registry(void) #define TRY(k, name) \ if (!found && config_nameserver_from_reg_key(k,TEXT(name)) == 0) { \ - log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ + evdns_log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ found = 1; \ } else if (!found) { \ - log(EVDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \ + evdns_log(EVDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \ #k,#name); \ } @@ -3262,14 +3269,14 @@ load_nameservers_from_registry(void) if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, &nt_key) != ERROR_SUCCESS) { - log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError()); + evdns_log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError()); return -1; } r = RegOpenKeyEx(nt_key, TEXT("Interfaces"), 0, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &interfaces_key); if (r != ERROR_SUCCESS) { - log(EVDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError()); + evdns_log(EVDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError()); return -1; } TRY(nt_key, "NameServer"); @@ -3282,7 +3289,7 @@ load_nameservers_from_registry(void) HKEY win_key = 0; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0, KEY_READ, &win_key) != ERROR_SUCCESS) { - log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError()); + evdns_log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError()); return -1; } TRY(win_key, "NameServer"); @@ -3290,7 +3297,7 @@ load_nameservers_from_registry(void) } if (found == 0) { - log(EVDNS_LOG_WARN,"Didn't find any nameservers."); + evdns_log(EVDNS_LOG_WARN,"Didn't find any nameservers."); } return found ? 0 : -1; diff --git a/src/or/eventdns.h b/src/ext/eventdns.h index 1c130b2a12..ad8c100dd6 100644 --- a/src/or/eventdns.h +++ b/src/ext/eventdns.h @@ -209,8 +209,8 @@ * with the next probe. */ -#ifndef _TOR_EVENTDNS_H -#define _TOR_EVENTDNS_H +#ifndef TOR_EVENTDNS_H +#define TOR_EVENTDNS_H /* Error codes 0-5 are as described in RFC 1035. */ #define DNS_ERR_NONE 0 diff --git a/src/common/ht.h b/src/ext/ht.h index 25156c4165..62c458ad0e 100644 --- a/src/common/ht.h +++ b/src/ext/ht.h @@ -1,12 +1,12 @@ /* Copyright (c) 2002, Christopher Clark. * Copyright (c) 2005-2006, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See license at end. */ /* Based on ideas by Christopher Clark and interfaces from Niels Provos. */ -#ifndef _TOR_HT_H -#define _TOR_HT_H +#ifndef HT_H_INCLUDED_ +#define HT_H_INCLUDED_ #define HT_HEAD(name, type) \ struct name { \ @@ -168,7 +168,7 @@ ht_string_hash(const char *s) } \ /* Insert the element 'elm' into the table 'head'. Do not call this \ * function if the table might already contain a matching element. */ \ - static INLINE void \ + ATTR_UNUSED static INLINE void \ name##_HT_INSERT(struct name *head, struct type *elm) \ { \ struct type **p; \ @@ -183,7 +183,7 @@ ht_string_hash(const char *s) /* Insert the element 'elm' into the table 'head'. If there already \ * a matching element in the table, replace that element and return \ * it. */ \ - static INLINE struct type * \ + ATTR_UNUSED static INLINE struct type * \ name##_HT_REPLACE(struct name *head, struct type *elm) \ { \ struct type **p, *r; \ @@ -204,7 +204,7 @@ ht_string_hash(const char *s) } \ /* Remove any element matching 'elm' from the table 'head'. If such \ * an element is found, return it; otherwise return NULL. */ \ - static INLINE struct type * \ + ATTR_UNUSED static INLINE struct type * \ name##_HT_REMOVE(struct name *head, struct type *elm) \ { \ struct type **p, *r; \ @@ -222,11 +222,11 @@ ht_string_hash(const char *s) * using 'data' as its second argument. If the function returns \ * nonzero, remove the most recently examined element before invoking \ * the function again. */ \ - static INLINE void \ + ATTR_UNUSED static INLINE void \ name##_HT_FOREACH_FN(struct name *head, \ int (*fn)(struct type *, void *), \ void *data) \ - { \ +{ \ unsigned idx; \ struct type **p, **nextp, *next; \ if (!head->hth_table) \ @@ -248,7 +248,7 @@ ht_string_hash(const char *s) /* Return a pointer to the first element in the table 'head', under \ * an arbitrary order. This order is stable under remove operations, \ * but not under others. If the table is empty, return NULL. */ \ - static INLINE struct type ** \ + ATTR_UNUSED static INLINE struct type ** \ name##_HT_START(struct name *head) \ { \ unsigned b = 0; \ @@ -264,7 +264,7 @@ ht_string_hash(const char *s) * NULL. If 'elm' is to be removed from the table, you must call \ * this function for the next value before you remove it. \ */ \ - static INLINE struct type ** \ + ATTR_UNUSED static INLINE struct type ** \ name##_HT_NEXT(struct name *head, struct type **elm) \ { \ if ((*elm)->field.hte_next) { \ @@ -280,7 +280,7 @@ ht_string_hash(const char *s) return NULL; \ } \ } \ - static INLINE struct type ** \ + ATTR_UNUSED static INLINE struct type ** \ name##_HT_NEXT_RMV(struct name *head, struct type **elm) \ { \ unsigned h = HT_ELT_HASH_(*elm, field, hashfn); \ diff --git a/src/ext/include.am b/src/ext/include.am new file mode 100644 index 0000000000..ea7e58e79e --- /dev/null +++ b/src/ext/include.am @@ -0,0 +1,17 @@ + +AM_CPPFLAGS += -I$(srcdir)/src/ext -Isrc/ext + +EXTRA_DIST += src/ext/README + +EXTHEADERS = \ + src/ext/ht.h \ + src/ext/eventdns.h \ + src/ext/tinytest.h \ + src/ext/strlcat.c \ + src/ext/strlcpy.c \ + src/ext/tinytest_macros.h \ + src/ext/tor_queue.h + +noinst_HEADERS+= $(EXTHEADERS) + + diff --git a/src/common/strlcat.c b/src/ext/strlcat.c index 316733bccc..316733bccc 100644 --- a/src/common/strlcat.c +++ b/src/ext/strlcat.c diff --git a/src/common/strlcpy.c b/src/ext/strlcpy.c index 9fc47903a1..9fc47903a1 100644 --- a/src/common/strlcpy.c +++ b/src/ext/strlcpy.c diff --git a/src/test/tinytest.c b/src/ext/tinytest.c index 4d9afacce4..4d9afacce4 100644 --- a/src/test/tinytest.c +++ b/src/ext/tinytest.c diff --git a/src/test/tinytest.h b/src/ext/tinytest.h index bcac9f079c..bcac9f079c 100644 --- a/src/test/tinytest.h +++ b/src/ext/tinytest.h diff --git a/src/test/tinytest_demo.c b/src/ext/tinytest_demo.c index be95ce4c1d..be95ce4c1d 100644 --- a/src/test/tinytest_demo.c +++ b/src/ext/tinytest_demo.c diff --git a/src/test/tinytest_macros.h b/src/ext/tinytest_macros.h index 9ff69b1d50..9ff69b1d50 100644 --- a/src/test/tinytest_macros.h +++ b/src/ext/tinytest_macros.h diff --git a/src/ext/tor_queue.h b/src/ext/tor_queue.h new file mode 100644 index 0000000000..f05e48c18e --- /dev/null +++ b/src/ext/tor_queue.h @@ -0,0 +1,568 @@ +/* $OpenBSD: queue.h,v 1.36 2012/04/11 13:29:14 naddy Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef TOR_QUEUE_H_ +#define TOR_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) +#define TOR_Q_INVALIDATE_(a) (a) = ((void *)-1) +#else +#define TOR_Q_INVALIDATE_(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define TOR_SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define TOR_SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define TOR_SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define TOR_SLIST_FIRST(head) ((head)->slh_first) +#define TOR_SLIST_END(head) NULL +#define TOR_SLIST_EMPTY(head) (SLIST_FIRST(head) == TOR_SLIST_END(head)) +#define TOR_SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define TOR_SLIST_FOREACH(var, head, field) \ + for((var) = TOR_SLIST_FIRST(head); \ + (var) != TOR_SLIST_END(head); \ + (var) = TOR_SLIST_NEXT(var, field)) + +#define TOR_SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_SLIST_FIRST(head); \ + (var) && ((tvar) = TOR_SLIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define TOR_SLIST_INIT(head) { \ + TOR_SLIST_FIRST(head) = TOR_SLIST_END(head); \ +} + +#define TOR_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define TOR_SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define TOR_SLIST_REMOVE_AFTER(elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define TOR_SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define TOR_SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + TOR_SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + TOR_Q_INVALIDATE_((elm)->field.sle_next); \ + } \ +} while (0) + +/* + * List definitions. + */ +#define TOR_LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define TOR_LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define TOR_LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define TOR_LIST_FIRST(head) ((head)->lh_first) +#define TOR_LIST_END(head) NULL +#define TOR_LIST_EMPTY(head) (TOR_LIST_FIRST(head) == TOR_LIST_END(head)) +#define TOR_LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define TOR_LIST_FOREACH(var, head, field) \ + for((var) = TOR_LIST_FIRST(head); \ + (var)!= TOR_LIST_END(head); \ + (var) = TOR_LIST_NEXT(var, field)) + +#define TOR_LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_LIST_FIRST(head); \ + (var) && ((tvar) = TOR_LIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * List functions. + */ +#define TOR_LIST_INIT(head) do { \ + TOR_LIST_FIRST(head) = TOR_LIST_END(head); \ +} while (0) + +#define TOR_LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define TOR_LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define TOR_LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define TOR_LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + TOR_Q_INVALIDATE_((elm)->field.le_prev); \ + TOR_Q_INVALIDATE_((elm)->field.le_next); \ +} while (0) + +#define TOR_LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + TOR_Q_INVALIDATE_((elm)->field.le_prev); \ + TOR_Q_INVALIDATE_((elm)->field.le_next); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define TOR_SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define TOR_SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define TOR_SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define TOR_SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define TOR_SIMPLEQ_END(head) NULL +#define TOR_SIMPLEQ_EMPTY(head) (TOR_SIMPLEQ_FIRST(head) == TOR_SIMPLEQ_END(head)) +#define TOR_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define TOR_SIMPLEQ_FOREACH(var, head, field) \ + for((var) = TOR_SIMPLEQ_FIRST(head); \ + (var) != TOR_SIMPLEQ_END(head); \ + (var) = TOR_SIMPLEQ_NEXT(var, field)) + +#define TOR_SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = TOR_SIMPLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Simple queue functions. + */ +#define TOR_SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define TOR_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define TOR_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define TOR_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define TOR_SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define TOR_SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define TOR_TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TOR_TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TOR_TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TOR_TAILQ_FIRST(head) ((head)->tqh_first) +#define TOR_TAILQ_END(head) NULL +#define TOR_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TOR_TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TOR_TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TOR_TAILQ_EMPTY(head) \ + (TOR_TAILQ_FIRST(head) == TOR_TAILQ_END(head)) + +#define TOR_TAILQ_FOREACH(var, head, field) \ + for((var) = TOR_TAILQ_FIRST(head); \ + (var) != TOR_TAILQ_END(head); \ + (var) = TOR_TAILQ_NEXT(var, field)) + +#define TOR_TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_TAILQ_FIRST(head); \ + (var) != TOR_TAILQ_END(head) && \ + ((tvar) = TOR_TAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + + +#define TOR_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TOR_TAILQ_LAST(head, headname); \ + (var) != TOR_TAILQ_END(head); \ + (var) = TOR_TAILQ_PREV(var, headname, field)) + +#define TOR_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TOR_TAILQ_LAST(head, headname); \ + (var) != TOR_TAILQ_END(head) && \ + ((tvar) = TOR_TAILQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Tail queue functions. + */ +#define TOR_TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TOR_TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TOR_TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TOR_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TOR_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TOR_TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + TOR_Q_INVALIDATE_((elm)->field.tqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.tqe_next); \ +} while (0) + +#define TOR_TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + TOR_Q_INVALIDATE_((elm)->field.tqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.tqe_next); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define TOR_CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define TOR_CIRCLEQ_HEAD_INITIALIZER(head) \ + { TOR_CIRCLEQ_END(&head), TOR_CIRCLEQ_END(&head) } + +#define TOR_CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define TOR_CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define TOR_CIRCLEQ_LAST(head) ((head)->cqh_last) +#define TOR_CIRCLEQ_END(head) ((void *)(head)) +#define TOR_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define TOR_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define TOR_CIRCLEQ_EMPTY(head) \ + (TOR_CIRCLEQ_FIRST(head) == TOR_CIRCLEQ_END(head)) + +#define TOR_CIRCLEQ_FOREACH(var, head, field) \ + for((var) = TOR_CIRCLEQ_FIRST(head); \ + (var) != TOR_CIRCLEQ_END(head); \ + (var) = TOR_CIRCLEQ_NEXT(var, field)) + +#define TOR_CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_CIRCLEQ_FIRST(head); \ + (var) != TOR_CIRCLEQ_END(head) && \ + ((tvar) = TOR_CIRCLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +#define TOR_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = TOR_CIRCLEQ_LAST(head); \ + (var) != TOR_CIRCLEQ_END(head); \ + (var) = TOR_CIRCLEQ_PREV(var, field)) + +#define TOR_CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TOR_CIRCLEQ_LAST(head, headname); \ + (var) != TOR_CIRCLEQ_END(head) && \ + ((tvar) = TOR_CIRCLEQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Circular queue functions. + */ +#define TOR_CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = TOR_CIRCLEQ_END(head); \ + (head)->cqh_last = TOR_CIRCLEQ_END(head); \ +} while (0) + +#define TOR_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == TOR_CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define TOR_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == TOR_CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define TOR_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = TOR_CIRCLEQ_END(head); \ + if ((head)->cqh_last == TOR_CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define TOR_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = TOR_CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == TOR_CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define TOR_CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == TOR_CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == TOR_CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ + TOR_Q_INVALIDATE_((elm)->field.cqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.cqe_next); \ +} while (0) + +#define TOR_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + TOR_CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + TOR_CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ + TOR_Q_INVALIDATE_((elm)->field.cqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.cqe_next); \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/src/ext/tor_queue.txt b/src/ext/tor_queue.txt new file mode 100644 index 0000000000..f284e7192f --- /dev/null +++ b/src/ext/tor_queue.txt @@ -0,0 +1,883 @@ +Below follows the manpage for tor_queue.h, as included with OpenBSD's +sys/queue.h. License follows at the end of the file. + +====================================================================== +QUEUE(3) OpenBSD Programmer's Manual QUEUE(3) + +NAME + SLIST_ENTRY, SLIST_HEAD, SLIST_HEAD_INITIALIZER, SLIST_FIRST, SLIST_NEXT, + SLIST_END, SLIST_EMPTY, SLIST_FOREACH, SLIST_FOREACH_SAFE, SLIST_INIT, + SLIST_INSERT_AFTER, SLIST_INSERT_HEAD, SLIST_REMOVE_AFTER, + SLIST_REMOVE_HEAD, SLIST_REMOVE, LIST_ENTRY, LIST_HEAD, + LIST_HEAD_INITIALIZER, LIST_FIRST, LIST_NEXT, LIST_END, LIST_EMPTY, + LIST_FOREACH, LIST_FOREACH_SAFE, LIST_INIT, LIST_INSERT_AFTER, + LIST_INSERT_BEFORE, LIST_INSERT_HEAD, LIST_REMOVE, LIST_REPLACE, + SIMPLEQ_ENTRY, SIMPLEQ_HEAD, SIMPLEQ_HEAD_INITIALIZER, SIMPLEQ_FIRST, + SIMPLEQ_NEXT, SIMPLEQ_END, SIMPLEQ_EMPTY, SIMPLEQ_FOREACH, + SIMPLEQ_FOREACH_SAFE, SIMPLEQ_INIT, SIMPLEQ_INSERT_AFTER, + SIMPLEQ_INSERT_HEAD, SIMPLEQ_INSERT_TAIL, SIMPLEQ_REMOVE_AFTER, + SIMPLEQ_REMOVE_HEAD, TAILQ_ENTRY, TAILQ_HEAD, TAILQ_HEAD_INITIALIZER, + TAILQ_FIRST, TAILQ_NEXT, TAILQ_END, TAILQ_LAST, TAILQ_PREV, TAILQ_EMPTY, + TAILQ_FOREACH, TAILQ_FOREACH_SAFE, TAILQ_FOREACH_REVERSE, + TAILQ_FOREACH_REVERSE_SAFE, TAILQ_INIT, TAILQ_INSERT_AFTER, + TAILQ_INSERT_BEFORE, TAILQ_INSERT_HEAD, TAILQ_INSERT_TAIL, TAILQ_REMOVE, + TAILQ_REPLACE, CIRCLEQ_ENTRY, CIRCLEQ_HEAD, CIRCLEQ_HEAD_INITIALIZER, + CIRCLEQ_FIRST, CIRCLEQ_LAST, CIRCLEQ_END, CIRCLEQ_NEXT, CIRCLEQ_PREV, + CIRCLEQ_EMPTY, CIRCLEQ_FOREACH, CIRCLEQ_FOREACH_SAFE, + CIRCLEQ_FOREACH_REVERSE_SAFE, CIRCLEQ_INIT, CIRCLEQ_INSERT_AFTER, + CIRCLEQ_INSERT_BEFORE, CIRCLEQ_INSERT_HEAD, CIRCLEQ_INSERT_TAIL, + CIRCLEQ_REMOVE, CIRCLEQ_REPLACE - implementations of singly-linked lists, + doubly-linked lists, simple queues, tail queues, and circular queues + +SYNOPSIS + #include <sys/queue.h> + + SLIST_ENTRY(TYPE); + + SLIST_HEAD(HEADNAME, TYPE); + + SLIST_HEAD_INITIALIZER(SLIST_HEAD head); + + struct TYPE * + SLIST_FIRST(SLIST_HEAD *head); + + struct TYPE * + SLIST_NEXT(struct TYPE *listelm, SLIST_ENTRY NAME); + + struct TYPE * + SLIST_END(SLIST_HEAD *head); + + int + SLIST_EMPTY(SLIST_HEAD *head); + + SLIST_FOREACH(VARNAME, SLIST_HEAD *head, SLIST_ENTRY NAME); + + SLIST_FOREACH_SAFE(VARNAME, SLIST_HEAD *head, SLIST_ENTRY + NAME, TEMP_VARNAME); + + void + SLIST_INIT(SLIST_HEAD *head); + + void + SLIST_INSERT_AFTER(struct TYPE *listelm, struct TYPE *elm, SLIST_ENTRY + NAME); + + void + SLIST_INSERT_HEAD(SLIST_HEAD *head, struct TYPE *elm, SLIST_ENTRY NAME); + + void + SLIST_REMOVE_AFTER(struct TYPE *elm, SLIST_ENTRY NAME); + + void + SLIST_REMOVE_HEAD(SLIST_HEAD *head, SLIST_ENTRY NAME); + + void + SLIST_REMOVE(SLIST_HEAD *head, struct TYPE *elm, TYPE, SLIST_ENTRY NAME); + + LIST_ENTRY(TYPE); + + LIST_HEAD(HEADNAME, TYPE); + + LIST_HEAD_INITIALIZER(LIST_HEAD head); + + struct TYPE * + LIST_FIRST(LIST_HEAD *head); + + struct TYPE * + LIST_NEXT(struct TYPE *listelm, LIST_ENTRY NAME); + + struct TYPE * + LIST_END(LIST_HEAD *head); + + int + LIST_EMPTY(LIST_HEAD *head); + + LIST_FOREACH(VARNAME, LIST_HEAD *head, LIST_ENTRY NAME); + + LIST_FOREACH_SAFE(VARNAME, LIST_HEAD *head, LIST_ENTRY + NAME, TEMP_VARNAME); + + void + LIST_INIT(LIST_HEAD *head); + + void + LIST_INSERT_AFTER(struct TYPE *listelm, struct TYPE *elm, LIST_ENTRY + NAME); + + void + LIST_INSERT_BEFORE(struct TYPE *listelm, struct TYPE *elm, LIST_ENTRY + NAME); + + void + LIST_INSERT_HEAD(LIST_HEAD *head, struct TYPE *elm, LIST_ENTRY NAME); + + void + LIST_REMOVE(struct TYPE *elm, LIST_ENTRY NAME); + + void + LIST_REPLACE(struct TYPE *elm, struct TYPE *elm2, LIST_ENTRY NAME); + + SIMPLEQ_ENTRY(TYPE); + + SIMPLEQ_HEAD(HEADNAME, TYPE); + + SIMPLEQ_HEAD_INITIALIZER(SIMPLEQ_HEAD head); + + struct TYPE * + SIMPLEQ_FIRST(SIMPLEQ_HEAD *head); + + struct TYPE * + SIMPLEQ_NEXT(struct TYPE *listelm, SIMPLEQ_ENTRY NAME); + + struct TYPE * + SIMPLEQ_END(SIMPLEQ_HEAD *head); + + int + SIMPLEQ_EMPTY(SIMPLEQ_HEAD *head); + + SIMPLEQ_FOREACH(VARNAME, SIMPLEQ_HEAD *head, SIMPLEQ_ENTRY NAME); + + SIMPLEQ_FOREACH_SAFE(VARNAME, SIMPLEQ_HEAD *head, SIMPLEQ_ENTRY + NAME, TEMP_VARNAME); + + void + SIMPLEQ_INIT(SIMPLEQ_HEAD *head); + + void + SIMPLEQ_INSERT_AFTER(SIMPLEQ_HEAD *head, struct TYPE *listelm, struct + TYPE *elm, SIMPLEQ_ENTRY NAME); + + void + SIMPLEQ_INSERT_HEAD(SIMPLEQ_HEAD *head, struct TYPE *elm, SIMPLEQ_ENTRY + NAME); + + void + SIMPLEQ_INSERT_TAIL(SIMPLEQ_HEAD *head, struct TYPE *elm, SIMPLEQ_ENTRY + NAME); + + void + SIMPLEQ_REMOVE_AFTER(SIMPLEQ_HEAD *head, struct TYPE *elm, SIMPLEQ_ENTRY + NAME); + + void + SIMPLEQ_REMOVE_HEAD(SIMPLEQ_HEAD *head, SIMPLEQ_ENTRY NAME); + + TAILQ_ENTRY(TYPE); + + TAILQ_HEAD(HEADNAME, TYPE); + + TAILQ_HEAD_INITIALIZER(TAILQ_HEAD head); + + struct TYPE * + TAILQ_FIRST(TAILQ_HEAD *head); + + struct TYPE * + TAILQ_NEXT(struct TYPE *listelm, TAILQ_ENTRY NAME); + + struct TYPE * + TAILQ_END(TAILQ_HEAD *head); + + struct TYPE * + TAILQ_LAST(TAILQ_HEAD *head, HEADNAME NAME); + + struct TYPE * + TAILQ_PREV(struct TYPE *listelm, HEADNAME NAME, TAILQ_ENTRY NAME); + + int + TAILQ_EMPTY(TAILQ_HEAD *head); + + TAILQ_FOREACH(VARNAME, TAILQ_HEAD *head, TAILQ_ENTRY NAME); + + TAILQ_FOREACH_SAFE(VARNAME, TAILQ_HEAD *head, TAILQ_ENTRY + NAME, TEMP_VARNAME); + + TAILQ_FOREACH_REVERSE(VARNAME, TAILQ_HEAD *head, HEADNAME, TAILQ_ENTRY + NAME); + + TAILQ_FOREACH_REVERSE_SAFE(VARNAME, TAILQ_HEAD + *head, HEADNAME, TAILQ_ENTRY NAME, TEMP_VARNAME); + + void + TAILQ_INIT(TAILQ_HEAD *head); + + void + TAILQ_INSERT_AFTER(TAILQ_HEAD *head, struct TYPE *listelm, struct TYPE + *elm, TAILQ_ENTRY NAME); + + void + TAILQ_INSERT_BEFORE(struct TYPE *listelm, struct TYPE *elm, TAILQ_ENTRY + NAME); + + void + TAILQ_INSERT_HEAD(TAILQ_HEAD *head, struct TYPE *elm, TAILQ_ENTRY NAME); + + void + TAILQ_INSERT_TAIL(TAILQ_HEAD *head, struct TYPE *elm, TAILQ_ENTRY NAME); + + void + TAILQ_REMOVE(TAILQ_HEAD *head, struct TYPE *elm, TAILQ_ENTRY NAME); + + void + TAILQ_REPLACE(TAILQ_HEAD *head, struct TYPE *elm, struct TYPE + *elm2, TAILQ_ENTRY NAME); + + CIRCLEQ_ENTRY(TYPE); + + CIRCLEQ_HEAD(HEADNAME, TYPE); + + CIRCLEQ_HEAD_INITIALIZER(CIRCLEQ_HEAD head); + + struct TYPE * + CIRCLEQ_FIRST(CIRCLEQ_HEAD *head); + + struct TYPE * + CIRCLEQ_LAST(CIRCLEQ_HEAD *head); + + struct TYPE * + CIRCLEQ_END(CIRCLEQ_HEAD *head); + + struct TYPE * + CIRCLEQ_NEXT(struct TYPE *listelm, CIRCLEQ_ENTRY NAME); + + struct TYPE * + CIRCLEQ_PREV(struct TYPE *listelm, CIRCLEQ_ENTRY NAME); + + int + CIRCLEQ_EMPTY(CIRCLEQ_HEAD *head); + + CIRCLEQ_FOREACH(VARNAME, CIRCLEQ_HEAD *head, CIRCLEQ_ENTRY NAME); + + CIRCLEQ_FOREACH_SAFE(VARNAME, CIRCLEQ_HEAD *head, CIRCLEQ_ENTRY + NAME, TEMP_VARNAME); + + CIRCLEQ_FOREACH_REVERSE(VARNAME, CIRCLEQ_HEAD *head, CIRCLEQ_ENTRY NAME); + + CIRCLEQ_FOREACH_REVERSE_SAFE(VARNAME, CIRCLEQ_HEAD *head, CIRCLEQ_ENTRY + NAME, TEMP_VARNAME); + + void + CIRCLEQ_INIT(CIRCLEQ_HEAD *head); + + void + CIRCLEQ_INSERT_AFTER(CIRCLEQ_HEAD *head, struct TYPE *listelm, struct + TYPE *elm, CIRCLEQ_ENTRY NAME); + + void + CIRCLEQ_INSERT_BEFORE(CIRCLEQ_HEAD *head, struct TYPE *listelm, struct + TYPE *elm, CIRCLEQ_ENTRY NAME); + + void + CIRCLEQ_INSERT_HEAD(CIRCLEQ_HEAD *head, struct TYPE *elm, CIRCLEQ_ENTRY + NAME); + + void + CIRCLEQ_INSERT_TAIL(CIRCLEQ_HEAD *head, struct TYPE *elm, CIRCLEQ_ENTRY + NAME); + + void + CIRCLEQ_REMOVE(CIRCLEQ_HEAD *head, struct TYPE *elm, CIRCLEQ_ENTRY NAME); + + void + CIRCLEQ_REPLACE(CIRCLEQ_HEAD *head, struct TYPE *elm, struct TYPE + *elm2, CIRCLEQ_ENTRY NAME); + +DESCRIPTION + These macros define and operate on five types of data structures: singly- + linked lists, simple queues, lists, tail queues, and circular queues. + All five structures support the following functionality: + + 1. Insertion of a new entry at the head of the list. + 2. Insertion of a new entry after any element in the list. + 3. Removal of an entry from the head of the list. + 4. Forward traversal through the list. + + Singly-linked lists are the simplest of the five data structures and + support only the above functionality. Singly-linked lists are ideal for + applications with large datasets and few or no removals, or for + implementing a LIFO queue. + + Simple queues add the following functionality: + + 1. Entries can be added at the end of a list. + + However: + + 1. All list insertions must specify the head of the list. + 2. Each head entry requires two pointers rather than one. + 3. Code size is about 15% greater and operations run about 20% + slower than singly-linked lists. + + Simple queues are ideal for applications with large datasets and few or + no removals, or for implementing a FIFO queue. + + All doubly linked types of data structures (lists, tail queues, and + circle queues) additionally allow: + + 1. Insertion of a new entry before any element in the list. + 2. Removal of any entry in the list. + + However: + + 1. Each element requires two pointers rather than one. + 2. Code size and execution time of operations (except for + removal) is about twice that of the singly-linked data- + structures. + + Lists are the simplest of the doubly linked data structures and support + only the above functionality over singly-linked lists. + + Tail queues add the following functionality: + + 1. Entries can be added at the end of a list. + 2. They may be traversed backwards, at a cost. + + However: + + 1. All list insertions and removals must specify the head of the + list. + 2. Each head entry requires two pointers rather than one. + 3. Code size is about 15% greater and operations run about 20% + slower than singly-linked lists. + + Circular queues add the following functionality: + + 1. Entries can be added at the end of a list. + 2. They may be traversed backwards, from tail to head. + + However: + + 1. All list insertions and removals must specify the head of the + list. + 2. Each head entry requires two pointers rather than one. + 3. The termination condition for traversal is more complex. + 4. Code size is about 40% greater and operations run about 45% + slower than lists. + + In the macro definitions, TYPE is the name tag of a user defined + structure that must contain a field of type SLIST_ENTRY, LIST_ENTRY, + SIMPLEQ_ENTRY, TAILQ_ENTRY, or CIRCLEQ_ENTRY, named NAME. The argument + HEADNAME is the name tag of a user defined structure that must be + declared using the macros SLIST_HEAD(), LIST_HEAD(), SIMPLEQ_HEAD(), + TAILQ_HEAD(), or CIRCLEQ_HEAD(). See the examples below for further + explanation of how these macros are used. + +SINGLY-LINKED LISTS + A singly-linked list is headed by a structure defined by the SLIST_HEAD() + macro. This structure contains a single pointer to the first element on + the list. The elements are singly linked for minimum space and pointer + manipulation overhead at the expense of O(n) removal for arbitrary + elements. New elements can be added to the list after an existing + element or at the head of the list. A SLIST_HEAD structure is declared + as follows: + + SLIST_HEAD(HEADNAME, TYPE) head; + + where HEADNAME is the name of the structure to be defined, and struct + TYPE is the type of the elements to be linked into the list. A pointer + to the head of the list can later be declared as: + + struct HEADNAME *headp; + + (The names head and headp are user selectable.) + + The HEADNAME facility is often not used, leading to the following bizarre + code: + + SLIST_HEAD(, TYPE) head, *headp; + + The SLIST_ENTRY() macro declares a structure that connects the elements + in the list. + + The SLIST_INIT() macro initializes the list referenced by head. + + The list can also be initialized statically by using the + SLIST_HEAD_INITIALIZER() macro like this: + + SLIST_HEAD(HEADNAME, TYPE) head = SLIST_HEAD_INITIALIZER(head); + + The SLIST_INSERT_HEAD() macro inserts the new element elm at the head of + the list. + + The SLIST_INSERT_AFTER() macro inserts the new element elm after the + element listelm. + + The SLIST_REMOVE_HEAD() macro removes the first element of the list + pointed by head. + + The SLIST_REMOVE_AFTER() macro removes the list element immediately + following elm. + + The SLIST_REMOVE() macro removes the element elm of the list pointed by + head. + + The SLIST_FIRST() and SLIST_NEXT() macros can be used to traverse the + list: + + for (np = SLIST_FIRST(&head); np != NULL; np = SLIST_NEXT(np, NAME)) + + Or, for simplicity, one can use the SLIST_FOREACH() macro: + + SLIST_FOREACH(np, head, NAME) + + The macro SLIST_FOREACH_SAFE() traverses the list referenced by head in a + forward direction, assigning each element in turn to var. However, + unlike SLIST_FOREACH() it is permitted to remove var as well as free it + from within the loop safely without interfering with the traversal. + + The SLIST_EMPTY() macro should be used to check whether a simple list is + empty. + +SINGLY-LINKED LIST EXAMPLE + SLIST_HEAD(listhead, entry) head; + struct entry { + ... + SLIST_ENTRY(entry) entries; /* Simple list. */ + ... + } *n1, *n2, *np; + + SLIST_INIT(&head); /* Initialize simple list. */ + + n1 = malloc(sizeof(struct entry)); /* Insert at the head. */ + SLIST_INSERT_HEAD(&head, n1, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert after. */ + SLIST_INSERT_AFTER(n1, n2, entries); + + SLIST_FOREACH(np, &head, entries) /* Forward traversal. */ + np-> ... + + while (!SLIST_EMPTY(&head)) { /* Delete. */ + n1 = SLIST_FIRST(&head); + SLIST_REMOVE_HEAD(&head, entries); + free(n1); + } + + +LISTS + A list is headed by a structure defined by the LIST_HEAD() macro. This + structure contains a single pointer to the first element on the list. + The elements are doubly linked so that an arbitrary element can be + removed without traversing the list. New elements can be added to the + list after an existing element, before an existing element, or at the + head of the list. A LIST_HEAD structure is declared as follows: + + LIST_HEAD(HEADNAME, TYPE) head; + + where HEADNAME is the name of the structure to be defined, and struct + TYPE is the type of the elements to be linked into the list. A pointer + to the head of the list can later be declared as: + + struct HEADNAME *headp; + + (The names head and headp are user selectable.) + + The HEADNAME facility is often not used, leading to the following bizarre + code: + + LIST_HEAD(, TYPE) head, *headp; + + The LIST_ENTRY() macro declares a structure that connects the elements in + the list. + + The LIST_INIT() macro initializes the list referenced by head. + + The list can also be initialized statically by using the + LIST_HEAD_INITIALIZER() macro like this: + + LIST_HEAD(HEADNAME, TYPE) head = LIST_HEAD_INITIALIZER(head); + + The LIST_INSERT_HEAD() macro inserts the new element elm at the head of + the list. + + The LIST_INSERT_AFTER() macro inserts the new element elm after the + element listelm. + + The LIST_INSERT_BEFORE() macro inserts the new element elm before the + element listelm. + + The LIST_REMOVE() macro removes the element elm from the list. + + The LIST_REPLACE() macro replaces the list element elm with the new + element elm2. + + The LIST_FIRST() and LIST_NEXT() macros can be used to traverse the list: + + for (np = LIST_FIRST(&head); np != NULL; np = LIST_NEXT(np, NAME)) + + Or, for simplicity, one can use the LIST_FOREACH() macro: + + LIST_FOREACH(np, head, NAME) + + The macro LIST_FOREACH_SAFE() traverses the list referenced by head in a + forward direction, assigning each element in turn to var. However, + unlike LIST_FOREACH() it is permitted to remove var as well as free it + from within the loop safely without interfering with the traversal. + + The LIST_EMPTY() macro should be used to check whether a list is empty. + +LIST EXAMPLE + LIST_HEAD(listhead, entry) head; + struct entry { + ... + LIST_ENTRY(entry) entries; /* List. */ + ... + } *n1, *n2, *np; + + LIST_INIT(&head); /* Initialize list. */ + + n1 = malloc(sizeof(struct entry)); /* Insert at the head. */ + LIST_INSERT_HEAD(&head, n1, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert after. */ + LIST_INSERT_AFTER(n1, n2, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert before. */ + LIST_INSERT_BEFORE(n1, n2, entries); + /* Forward traversal. */ + LIST_FOREACH(np, &head, entries) + np-> ... + + while (!LIST_EMPTY(&head)) /* Delete. */ + n1 = LIST_FIRST(&head); + LIST_REMOVE(n1, entries); + free(n1); + } + +SIMPLE QUEUES + A simple queue is headed by a structure defined by the SIMPLEQ_HEAD() + macro. This structure contains a pair of pointers, one to the first + element in the simple queue and the other to the last element in the + simple queue. The elements are singly linked. New elements can be added + to the queue after an existing element, at the head of the queue or at + the tail of the queue. A SIMPLEQ_HEAD structure is declared as follows: + + SIMPLEQ_HEAD(HEADNAME, TYPE) head; + + where HEADNAME is the name of the structure to be defined, and struct + TYPE is the type of the elements to be linked into the queue. A pointer + to the head of the queue can later be declared as: + + struct HEADNAME *headp; + + (The names head and headp are user selectable.) + + The SIMPLEQ_ENTRY() macro declares a structure that connects the elements + in the queue. + + The SIMPLEQ_INIT() macro initializes the queue referenced by head. + + The queue can also be initialized statically by using the + SIMPLEQ_HEAD_INITIALIZER() macro like this: + + SIMPLEQ_HEAD(HEADNAME, TYPE) head = SIMPLEQ_HEAD_INITIALIZER(head); + + The SIMPLEQ_INSERT_AFTER() macro inserts the new element elm after the + element listelm. + + The SIMPLEQ_INSERT_HEAD() macro inserts the new element elm at the head + of the queue. + + The SIMPLEQ_INSERT_TAIL() macro inserts the new element elm at the end of + the queue. + + The SIMPLEQ_REMOVE_AFTER() macro removes the queue element immediately + following elm. + + The SIMPLEQ_REMOVE_HEAD() macro removes the first element from the queue. + + The SIMPLEQ_FIRST() and SIMPLEQ_NEXT() macros can be used to traverse the + queue. The SIMPLEQ_FOREACH() is used for queue traversal: + + SIMPLEQ_FOREACH(np, head, NAME) + + The macro SIMPLEQ_FOREACH_SAFE() traverses the queue referenced by head + in a forward direction, assigning each element in turn to var. However, + unlike SIMPLEQ_FOREACH() it is permitted to remove var as well as free it + from within the loop safely without interfering with the traversal. + + The SIMPLEQ_EMPTY() macro should be used to check whether a list is + empty. + +SIMPLE QUEUE EXAMPLE + SIMPLEQ_HEAD(listhead, entry) head = SIMPLEQ_HEAD_INITIALIZER(head); + struct entry { + ... + SIMPLEQ_ENTRY(entry) entries; /* Simple queue. */ + ... + } *n1, *n2, *np; + + n1 = malloc(sizeof(struct entry)); /* Insert at the head. */ + SIMPLEQ_INSERT_HEAD(&head, n1, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert after. */ + SIMPLEQ_INSERT_AFTER(&head, n1, n2, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert at the tail. */ + SIMPLEQ_INSERT_TAIL(&head, n2, entries); + /* Forward traversal. */ + SIMPLEQ_FOREACH(np, &head, entries) + np-> ... + /* Delete. */ + while (!SIMPLEQ_EMPTY(&head)) { + n1 = SIMPLEQ_FIRST(&head); + SIMPLEQ_REMOVE_HEAD(&head, entries); + free(n1); + } + +TAIL QUEUES + A tail queue is headed by a structure defined by the TAILQ_HEAD() macro. + This structure contains a pair of pointers, one to the first element in + the tail queue and the other to the last element in the tail queue. The + elements are doubly linked so that an arbitrary element can be removed + without traversing the tail queue. New elements can be added to the + queue after an existing element, before an existing element, at the head + of the queue, or at the end of the queue. A TAILQ_HEAD structure is + declared as follows: + + TAILQ_HEAD(HEADNAME, TYPE) head; + + where HEADNAME is the name of the structure to be defined, and struct + TYPE is the type of the elements to be linked into the tail queue. A + pointer to the head of the tail queue can later be declared as: + + struct HEADNAME *headp; + + (The names head and headp are user selectable.) + + The TAILQ_ENTRY() macro declares a structure that connects the elements + in the tail queue. + + The TAILQ_INIT() macro initializes the tail queue referenced by head. + + The tail queue can also be initialized statically by using the + TAILQ_HEAD_INITIALIZER() macro. + + The TAILQ_INSERT_HEAD() macro inserts the new element elm at the head of + the tail queue. + + The TAILQ_INSERT_TAIL() macro inserts the new element elm at the end of + the tail queue. + + The TAILQ_INSERT_AFTER() macro inserts the new element elm after the + element listelm. + + The TAILQ_INSERT_BEFORE() macro inserts the new element elm before the + element listelm. + + The TAILQ_REMOVE() macro removes the element elm from the tail queue. + + The TAILQ_REPLACE() macro replaces the list element elm with the new + element elm2. + + TAILQ_FOREACH() and TAILQ_FOREACH_REVERSE() are used for traversing a + tail queue. TAILQ_FOREACH() starts at the first element and proceeds + towards the last. TAILQ_FOREACH_REVERSE() starts at the last element and + proceeds towards the first. + + TAILQ_FOREACH(np, &head, NAME) + TAILQ_FOREACH_REVERSE(np, &head, HEADNAME, NAME) + + The macros TAILQ_FOREACH_SAFE() and TAILQ_FOREACH_REVERSE_SAFE() traverse + the list referenced by head in a forward or reverse direction + respectively, assigning each element in turn to var. However, unlike + their unsafe counterparts, they permit both the removal of var as well as + freeing it from within the loop safely without interfering with the + traversal. + + The TAILQ_FIRST(), TAILQ_NEXT(), TAILQ_LAST() and TAILQ_PREV() macros can + be used to manually traverse a tail queue or an arbitrary part of one. + + The TAILQ_EMPTY() macro should be used to check whether a tail queue is + empty. + +TAIL QUEUE EXAMPLE + TAILQ_HEAD(tailhead, entry) head; + struct entry { + ... + TAILQ_ENTRY(entry) entries; /* Tail queue. */ + ... + } *n1, *n2, *np; + + TAILQ_INIT(&head); /* Initialize queue. */ + + n1 = malloc(sizeof(struct entry)); /* Insert at the head. */ + TAILQ_INSERT_HEAD(&head, n1, entries); + + n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */ + TAILQ_INSERT_TAIL(&head, n1, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert after. */ + TAILQ_INSERT_AFTER(&head, n1, n2, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert before. */ + TAILQ_INSERT_BEFORE(n1, n2, entries); + /* Forward traversal. */ + TAILQ_FOREACH(np, &head, entries) + np-> ... + /* Manual forward traversal. */ + for (np = n2; np != NULL; np = TAILQ_NEXT(np, entries)) + np-> ... + /* Delete. */ + while ((np = TAILQ_FIRST(&head))) { + TAILQ_REMOVE(&head, np, entries); + free(np); + } + + +CIRCULAR QUEUES + A circular queue is headed by a structure defined by the CIRCLEQ_HEAD() + macro. This structure contains a pair of pointers, one to the first + element in the circular queue and the other to the last element in the + circular queue. The elements are doubly linked so that an arbitrary + element can be removed without traversing the queue. New elements can be + added to the queue after an existing element, before an existing element, + at the head of the queue, or at the end of the queue. A CIRCLEQ_HEAD + structure is declared as follows: + + CIRCLEQ_HEAD(HEADNAME, TYPE) head; + + where HEADNAME is the name of the structure to be defined, and struct + TYPE is the type of the elements to be linked into the circular queue. A + pointer to the head of the circular queue can later be declared as: + + struct HEADNAME *headp; + + (The names head and headp are user selectable.) + + The CIRCLEQ_ENTRY() macro declares a structure that connects the elements + in the circular queue. + + The CIRCLEQ_INIT() macro initializes the circular queue referenced by + head. + + The circular queue can also be initialized statically by using the + CIRCLEQ_HEAD_INITIALIZER() macro. + + The CIRCLEQ_INSERT_HEAD() macro inserts the new element elm at the head + of the circular queue. + + The CIRCLEQ_INSERT_TAIL() macro inserts the new element elm at the end of + the circular queue. + + The CIRCLEQ_INSERT_AFTER() macro inserts the new element elm after the + element listelm. + + The CIRCLEQ_INSERT_BEFORE() macro inserts the new element elm before the + element listelm. + + The CIRCLEQ_REMOVE() macro removes the element elm from the circular + queue. + + The CIRCLEQ_REPLACE() macro replaces the list element elm with the new + element elm2. + + The CIRCLEQ_FIRST(), CIRCLEQ_LAST(), CIRCLEQ_END(), CIRCLEQ_NEXT() and + CIRCLEQ_PREV() macros can be used to traverse a circular queue. The + CIRCLEQ_FOREACH() is used for circular queue forward traversal: + + CIRCLEQ_FOREACH(np, head, NAME) + + The CIRCLEQ_FOREACH_REVERSE() macro acts like CIRCLEQ_FOREACH() but + traverses the circular queue backwards. + + The macros CIRCLEQ_FOREACH_SAFE() and CIRCLEQ_FOREACH_REVERSE_SAFE() + traverse the list referenced by head in a forward or reverse direction + respectively, assigning each element in turn to var. However, unlike + their unsafe counterparts, they permit both the removal of var as well as + freeing it from within the loop safely without interfering with the + traversal. + + The CIRCLEQ_EMPTY() macro should be used to check whether a circular + queue is empty. + +CIRCULAR QUEUE EXAMPLE + CIRCLEQ_HEAD(circleq, entry) head; + struct entry { + ... + CIRCLEQ_ENTRY(entry) entries; /* Circular queue. */ + ... + } *n1, *n2, *np; + + CIRCLEQ_INIT(&head); /* Initialize circular queue. */ + + n1 = malloc(sizeof(struct entry)); /* Insert at the head. */ + CIRCLEQ_INSERT_HEAD(&head, n1, entries); + + n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */ + CIRCLEQ_INSERT_TAIL(&head, n1, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert after. */ + CIRCLEQ_INSERT_AFTER(&head, n1, n2, entries); + + n2 = malloc(sizeof(struct entry)); /* Insert before. */ + CIRCLEQ_INSERT_BEFORE(&head, n1, n2, entries); + /* Forward traversal. */ + CIRCLEQ_FOREACH(np, &head, entries) + np-> ... + /* Reverse traversal. */ + CIRCLEQ_FOREACH_REVERSE(np, &head, entries) + np-> ... + /* Delete. */ + while (!CIRCLEQ_EMPTY(&head)) { + n1 = CIRCLEQ_FIRST(&head); + CIRCLEQ_REMOVE(&head, n1, entries); + free(n1); + } + +NOTES + It is an error to assume the next and previous fields are preserved after + an element has been removed from a list or queue. Using any macro + (except the various forms of insertion) on an element removed from a list + or queue is incorrect. An example of erroneous usage is removing the + same element twice. + + The SLIST_END(), LIST_END(), SIMPLEQ_END() and TAILQ_END() macros are + provided for symmetry with CIRCLEQ_END(). They expand to NULL and don't + serve any useful purpose. + + Trying to free a list in the following way is a common error: + + LIST_FOREACH(var, head, entry) + free(var); + free(head); + + Since var is free'd, the FOREACH macros refer to a pointer that may have + been reallocated already. A similar situation occurs when the current + element is deleted from the list. In cases like these the data + structure's FOREACH_SAFE macros should be used instead. + +HISTORY + The queue functions first appeared in 4.4BSD. + +OpenBSD 5.0 April 11, 2012 OpenBSD 5.0 +====================================================================== +.\" $OpenBSD: queue.3,v 1.56 2012/04/11 13:29:14 naddy Exp $ +.\" $NetBSD: queue.3,v 1.4 1995/07/03 00:25:36 mycroft Exp $ +.\" +.\" Copyright (c) 1993 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. + diff --git a/src/include.am b/src/include.am new file mode 100644 index 0000000000..d0693e25b0 --- /dev/null +++ b/src/include.am @@ -0,0 +1,7 @@ +include src/ext/include.am +include src/common/include.am +include src/or/include.am +include src/test/include.am +include src/tools/include.am +include src/win32/include.am +include src/config/include.am diff --git a/src/or/Makefile.am b/src/or/Makefile.am deleted file mode 100644 index 3cc789a1be..0000000000 --- a/src/or/Makefile.am +++ /dev/null @@ -1,158 +0,0 @@ -bin_PROGRAMS = tor -noinst_LIBRARIES = libtor.a - -if BUILD_NT_SERVICES -tor_platform_source=ntmain.c -else -tor_platform_source= -endif - -EXTRA_DIST=ntmain.c or_sha1.i Makefile.nmake - -if USE_EXTERNAL_EVDNS -evdns_source= -else -evdns_source=eventdns.c -endif - -libtor_a_SOURCES = \ - buffers.c \ - circuitbuild.c \ - circuitlist.c \ - circuituse.c \ - command.c \ - config.c \ - connection.c \ - connection_edge.c \ - connection_or.c \ - control.c \ - cpuworker.c \ - directory.c \ - dirserv.c \ - dirvote.c \ - dns.c \ - dnsserv.c \ - geoip.c \ - hibernate.c \ - main.c \ - microdesc.c \ - networkstatus.c \ - nodelist.c \ - onion.c \ - transports.c \ - policies.c \ - reasons.c \ - relay.c \ - rendclient.c \ - rendcommon.c \ - rendmid.c \ - rendservice.c \ - rephist.c \ - router.c \ - routerlist.c \ - routerparse.c \ - status.c \ - $(evdns_source) \ - $(tor_platform_source) \ - config_codedigest.c - -#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \ -# ../common/libor-event.a - - -tor_SOURCES = tor_main.c - -AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ - -DLOCALSTATEDIR="\"$(localstatedir)\"" \ - -DBINDIR="\"$(bindir)\"" - -# -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. - - -tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ -tor_LDADD = ./libtor.a ../common/libor.a ../common/libor-crypto.a \ - ../common/libor-event.a \ - @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ - -noinst_HEADERS = \ - buffers.h \ - circuitbuild.h \ - circuitlist.h \ - circuituse.h \ - command.h \ - config.h \ - connection.h \ - connection_edge.h \ - connection_or.h \ - control.h \ - cpuworker.h \ - directory.h \ - dirserv.h \ - dirvote.h \ - dns.h \ - dnsserv.h \ - eventdns.h \ - eventdns_tor.h \ - geoip.h \ - hibernate.h \ - main.h \ - microdesc.h \ - networkstatus.h \ - nodelist.h \ - ntmain.h \ - onion.h \ - or.h \ - transports.h \ - policies.h \ - reasons.h \ - relay.h \ - rendclient.h \ - rendcommon.h \ - rendmid.h \ - rendservice.h \ - rephist.h \ - router.h \ - routerlist.h \ - routerparse.h \ - status.h \ - micro-revision.i - -config_codedigest.o: or_sha1.i - -tor_main.o: micro-revision.i - -micro-revision.i: FORCE - @rm -f micro-revision.tmp; \ - if test -d "$(top_srcdir)/.git" && \ - test -x "`which git 2>&1;true`"; then \ - HASH="`cd "$(top_srcdir)" && git rev-parse --short=16 HEAD`"; \ - echo \"$$HASH\" > micro-revision.tmp; \ - fi; \ - if test ! -f micro-revision.tmp ; then \ - 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; \ - fi; true - -or_sha1.i: $(tor_SOURCES) $(libtor_a_SOURCES) - if test "@SHA1SUM@" != none; then \ - (cd "$(srcdir)" && "@SHA1SUM@" $(tor_SOURCES) $(libtor_a_SOURCES)) | \ - "@SED@" -n 's/^\(.*\)$$/"\1\\n"/p' > or_sha1.i; \ - elif test "@OPENSSL@" != none; then \ - (cd "$(srcdir)" && "@OPENSSL@" sha1 $(tor_SOURCES) $(libtor_a_SOURCES)) | \ - "@SED@" -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > or_sha1.i; \ - else \ - rm or_sha1.i; \ - touch or_sha1.i; \ - fi - -CLEANFILES = micro-revision.i - -#Dummy target to ensure that micro-revision.i _always_ gets built. -FORCE: diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake index 3181e79c20..3b627b1d06 100644 --- a/src/or/Makefile.nmake +++ b/src/or/Makefile.nmake @@ -1,28 +1,75 @@ all: tor.exe -CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common +CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common \ + /I ..\ext -LIBS = ..\..\..\build-alpha\lib\libevent.a \ - ..\..\..\build-alpha\lib\libcrypto.a \ - ..\..\..\build-alpha\lib\libssl.a \ - ..\..\..\build-alpha\lib\libz.a \ - ws2_32.lib advapi32.lib shell32.lib +LIBS = ..\..\..\build-alpha\lib\libevent.lib \ + ..\..\..\build-alpha\lib\libcrypto.lib \ + ..\..\..\build-alpha\lib\libssl.lib \ + ..\..\..\build-alpha\lib\libz.lib \ + ws2_32.lib advapi32.lib shell32.lib \ + crypt32.lib gdi32.lib user32.lib -LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \ - command.obj config.obj connection.obj connection_edge.obj \ - connection_or.obj control.obj cpuworker.obj directory.obj \ - dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \ - hibernate.obj main.obj microdesc.obj networkstatus.obj \ - nodelist.obj onion.obj policies.obj reasons.obj relay.obj \ - rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \ - rephist.obj router.obj routerlist.obj routerparse.obj status.obj \ - config_codedigest.obj ntmain.obj +LIBTOR_OBJECTS = \ + addressmap.obj \ + buffers.obj \ + channel.obj \ + channeltls.obj \ + circuitbuild.obj \ + circuitlist.obj \ + circuitmux.obj \ + circuitmux_ewma.obj \ + circuitstats.obj \ + circuituse.obj \ + command.obj \ + config.obj \ + config_codedigest.obj \ + confparse.obj \ + connection.obj \ + connection_edge.obj \ + connection_or.obj \ + control.obj \ + cpuworker.obj \ + directory.obj \ + dirserv.obj \ + dirvote.obj \ + dns.obj \ + dnsserv.obj \ + fp_pair.obj \ + entrynodes.obj \ + geoip.obj \ + hibernate.obj \ + main.obj \ + microdesc.obj \ + networkstatus.obj \ + nodelist.obj \ + ntmain.obj \ + onion.obj \ + onion_fast.obj \ + onion_ntor.obj \ + onion_tap.obj \ + policies.obj \ + reasons.obj \ + relay.obj \ + rendclient.obj \ + rendcommon.obj \ + rendmid.obj \ + rendservice.obj \ + rephist.obj \ + replaycache.obj \ + router.obj \ + routerlist.obj \ + routerparse.obj \ + routerset.obj \ + statefile.obj \ + status.obj \ + transports.obj libtor.lib: $(LIBTOR_OBJECTS) - lib $(LIBTOR_OBJECTS) /out:libtor.lib + lib $(LIBTOR_OBJECTS) /out:$@ tor.exe: libtor.lib tor_main.obj - $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj + $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj /Fe$@ clean: del $(LIBTOR_OBJECTS) *.lib tor.exe diff --git a/src/or/addressmap.c b/src/or/addressmap.c new file mode 100644 index 0000000000..79e4b7c5e2 --- /dev/null +++ b/src/or/addressmap.c @@ -0,0 +1,1078 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define ADDRESSMAP_PRIVATE + +#include "or.h" +#include "addressmap.h" +#include "circuituse.h" +#include "config.h" +#include "connection_edge.h" +#include "control.h" +#include "dns.h" +#include "routerset.h" +#include "nodelist.h" + +/** A client-side struct to remember requests to rewrite addresses + * to new addresses. These structs are stored in the hash table + * "addressmap" below. + * + * There are 5 ways to set an address mapping: + * - A MapAddress command from the controller [permanent] + * - An AddressMap directive in the torrc [permanent] + * - When a TrackHostExits torrc directive is triggered [temporary] + * - When a DNS resolve succeeds [temporary] + * - When a DNS resolve fails [temporary] + * + * When an addressmap request is made but one is already registered, + * the new one is replaced only if the currently registered one has + * no "new_address" (that is, it's in the process of DNS resolve), + * or if the new one is permanent (expires==0 or 1). + * + * (We overload the 'expires' field, using "0" for mappings set via + * the configuration file, "1" for mappings set from the control + * interface, and other values for DNS and TrackHostExit mappings that can + * expire.) + * + * A mapping may be 'wildcarded'. If "src_wildcard" is true, then + * any address that ends with a . followed by the key for this entry will + * get remapped by it. If "dst_wildcard" is also true, then only the + * matching suffix of such addresses will get replaced by new_address. + */ +typedef struct { + char *new_address; + time_t expires; + ENUM_BF(addressmap_entry_source_t) source:3; + unsigned src_wildcard:1; + unsigned dst_wildcard:1; + short num_resolve_failures; +} addressmap_entry_t; + +/** Entry for mapping addresses to which virtual address we mapped them to. */ +typedef struct { + char *ipv4_address; + char *ipv6_address; + char *hostname_address; +} virtaddress_entry_t; + +/** A hash table to store client-side address rewrite instructions. */ +static strmap_t *addressmap=NULL; + +/** + * Table mapping addresses to which virtual address, if any, we + * assigned them to. + * + * We maintain the following invariant: if [A,B] is in + * virtaddress_reversemap, then B must be a virtual address, and [A,B] + * must be in addressmap. We do not require that the converse hold: + * if it fails, then we could end up mapping two virtual addresses to + * the same address, which is no disaster. + **/ +static strmap_t *virtaddress_reversemap=NULL; + +/** Initialize addressmap. */ +void +addressmap_init(void) +{ + addressmap = strmap_new(); + virtaddress_reversemap = strmap_new(); +} + +/** Free the memory associated with the addressmap entry <b>_ent</b>. */ +static void +addressmap_ent_free(void *_ent) +{ + addressmap_entry_t *ent; + if (!_ent) + return; + + ent = _ent; + tor_free(ent->new_address); + tor_free(ent); +} + +/** Free storage held by a virtaddress_entry_t* entry in <b>ent</b>. */ +static void +addressmap_virtaddress_ent_free(void *_ent) +{ + virtaddress_entry_t *ent; + if (!_ent) + return; + + ent = _ent; + tor_free(ent->ipv4_address); + tor_free(ent->hostname_address); + tor_free(ent); +} + +/** Free storage held by a virtaddress_entry_t* entry in <b>ent</b>. */ +static void +addressmap_virtaddress_remove(const char *address, addressmap_entry_t *ent) +{ + if (ent && ent->new_address && + address_is_in_virtual_range(ent->new_address)) { + virtaddress_entry_t *ve = + strmap_get(virtaddress_reversemap, ent->new_address); + /*log_fn(LOG_NOTICE,"remove reverse mapping for %s",ent->new_address);*/ + if (ve) { + if (!strcmp(address, ve->ipv4_address)) + tor_free(ve->ipv4_address); + if (!strcmp(address, ve->hostname_address)) + tor_free(ve->hostname_address); + if (!ve->ipv4_address && !ve->hostname_address) { + tor_free(ve); + strmap_remove(virtaddress_reversemap, ent->new_address); + } + } + } +} + +/** Remove <b>ent</b> (which must be mapped to by <b>address</b>) from the + * client address maps. */ +static void +addressmap_ent_remove(const char *address, addressmap_entry_t *ent) +{ + addressmap_virtaddress_remove(address, ent); + addressmap_ent_free(ent); +} + +/** Unregister all TrackHostExits mappings from any address to + * *.exitname.exit. */ +void +clear_trackexithost_mappings(const char *exitname) +{ + char *suffix = NULL; + if (!addressmap || !exitname) + return; + tor_asprintf(&suffix, ".%s.exit", exitname); + tor_strlower(suffix); + + STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) { + if (ent->source == ADDRMAPSRC_TRACKEXIT && + !strcmpend(ent->new_address, suffix)) { + addressmap_ent_remove(address, ent); + MAP_DEL_CURRENT(address); + } + } STRMAP_FOREACH_END; + + tor_free(suffix); +} + +/** Remove all TRACKEXIT mappings from the addressmap for which the target + * host is unknown or no longer allowed, or for which the source address + * is no longer in trackexithosts. */ +void +addressmap_clear_excluded_trackexithosts(const or_options_t *options) +{ + const routerset_t *allow_nodes = options->ExitNodes; + const routerset_t *exclude_nodes = options->ExcludeExitNodesUnion_; + + if (!addressmap) + return; + if (routerset_is_empty(allow_nodes)) + allow_nodes = NULL; + if (allow_nodes == NULL && routerset_is_empty(exclude_nodes)) + return; + + STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) { + size_t len; + const char *target = ent->new_address, *dot; + char *nodename; + const node_t *node; + + if (!target) { + /* DNS resolving in progress */ + continue; + } else if (strcmpend(target, ".exit")) { + /* Not a .exit mapping */ + continue; + } else if (ent->source != ADDRMAPSRC_TRACKEXIT) { + /* Not a trackexit mapping. */ + continue; + } + len = strlen(target); + if (len < 6) + continue; /* malformed. */ + dot = target + len - 6; /* dot now points to just before .exit */ + while (dot > target && *dot != '.') + dot--; + if (*dot == '.') dot++; + nodename = tor_strndup(dot, len-5-(dot-target));; + node = node_get_by_nickname(nodename, 0); + tor_free(nodename); + if (!node || + (allow_nodes && !routerset_contains_node(allow_nodes, node)) || + routerset_contains_node(exclude_nodes, node) || + !hostname_in_track_host_exits(options, address)) { + /* We don't know this one, or we want to be rid of it. */ + addressmap_ent_remove(address, ent); + MAP_DEL_CURRENT(address); + } + } STRMAP_FOREACH_END; +} + +/** Return true iff <b>address</b> is one that we are configured to + * automap on resolve according to <b>options</b>. */ +int +addressmap_address_should_automap(const char *address, + const or_options_t *options) +{ + const smartlist_t *suffix_list = options->AutomapHostsSuffixes; + + if (!suffix_list) + return 0; + + SMARTLIST_FOREACH_BEGIN(suffix_list, const char *, suffix) { + if (!strcasecmpend(address, suffix)) + return 1; + } SMARTLIST_FOREACH_END(suffix); + return 0; +} + +/** Remove all AUTOMAP mappings from the addressmap for which the + * source address no longer matches AutomapHostsSuffixes, which is + * no longer allowed by AutomapHostsOnResolve, or for which the + * target address is no longer in the virtual network. */ +void +addressmap_clear_invalid_automaps(const or_options_t *options) +{ + int clear_all = !options->AutomapHostsOnResolve; + const smartlist_t *suffixes = options->AutomapHostsSuffixes; + + if (!addressmap) + return; + + if (!suffixes) + clear_all = 1; /* This should be impossible, but let's be sure. */ + + STRMAP_FOREACH_MODIFY(addressmap, src_address, addressmap_entry_t *, ent) { + int remove = clear_all; + if (ent->source != ADDRMAPSRC_AUTOMAP) + continue; /* not an automap mapping. */ + + if (!remove) { + remove = ! addressmap_address_should_automap(src_address, options); + } + + if (!remove && ! address_is_in_virtual_range(ent->new_address)) + remove = 1; + + if (remove) { + addressmap_ent_remove(src_address, ent); + MAP_DEL_CURRENT(src_address); + } + } STRMAP_FOREACH_END; +} + +/** Remove all entries from the addressmap that were set via the + * configuration file or the command line. */ +void +addressmap_clear_configured(void) +{ + addressmap_get_mappings(NULL, 0, 0, 0); +} + +/** Remove all entries from the addressmap that are set to expire, ever. */ +void +addressmap_clear_transient(void) +{ + addressmap_get_mappings(NULL, 2, TIME_MAX, 0); +} + +/** Clean out entries from the addressmap cache that were + * added long enough ago that they are no longer valid. + */ +void +addressmap_clean(time_t now) +{ + addressmap_get_mappings(NULL, 2, now, 0); +} + +/** Free all the elements in the addressmap, and free the addressmap + * itself. */ +void +addressmap_free_all(void) +{ + strmap_free(addressmap, addressmap_ent_free); + addressmap = NULL; + + strmap_free(virtaddress_reversemap, addressmap_virtaddress_ent_free); + virtaddress_reversemap = NULL; +} + +/** Try to find a match for AddressMap expressions that use + * wildcard notation such as '*.c.d *.e.f' (so 'a.c.d' will map to 'a.e.f') or + * '*.c.d a.b.c' (so 'a.c.d' will map to a.b.c). + * Return the matching entry in AddressMap or NULL if no match is found. + * For expressions such as '*.c.d *.e.f', truncate <b>address</b> 'a.c.d' + * to 'a' before we return the matching AddressMap entry. + * + * This function does not handle the case where a pattern of the form "*.c.d" + * matches the address c.d -- that's done by the main addressmap_rewrite + * function. + */ +static addressmap_entry_t * +addressmap_match_superdomains(char *address) +{ + addressmap_entry_t *val; + char *cp; + + cp = address; + while ((cp = strchr(cp, '.'))) { + /* cp now points to a suffix of address that begins with a . */ + val = strmap_get_lc(addressmap, cp+1); + if (val && val->src_wildcard) { + if (val->dst_wildcard) + *cp = '\0'; + return val; + } + ++cp; + } + return NULL; +} + +/** Look at address, and rewrite it until it doesn't want any + * more rewrites; but don't get into an infinite loop. + * Don't write more than maxlen chars into address. Return true if the + * address changed; false otherwise. Set *<b>expires_out</b> to the + * expiry time of the result, or to <b>time_max</b> if the result does + * not expire. + * + * If <b>exit_source_out</b> is non-null, we set it as follows. If we the + * address starts out as a non-exit address, and we remap it to an .exit + * address at any point, then set *<b>exit_source_out</b> to the + * address_entry_source_t of the first such rule. Set *<b>exit_source_out</b> + * to ADDRMAPSRC_NONE if there is no such rewrite, or if the original address + * was a .exit. + */ +int +addressmap_rewrite(char *address, size_t maxlen, + unsigned flags, + time_t *expires_out, + addressmap_entry_source_t *exit_source_out) +{ + addressmap_entry_t *ent; + int rewrites; + time_t expires = TIME_MAX; + addressmap_entry_source_t exit_source = ADDRMAPSRC_NONE; + char *addr_orig = tor_strdup(address); + char *log_addr_orig = NULL; + + for (rewrites = 0; rewrites < 16; rewrites++) { + int exact_match = 0; + log_addr_orig = tor_strdup(escaped_safe_str_client(address)); + + ent = strmap_get(addressmap, address); + + if (!ent || !ent->new_address) { + ent = addressmap_match_superdomains(address); + } else { + if (ent->src_wildcard && !ent->dst_wildcard && + !strcasecmp(address, ent->new_address)) { + /* This is a rule like *.example.com example.com, and we just got + * "example.com" */ + goto done; + } + + exact_match = 1; + } + + if (!ent || !ent->new_address) { + goto done; + } + + if (ent && ent->source == ADDRMAPSRC_DNS) { + sa_family_t f; + tor_addr_t tmp; + f = tor_addr_parse(&tmp, ent->new_address); + if (f == AF_INET && !(flags & AMR_FLAG_USE_IPV4_DNS)) + goto done; + else if (f == AF_INET6 && !(flags & AMR_FLAG_USE_IPV6_DNS)) + goto done; + } + + if (ent->dst_wildcard && !exact_match) { + strlcat(address, ".", maxlen); + strlcat(address, ent->new_address, maxlen); + } else { + strlcpy(address, ent->new_address, maxlen); + } + + if (!strcmpend(address, ".exit") && + strcmpend(addr_orig, ".exit") && + exit_source == ADDRMAPSRC_NONE) { + exit_source = ent->source; + } + + log_info(LD_APP, "Addressmap: rewriting %s to %s", + log_addr_orig, escaped_safe_str_client(address)); + if (ent->expires > 1 && ent->expires < expires) + expires = ent->expires; + + tor_free(log_addr_orig); + } + log_warn(LD_CONFIG, + "Loop detected: we've rewritten %s 16 times! Using it as-is.", + escaped_safe_str_client(address)); + /* it's fine to rewrite a rewrite, but don't loop forever */ + + done: + tor_free(addr_orig); + tor_free(log_addr_orig); + if (exit_source_out) + *exit_source_out = exit_source; + if (expires_out) + *expires_out = TIME_MAX; + return (rewrites > 0); +} + +/** If we have a cached reverse DNS entry for the address stored in the + * <b>maxlen</b>-byte buffer <b>address</b> (typically, a dotted quad) then + * rewrite to the cached value and return 1. Otherwise return 0. Set + * *<b>expires_out</b> to the expiry time of the result, or to <b>time_max</b> + * if the result does not expire. */ +int +addressmap_rewrite_reverse(char *address, size_t maxlen, unsigned flags, + time_t *expires_out) +{ + char *s, *cp; + addressmap_entry_t *ent; + int r = 0; + { + sa_family_t f; + tor_addr_t tmp; + f = tor_addr_parse(&tmp, address); + if (f == AF_INET && !(flags & AMR_FLAG_USE_IPV4_DNS)) + return 0; + else if (f == AF_INET6 && !(flags & AMR_FLAG_USE_IPV6_DNS)) + return 0; + } + + tor_asprintf(&s, "REVERSE[%s]", address); + ent = strmap_get(addressmap, s); + if (ent) { + cp = tor_strdup(escaped_safe_str_client(ent->new_address)); + log_info(LD_APP, "Rewrote reverse lookup %s -> %s", + escaped_safe_str_client(s), cp); + tor_free(cp); + strlcpy(address, ent->new_address, maxlen); + r = 1; + } + + if (expires_out) + *expires_out = (ent && ent->expires > 1) ? ent->expires : TIME_MAX; + + tor_free(s); + return r; +} + +/** Return 1 if <b>address</b> is already registered, else return 0. If address + * is already registered, and <b>update_expires</b> is non-zero, then update + * the expiry time on the mapping with update_expires if it is a + * mapping created by TrackHostExits. */ +int +addressmap_have_mapping(const char *address, int update_expiry) +{ + addressmap_entry_t *ent; + if (!(ent=strmap_get_lc(addressmap, address))) + return 0; + if (update_expiry && ent->source==ADDRMAPSRC_TRACKEXIT) + ent->expires=time(NULL) + update_expiry; + return 1; +} + +/** Register a request to map <b>address</b> to <b>new_address</b>, + * which will expire on <b>expires</b> (or 0 if never expires from + * config file, 1 if never expires from controller, 2 if never expires + * (virtual address mapping) from the controller.) + * + * <b>new_address</b> should be a newly dup'ed string, which we'll use or + * free as appropriate. We will leave address alone. + * + * If <b>wildcard_addr</b> is true, then the mapping will match any address + * equal to <b>address</b>, or any address ending with a period followed by + * <b>address</b>. If <b>wildcard_addr</b> and <b>wildcard_new_addr</b> are + * both true, the mapping will rewrite addresses that end with + * ".<b>address</b>" into ones that end with ".<b>new_address</b>." + * + * If <b>new_address</b> is NULL, or <b>new_address</b> is equal to + * <b>address</b> and <b>wildcard_addr</b> is equal to + * <b>wildcard_new_addr</b>, remove any mappings that exist from + * <b>address</b>. + * + * + * It is an error to set <b>wildcard_new_addr</b> if <b>wildcard_addr</b> is + * not set. */ +void +addressmap_register(const char *address, char *new_address, time_t expires, + addressmap_entry_source_t source, + const int wildcard_addr, + const int wildcard_new_addr) +{ + addressmap_entry_t *ent; + + if (wildcard_new_addr) + tor_assert(wildcard_addr); + + ent = strmap_get(addressmap, address); + if (!new_address || (!strcasecmp(address,new_address) && + wildcard_addr == wildcard_new_addr)) { + /* Remove the mapping, if any. */ + tor_free(new_address); + if (ent) { + addressmap_ent_remove(address,ent); + strmap_remove(addressmap, address); + } + return; + } + if (!ent) { /* make a new one and register it */ + ent = tor_malloc_zero(sizeof(addressmap_entry_t)); + strmap_set(addressmap, address, ent); + } else if (ent->new_address) { /* we need to clean up the old mapping. */ + if (expires > 1) { + log_info(LD_APP,"Temporary addressmap ('%s' to '%s') not performed, " + "since it's already mapped to '%s'", + safe_str_client(address), + safe_str_client(new_address), + safe_str_client(ent->new_address)); + tor_free(new_address); + return; + } + if (address_is_in_virtual_range(ent->new_address) && + expires != 2) { + /* XXX This isn't the perfect test; we want to avoid removing + * mappings set from the control interface _as virtual mapping */ + addressmap_virtaddress_remove(address, ent); + } + tor_free(ent->new_address); + } /* else { we have an in-progress resolve with no mapping. } */ + + ent->new_address = new_address; + ent->expires = expires==2 ? 1 : expires; + ent->num_resolve_failures = 0; + ent->source = source; + ent->src_wildcard = wildcard_addr ? 1 : 0; + ent->dst_wildcard = wildcard_new_addr ? 1 : 0; + + log_info(LD_CONFIG, "Addressmap: (re)mapped '%s' to '%s'", + safe_str_client(address), + safe_str_client(ent->new_address)); + control_event_address_mapped(address, ent->new_address, expires, NULL, 1); +} + +/** An attempt to resolve <b>address</b> failed at some OR. + * Increment the number of resolve failures we have on record + * for it, and then return that number. + */ +int +client_dns_incr_failures(const char *address) +{ + addressmap_entry_t *ent = strmap_get(addressmap, address); + if (!ent) { + ent = tor_malloc_zero(sizeof(addressmap_entry_t)); + ent->expires = time(NULL) + MAX_DNS_ENTRY_AGE; + strmap_set(addressmap,address,ent); + } + 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_client(address), + ent->num_resolve_failures); + return ent->num_resolve_failures; +} + +/** If <b>address</b> is in the client DNS addressmap, reset + * the number of resolve failures we have on record for it. + * This is used when we fail a stream because it won't resolve: + * otherwise future attempts on that address will only try once. + */ +void +client_dns_clear_failures(const char *address) +{ + addressmap_entry_t *ent = strmap_get(addressmap, address); + if (ent) + ent->num_resolve_failures = 0; +} + +/** Record the fact that <b>address</b> resolved to <b>name</b>. + * We can now use this in subsequent streams via addressmap_rewrite() + * so we can more correctly choose an exit that will allow <b>address</b>. + * + * If <b>exitname</b> is defined, then append the addresses with + * ".exitname.exit" before registering the mapping. + * + * If <b>ttl</b> is nonnegative, the mapping will be valid for + * <b>ttl</b>seconds; otherwise, we use the default. + */ +static void +client_dns_set_addressmap_impl(entry_connection_t *for_conn, + const char *address, const char *name, + const char *exitname, + int ttl) +{ + char *extendedaddress=NULL, *extendedval=NULL; + (void)for_conn; + + tor_assert(address); + tor_assert(name); + + if (ttl<0) + ttl = DEFAULT_DNS_TTL; + else + ttl = dns_clip_ttl(ttl); + + if (exitname) { + /* XXXX fails to ever get attempts to get an exit address of + * google.com.digest[=~]nickname.exit; we need a syntax for this that + * won't make strict RFC952-compliant applications (like us) barf. */ + tor_asprintf(&extendedaddress, + "%s.%s.exit", address, exitname); + tor_asprintf(&extendedval, + "%s.%s.exit", name, exitname); + } else { + tor_asprintf(&extendedaddress, + "%s", address); + tor_asprintf(&extendedval, + "%s", name); + } + addressmap_register(extendedaddress, extendedval, + time(NULL) + ttl, ADDRMAPSRC_DNS, 0, 0); + tor_free(extendedaddress); +} + +/** Record the fact that <b>address</b> resolved to <b>val</b>. + * We can now use this in subsequent streams via addressmap_rewrite() + * so we can more correctly choose an exit that will allow <b>address</b>. + * + * If <b>exitname</b> is defined, then append the addresses with + * ".exitname.exit" before registering the mapping. + * + * If <b>ttl</b> is nonnegative, the mapping will be valid for + * <b>ttl</b>seconds; otherwise, we use the default. + */ +void +client_dns_set_addressmap(entry_connection_t *for_conn, + const char *address, + const tor_addr_t *val, + const char *exitname, + int ttl) +{ + tor_addr_t addr_tmp; + char valbuf[TOR_ADDR_BUF_LEN]; + + tor_assert(address); + tor_assert(val); + + if (tor_addr_parse(&addr_tmp, address) >= 0) + return; /* If address was an IP address already, don't add a mapping. */ + + if (tor_addr_family(val) == AF_INET) { + if (! for_conn->cache_ipv4_answers) + return; + } else if (tor_addr_family(val) == AF_INET6) { + if (! for_conn->cache_ipv6_answers) + return; + } + + if (! tor_addr_to_str(valbuf, val, sizeof(valbuf), 1)) + return; + + client_dns_set_addressmap_impl(for_conn, address, valbuf, exitname, ttl); +} + +/** Add a cache entry noting that <b>address</b> (ordinarily a dotted quad) + * resolved via a RESOLVE_PTR request to the hostname <b>v</b>. + * + * If <b>exitname</b> is defined, then append the addresses with + * ".exitname.exit" before registering the mapping. + * + * If <b>ttl</b> is nonnegative, the mapping will be valid for + * <b>ttl</b>seconds; otherwise, we use the default. + */ +void +client_dns_set_reverse_addressmap(entry_connection_t *for_conn, + const char *address, const char *v, + const char *exitname, + int ttl) +{ + char *s = NULL; + { + tor_addr_t tmp_addr; + sa_family_t f = tor_addr_parse(&tmp_addr, address); + if ((f == AF_INET && ! for_conn->cache_ipv4_answers) || + (f == AF_INET6 && ! for_conn->cache_ipv6_answers)) + return; + } + tor_asprintf(&s, "REVERSE[%s]", address); + client_dns_set_addressmap_impl(for_conn, s, v, exitname, ttl); + tor_free(s); +} + +/* By default, we hand out 127.192.0.1 through 127.254.254.254. + * These addresses should map to localhost, so even if the + * application accidentally tried to connect to them directly (not + * via Tor), it wouldn't get too far astray. + * + * These options are configured by parse_virtual_addr_network(). + */ + +static virtual_addr_conf_t virtaddr_conf_ipv4; +static virtual_addr_conf_t virtaddr_conf_ipv6; + +/** Read a netmask of the form 127.192.0.0/10 from "val", and check whether + * it's a valid set of virtual addresses to hand out in response to MAPADDRESS + * requests. Return 0 on success; set *msg (if provided) to a newly allocated + * string and return -1 on failure. If validate_only is false, sets the + * actual virtual address range to the parsed value. */ +int +parse_virtual_addr_network(const char *val, sa_family_t family, + int validate_only, + char **msg) +{ + const int ipv6 = (family == AF_INET6); + tor_addr_t addr; + maskbits_t bits; + const int max_bits = ipv6 ? 40 : 16; + virtual_addr_conf_t *conf = ipv6 ? &virtaddr_conf_ipv6 : &virtaddr_conf_ipv4; + + if (tor_addr_parse_mask_ports(val, 0, &addr, &bits, NULL, NULL) < 0) { + if (msg) + tor_asprintf(msg, "Error parsing VirtualAddressNetwork%s %s", + ipv6?"IPv6":"", val); + return -1; + } + if (tor_addr_family(&addr) != family) { + if (msg) + tor_asprintf(msg, "Incorrect address type for VirtualAddressNetwork%s", + ipv6?"IPv6":""); + return -1; + } +#if 0 + if (port_min != 1 || port_max != 65535) { + if (msg) + tor_asprintf(msg, "Can't specify ports on VirtualAddressNetwork%s", + ipv6?"IPv6":""); + return -1; + } +#endif + + if (bits > max_bits) { + if (msg) + tor_asprintf(msg, "VirtualAddressNetwork%s expects a /%d " + "network or larger",ipv6?"IPv6":"", max_bits); + return -1; + } + + if (validate_only) + return 0; + + tor_addr_copy(&conf->addr, &addr); + conf->bits = bits; + + return 0; +} + +/** + * Return true iff <b>addr</b> is likely to have been returned by + * client_dns_get_unused_address. + **/ +int +address_is_in_virtual_range(const char *address) +{ + tor_addr_t addr; + tor_assert(address); + if (!strcasecmpend(address, ".virtual")) { + return 1; + } else if (tor_addr_parse(&addr, address) >= 0) { + const virtual_addr_conf_t *conf = (tor_addr_family(&addr) == AF_INET6) ? + &virtaddr_conf_ipv6 : &virtaddr_conf_ipv4; + if (tor_addr_compare_masked(&addr, &conf->addr, conf->bits, CMP_EXACT)==0) + return 1; + } + return 0; +} + +/** Return a random address conforming to the virtual address configuration + * in <b>conf</b>. + */ +/* private */ void +get_random_virtual_addr(const virtual_addr_conf_t *conf, tor_addr_t *addr_out) +{ + uint8_t tmp[4]; + const uint8_t *addr_bytes; + uint8_t bytes[16]; + const int ipv6 = tor_addr_family(&conf->addr) == AF_INET6; + const int total_bytes = ipv6 ? 16 : 4; + + tor_assert(conf->bits <= total_bytes * 8); + + /* Set addr_bytes to the bytes of the virtual network, in host order */ + if (ipv6) { + addr_bytes = tor_addr_to_in6_addr8(&conf->addr); + } else { + set_uint32(tmp, tor_addr_to_ipv4n(&conf->addr)); + addr_bytes = tmp; + } + + /* Get an appropriate number of random bytes. */ + crypto_rand((char*)bytes, total_bytes); + + /* Now replace the first "conf->bits" bits of 'bytes' with addr_bytes*/ + if (conf->bits >= 8) + memcpy(bytes, addr_bytes, conf->bits / 8); + if (conf->bits & 7) { + uint8_t mask = 0xff >> (conf->bits & 7); + bytes[conf->bits/8] &= mask; + bytes[conf->bits/8] |= addr_bytes[conf->bits/8] & ~mask; + } + + if (ipv6) + tor_addr_from_ipv6_bytes(addr_out, (char*) bytes); + else + tor_addr_from_ipv4n(addr_out, get_uint32(bytes)); + + tor_assert(tor_addr_compare_masked(addr_out, &conf->addr, + conf->bits, CMP_EXACT)==0); +} + +/** Return a newly allocated string holding an address of <b>type</b> + * (one of RESOLVED_TYPE_{IPV4|HOSTNAME}) that has not yet been mapped, + * and that is very unlikely to be the address of any real host. + * + * May return NULL if we have run out of virtual addresses. + */ +static char * +addressmap_get_virtual_address(int type) +{ + char buf[64]; + tor_assert(addressmap); + + if (type == RESOLVED_TYPE_HOSTNAME) { + char rand[10]; + do { + crypto_rand(rand, sizeof(rand)); + base32_encode(buf,sizeof(buf),rand,sizeof(rand)); + strlcat(buf, ".virtual", sizeof(buf)); + } while (strmap_get(addressmap, buf)); + return tor_strdup(buf); + } else if (type == RESOLVED_TYPE_IPV4 || type == RESOLVED_TYPE_IPV6) { + const int ipv6 = (type == RESOLVED_TYPE_IPV6); + const virtual_addr_conf_t *conf = ipv6 ? + &virtaddr_conf_ipv6 : &virtaddr_conf_ipv4; + + /* Don't try more than 1000 times. This gives us P < 1e-9 for + * failing to get a good address so long as the address space is + * less than ~97.95% full. That's always going to be true under + * sensible circumstances for an IPv6 /10, and it's going to be + * true for an IPv4 /10 as long as we've handed out less than + * 4.08 million addresses. */ + uint32_t attempts = 1000; + + tor_addr_t addr; + + while (attempts--) { + get_random_virtual_addr(conf, &addr); + + if (!ipv6) { + /* Don't hand out any .0 or .255 address. */ + const uint32_t a = tor_addr_to_ipv4h(&addr); + if ((a & 0xff) == 0 || (a & 0xff) == 0xff) + continue; + } + + tor_addr_to_str(buf, &addr, sizeof(buf), 1); + if (!strmap_get(addressmap, buf)) { + /* XXXX This code is to make sure I didn't add an undecorated version + * by mistake. I hope it's needless. */ + char tmp[TOR_ADDR_BUF_LEN]; + tor_addr_to_str(buf, &addr, sizeof(tmp), 0); + if (strmap_get(addressmap, tmp)) { + log_warn(LD_BUG, "%s wasn't in the addressmap, but %s was.", + buf, tmp); + continue; + } + + return tor_strdup(buf); + } + } + log_warn(LD_CONFIG, "Ran out of virtual addresses!"); + return NULL; + } else { + log_warn(LD_BUG, "Called with unsupported address type (%d)", type); + return NULL; + } +} + +/** A controller has requested that we map some address of type + * <b>type</b> to the address <b>new_address</b>. Choose an address + * that is unlikely to be used, and map it, and return it in a newly + * allocated string. If another address of the same type is already + * mapped to <b>new_address</b>, try to return a copy of that address. + * + * The string in <b>new_address</b> may be freed or inserted into a map + * as appropriate. May return NULL if are out of virtual addresses. + **/ +const char * +addressmap_register_virtual_address(int type, char *new_address) +{ + char **addrp; + virtaddress_entry_t *vent; + int vent_needs_to_be_added = 0; + + tor_assert(new_address); + tor_assert(addressmap); + tor_assert(virtaddress_reversemap); + + vent = strmap_get(virtaddress_reversemap, new_address); + if (!vent) { + vent = tor_malloc_zero(sizeof(virtaddress_entry_t)); + vent_needs_to_be_added = 1; + } + + if (type == RESOLVED_TYPE_IPV4) + addrp = &vent->ipv4_address; + else if (type == RESOLVED_TYPE_IPV6) + addrp = &vent->ipv6_address; + else + addrp = &vent->hostname_address; + + if (*addrp) { + addressmap_entry_t *ent = strmap_get(addressmap, *addrp); + if (ent && ent->new_address && + !strcasecmp(new_address, ent->new_address)) { + tor_free(new_address); + tor_assert(!vent_needs_to_be_added); + return tor_strdup(*addrp); + } else { + 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_client(new_address), + safe_str_client(*addrp), + safe_str_client(*addrp), + ent?safe_str_client(ent->new_address):"(nothing)"); + } + } + + tor_free(*addrp); + *addrp = addressmap_get_virtual_address(type); + if (!*addrp) { + tor_free(vent); + tor_free(new_address); + return NULL; + } + log_info(LD_APP, "Registering map from %s to %s", *addrp, new_address); + if (vent_needs_to_be_added) + strmap_set(virtaddress_reversemap, new_address, vent); + addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_AUTOMAP, 0, 0); + +#if 0 + { + /* Try to catch possible bugs */ + addressmap_entry_t *ent; + ent = strmap_get(addressmap, *addrp); + tor_assert(ent); + tor_assert(!strcasecmp(ent->new_address,new_address)); + vent = strmap_get(virtaddress_reversemap, new_address); + tor_assert(vent); + tor_assert(!strcasecmp(*addrp, + (type == RESOLVED_TYPE_IPV4) ? + vent->ipv4_address : vent->hostname_address)); + log_info(LD_APP, "Map from %s to %s okay.", + safe_str_client(*addrp), + safe_str_client(new_address)); + } +#endif + + return *addrp; +} + +/** Return 1 if <b>address</b> has funny characters in it like colons. Return + * 0 if it's fine, or if we're configured to allow it anyway. <b>client</b> + * should be true if we're using this address as a client; false if we're + * using it as a server. + */ +int +address_is_invalid_destination(const char *address, int client) +{ + if (client) { + if (get_options()->AllowNonRFC953Hostnames) + return 0; + } else { + if (get_options()->ServerDNSAllowNonRFC953Hostnames) + return 0; + } + + /* It might be an IPv6 address! */ + { + tor_addr_t a; + if (tor_addr_parse(&a, address) >= 0) + return 0; + } + + while (*address) { + if (TOR_ISALNUM(*address) || + *address == '-' || + *address == '.' || + *address == '_') /* Underscore is not allowed, but Windows does it + * sometimes, just to thumb its nose at the IETF. */ + ++address; + else + return 1; + } + return 0; +} + +/** Iterate over all address mappings which have expiry times between + * min_expires and max_expires, inclusive. If sl is provided, add an + * "old-addr new-addr expiry" string to sl for each mapping, omitting + * the expiry time if want_expiry is false. If sl is NULL, remove the + * mappings. + */ +void +addressmap_get_mappings(smartlist_t *sl, time_t min_expires, + time_t max_expires, int want_expiry) +{ + strmap_iter_t *iter; + const char *key; + void *val_; + addressmap_entry_t *val; + + if (!addressmap) + addressmap_init(); + + for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) { + strmap_iter_get(iter, &key, &val_); + val = val_; + if (val->expires >= min_expires && val->expires <= max_expires) { + if (!sl) { + iter = strmap_iter_next_rmv(addressmap,iter); + addressmap_ent_remove(key, val); + continue; + } else if (val->new_address) { + const char *src_wc = val->src_wildcard ? "*." : ""; + const char *dst_wc = val->dst_wildcard ? "*." : ""; + if (want_expiry) { + if (val->expires < 3 || val->expires == TIME_MAX) + smartlist_add_asprintf(sl, "%s%s %s%s NEVER", + src_wc, key, dst_wc, val->new_address); + else { + char time[ISO_TIME_LEN+1]; + format_iso_time(time, val->expires); + smartlist_add_asprintf(sl, "%s%s %s%s \"%s\"", + src_wc, key, dst_wc, val->new_address, + time); + } + } else { + smartlist_add_asprintf(sl, "%s%s %s%s", + src_wc, key, dst_wc, val->new_address); + } + } + } + iter = strmap_iter_next(addressmap,iter); + } +} + diff --git a/src/or/addressmap.h b/src/or/addressmap.h new file mode 100644 index 0000000000..40210ee990 --- /dev/null +++ b/src/or/addressmap.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-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_ADDRESSMAP_H +#define TOR_ADDRESSMAP_H + +void addressmap_init(void); +void addressmap_clear_excluded_trackexithosts(const or_options_t *options); +void addressmap_clear_invalid_automaps(const or_options_t *options); +void addressmap_clean(time_t now); +void addressmap_clear_configured(void); +void addressmap_clear_transient(void); +void addressmap_free_all(void); +#define AMR_FLAG_USE_IPV4_DNS (1u<<0) +#define AMR_FLAG_USE_IPV6_DNS (1u<<1) +int addressmap_rewrite(char *address, size_t maxlen, unsigned flags, + time_t *expires_out, + addressmap_entry_source_t *exit_source_out); +int addressmap_rewrite_reverse(char *address, size_t maxlen, unsigned flags, + 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, + const int address_wildcard, + const int new_address_wildcard); +int parse_virtual_addr_network(const char *val, + sa_family_t family, 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(entry_connection_t *for_conn, + const char *address, const tor_addr_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 address_is_in_virtual_range(const char *addr); +void clear_trackexithost_mappings(const char *exitname); +void client_dns_set_reverse_addressmap(entry_connection_t *for_conn, + const char *address, const char *v, + const char *exitname, int ttl); +int addressmap_address_should_automap(const char *address, + const or_options_t *options); + +#ifdef ADDRESSMAP_PRIVATE +typedef struct virtual_addr_conf_t { + tor_addr_t addr; + maskbits_t bits; +} virtual_addr_conf_t; + +void get_random_virtual_addr(const virtual_addr_conf_t *conf, + tor_addr_t *addr_out); +#endif + +#endif + diff --git a/src/or/buffers.c b/src/or/buffers.c index 9be0476f64..c4c847ec87 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,6 +12,7 @@ **/ #define BUFFERS_PRIVATE #include "or.h" +#include "addressmap.h" #include "buffers.h" #include "config.h" #include "connection_edge.h" @@ -193,8 +194,6 @@ chunk_new_with_alloc_size(size_t alloc) freelist->lowest_length = freelist->cur_length; ++freelist->n_hit; } else { - /* XXXX take advantage of tor_malloc_roundup, once we know how that - * affects freelists. */ if (freelist) ++freelist->n_alloc; else @@ -217,7 +216,7 @@ static INLINE chunk_t * chunk_new_with_alloc_size(size_t alloc) { chunk_t *ch; - ch = tor_malloc_roundup(&alloc); + ch = tor_malloc(alloc); ch->next = NULL; ch->datalen = 0; ch->memlen = CHUNK_SIZE_WITH_ALLOC(alloc); @@ -337,11 +336,11 @@ buf_dump_freelist_sizes(int severity) { #ifdef ENABLE_BUF_FREELISTS int i; - log(severity, LD_MM, "====== Buffer freelists:"); + tor_log(severity, LD_MM, "====== Buffer freelists:"); for (i = 0; freelists[i].alloc_size; ++i) { uint64_t total = ((uint64_t)freelists[i].cur_length) * freelists[i].alloc_size; - log(severity, LD_MM, + tor_log(severity, LD_MM, U64_FORMAT" bytes in %d %d-byte chunks ["U64_FORMAT " misses; "U64_FORMAT" frees; "U64_FORMAT" hits]", U64_PRINTF_ARG(total), @@ -350,7 +349,7 @@ buf_dump_freelist_sizes(int severity) U64_PRINTF_ARG(freelists[i].n_free), U64_PRINTF_ARG(freelists[i].n_hit)); } - log(severity, LD_MM, U64_FORMAT" allocations in non-freelist sizes", + tor_log(severity, LD_MM, U64_FORMAT" allocations in non-freelist sizes", U64_PRINTF_ARG(n_freelist_miss)); #else (void)severity; @@ -1047,28 +1046,34 @@ cell_command_is_var_length(uint8_t command, int linkproto) int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) { - char hdr[VAR_CELL_HEADER_SIZE]; + char hdr[VAR_CELL_MAX_HEADER_SIZE]; var_cell_t *result; uint8_t command; uint16_t length; + const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; + const int circ_id_len = get_circ_id_size(wide_circ_ids); + const unsigned header_len = get_var_cell_header_size(wide_circ_ids); check(); *out = NULL; - if (buf->datalen < VAR_CELL_HEADER_SIZE) + if (buf->datalen < header_len) return 0; - peek_from_buf(hdr, sizeof(hdr), buf); + peek_from_buf(hdr, header_len, buf); - command = get_uint8(hdr+2); + command = get_uint8(hdr + circ_id_len); if (!(cell_command_is_var_length(command, linkproto))) return 0; - length = ntohs(get_uint16(hdr+3)); - if (buf->datalen < (size_t)(VAR_CELL_HEADER_SIZE+length)) + length = ntohs(get_uint16(hdr + circ_id_len + 1)); + if (buf->datalen < (size_t)(header_len+length)) return 1; result = var_cell_new(length); result->command = command; - result->circ_id = ntohs(get_uint16(hdr)); + if (wide_circ_ids) + result->circ_id = ntohl(get_uint32(hdr)); + else + result->circ_id = ntohs(get_uint16(hdr)); - buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE); + buf_remove_from_front(buf, header_len); peek_from_buf((char*) result->payload, length, buf); buf_remove_from_front(buf, length); check(); @@ -1127,30 +1132,36 @@ fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out, uint16_t cell_length; var_cell_t *cell; int result = 0; + const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; + const int circ_id_len = get_circ_id_size(wide_circ_ids); + const unsigned header_len = get_var_cell_header_size(wide_circ_ids); *out = NULL; buf_len = evbuffer_get_length(buf); - if (buf_len < VAR_CELL_HEADER_SIZE) + if (buf_len < header_len) return 0; - n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL); - tor_assert(n >= VAR_CELL_HEADER_SIZE); + n = inspect_evbuffer(buf, &hdr, header_len, &free_hdr, NULL); + tor_assert(n >= header_len); - command = get_uint8(hdr+2); + command = get_uint8(hdr + circ_id_len); if (!(cell_command_is_var_length(command, linkproto))) { goto done; } - cell_length = ntohs(get_uint16(hdr+3)); - if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) { + cell_length = ntohs(get_uint16(hdr + circ_id_len + 1)); + if (buf_len < (size_t)(header_len+cell_length)) { result = 1; /* Not all here yet. */ goto done; } cell = var_cell_new(cell_length); cell->command = command; - cell->circ_id = ntohs(get_uint16(hdr)); - evbuffer_drain(buf, VAR_CELL_HEADER_SIZE); + if (wide_circ_ids) + cell->circ_id = ntohl(get_uint32(hdr)); + else + cell->circ_id = ntohs(get_uint16(hdr)); + evbuffer_drain(buf, header_len); evbuffer_remove(buf, cell->payload, cell_length); *out = cell; result = 1; @@ -1507,22 +1518,19 @@ log_unsafe_socks_warning(int socks_protocol, const char *address, static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL); const 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, + if (safe_socks) { + log_fn_ratelim(&socks_ratelim, 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", + "TorFAQ#SOCKSAndDNS.%s", socks_protocol, (int)port, - safe_socks ? " Rejecting." : "", - m ? m : ""); - tor_free(m); + safe_socks ? " Rejecting." : ""); } control_event_client_status(LOG_WARN, "DANGEROUS_SOCKS PROTOCOL=SOCKS%d ADDRESS=%s:%d", @@ -1743,7 +1751,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, return 0; } req->replylen = 2; /* 2 bytes of response */ - req->reply[0] = 5; + req->reply[0] = 1; /* authversion == 1 */ req->reply[1] = 0; /* authentication successful */ log_debug(LD_APP, "socks5: Accepted username/password without checking."); @@ -1774,6 +1782,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, if (req->socks_version != 5) { /* we need to negotiate a method */ unsigned char nummethods = (unsigned char)*(data+1); + int have_user_pass, have_no_auth; int r=0; tor_assert(!req->socks_version); if (datalen < 2u+nummethods) { @@ -1784,19 +1793,21 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, return -1; req->replylen = 2; /* 2 bytes of response */ req->reply[0] = 5; /* socks5 reply */ - if (memchr(data+2, SOCKS_NO_AUTH, nummethods)) { - req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth - method */ - req->socks_version = 5; /* remember we've already negotiated auth */ - log_debug(LD_APP,"socks5: accepted method 0 (no authentication)"); - r=0; - } else if (memchr(data+2, SOCKS_USER_PASS, nummethods)) { + have_user_pass = (memchr(data+2, SOCKS_USER_PASS, nummethods) !=NULL); + have_no_auth = (memchr(data+2, SOCKS_NO_AUTH, nummethods) !=NULL); + if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) { req->auth_type = SOCKS_USER_PASS; req->reply[1] = SOCKS_USER_PASS; /* tell client to use "user/pass" auth method */ req->socks_version = 5; /* remember we've already negotiated auth */ log_debug(LD_APP,"socks5: accepted method 2 (username/password)"); r=0; + } else if (have_no_auth) { + req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth + method */ + req->socks_version = 5; /* remember we've already negotiated auth */ + log_debug(LD_APP,"socks5: accepted method 0 (no authentication)"); + r=0; } else { log_warn(LD_APP, "socks5: offered methods don't include 'no auth' or " diff --git a/src/or/buffers.h b/src/or/buffers.h index a5886adc7a..c947f0ba98 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for buffers.c. **/ -#ifndef _TOR_BUFFERS_H -#define _TOR_BUFFERS_H +#ifndef TOR_BUFFERS_H +#define TOR_BUFFERS_H buf_t *buf_new(void); buf_t *buf_new_with_capacity(size_t size); diff --git a/src/or/channel.c b/src/or/channel.c new file mode 100644 index 0000000000..1270eace7d --- /dev/null +++ b/src/or/channel.c @@ -0,0 +1,4132 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file channel.c + * \brief OR-to-OR channel abstraction layer + **/ + +/* + * Define this so channel.h gives us things only channel_t subclasses + * should touch. + */ + +#define TOR_CHANNEL_INTERNAL_ + +#include "or.h" +#include "channel.h" +#include "channeltls.h" +#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuitstats.h" +#include "connection_or.h" /* For var_cell_free() */ +#include "circuitmux.h" +#include "entrynodes.h" +#include "geoip.h" +#include "nodelist.h" +#include "relay.h" +#include "rephist.h" +#include "router.h" +#include "routerlist.h" + +/* Cell queue structure */ + +typedef struct cell_queue_entry_s cell_queue_entry_t; +struct cell_queue_entry_s { + TOR_SIMPLEQ_ENTRY(cell_queue_entry_s) next; + enum { + CELL_QUEUE_FIXED, + CELL_QUEUE_VAR, + CELL_QUEUE_PACKED + } type; + union { + struct { + cell_t *cell; + } fixed; + struct { + var_cell_t *var_cell; + } var; + struct { + packed_cell_t *packed_cell; + } packed; + } u; +}; + +/* Global lists of channels */ + +/* All channel_t instances */ +static smartlist_t *all_channels = NULL; + +/* All channel_t instances not in ERROR or CLOSED states */ +static smartlist_t *active_channels = NULL; + +/* All channel_t instances in ERROR or CLOSED states */ +static smartlist_t *finished_channels = NULL; + +/* All channel_listener_t instances */ +static smartlist_t *all_listeners = NULL; + +/* All channel_listener_t instances in LISTENING state */ +static smartlist_t *active_listeners = NULL; + +/* All channel_listener_t instances in LISTENING state */ +static smartlist_t *finished_listeners = NULL; + +/* Counter for ID numbers */ +static uint64_t n_channels_allocated = 0; + +/* Digest->channel map + * + * Similar to the one used in connection_or.c, this maps from the identity + * digest of a remote endpoint to a channel_t to that endpoint. Channels + * should be placed here when registered and removed when they close or error. + * If more than one channel exists, follow the next_with_same_id pointer + * as a linked list. + */ +HT_HEAD(channel_idmap, channel_idmap_entry_s) channel_identity_map = + HT_INITIALIZER(); + +typedef struct channel_idmap_entry_s { + HT_ENTRY(channel_idmap_entry_s) node; + uint8_t digest[DIGEST_LEN]; + TOR_LIST_HEAD(channel_list_s, channel_s) channel_list; +} channel_idmap_entry_t; + +static INLINE unsigned +channel_idmap_hash(const channel_idmap_entry_t *ent) +{ + const unsigned *a = (const unsigned *)ent->digest; +#if SIZEOF_INT == 4 + return a[0] ^ a[1] ^ a[2] ^ a[3] ^ a[4]; +#elif SIZEOF_INT == 8 + return a[0] ^ a[1]; +#endif +} + +static INLINE int +channel_idmap_eq(const channel_idmap_entry_t *a, + const channel_idmap_entry_t *b) +{ + return tor_memeq(a->digest, b->digest, DIGEST_LEN); +} + +HT_PROTOTYPE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, + channel_idmap_eq); +HT_GENERATE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, + channel_idmap_eq, 0.5, tor_malloc, tor_realloc, tor_free_); + +static cell_queue_entry_t * cell_queue_entry_dup(cell_queue_entry_t *q); +static void cell_queue_entry_free(cell_queue_entry_t *q, int handed_off); +static int cell_queue_entry_is_padding(cell_queue_entry_t *q); +static cell_queue_entry_t * +cell_queue_entry_new_fixed(cell_t *cell); +static cell_queue_entry_t * +cell_queue_entry_new_var(var_cell_t *var_cell); + +/* Functions to maintain the digest map */ +static void channel_add_to_digest_map(channel_t *chan); +static void channel_remove_from_digest_map(channel_t *chan); + +/* + * Flush cells from just the outgoing queue without trying to get them + * from circuits; used internall by channel_flush_some_cells(). + */ +static ssize_t +channel_flush_some_cells_from_outgoing_queue(channel_t *chan, + ssize_t num_cells); +static void channel_force_free(channel_t *chan); +static void +channel_free_list(smartlist_t *channels, int mark_for_close); +static void +channel_listener_free_list(smartlist_t *channels, int mark_for_close); +static void channel_listener_force_free(channel_listener_t *chan_l); +static void +channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q); + +/*********************************** + * Channel state utility functions * + **********************************/ + +/** + * Indicate whether a given channel state is valid + */ + +int +channel_state_is_valid(channel_state_t state) +{ + int is_valid; + + switch (state) { + case CHANNEL_STATE_CLOSED: + case CHANNEL_STATE_CLOSING: + case CHANNEL_STATE_ERROR: + case CHANNEL_STATE_MAINT: + case CHANNEL_STATE_OPENING: + case CHANNEL_STATE_OPEN: + is_valid = 1; + break; + case CHANNEL_STATE_LAST: + default: + is_valid = 0; + } + + return is_valid; +} + +/** + * Indicate whether a given channel listener state is valid + */ + +int +channel_listener_state_is_valid(channel_listener_state_t state) +{ + int is_valid; + + switch (state) { + case CHANNEL_LISTENER_STATE_CLOSED: + case CHANNEL_LISTENER_STATE_LISTENING: + case CHANNEL_LISTENER_STATE_CLOSING: + case CHANNEL_LISTENER_STATE_ERROR: + is_valid = 1; + break; + case CHANNEL_LISTENER_STATE_LAST: + default: + is_valid = 0; + } + + return is_valid; +} + +/** + * Indicate whether a channel state transition is valid + * + * This function takes two channel states and indicates whether a + * transition between them is permitted (see the state definitions and + * transition table in or.h at the channel_state_t typedef). + */ + +int +channel_state_can_transition(channel_state_t from, channel_state_t to) +{ + int is_valid; + + switch (from) { + case CHANNEL_STATE_CLOSED: + is_valid = (to == CHANNEL_STATE_OPENING); + break; + case CHANNEL_STATE_CLOSING: + is_valid = (to == CHANNEL_STATE_CLOSED || + to == CHANNEL_STATE_ERROR); + break; + case CHANNEL_STATE_ERROR: + is_valid = 0; + break; + case CHANNEL_STATE_MAINT: + is_valid = (to == CHANNEL_STATE_CLOSING || + to == CHANNEL_STATE_ERROR || + to == CHANNEL_STATE_OPEN); + break; + case CHANNEL_STATE_OPENING: + is_valid = (to == CHANNEL_STATE_CLOSING || + to == CHANNEL_STATE_ERROR || + to == CHANNEL_STATE_OPEN); + break; + case CHANNEL_STATE_OPEN: + is_valid = (to == CHANNEL_STATE_CLOSING || + to == CHANNEL_STATE_ERROR || + to == CHANNEL_STATE_MAINT); + break; + case CHANNEL_STATE_LAST: + default: + is_valid = 0; + } + + return is_valid; +} + +/** + * Indicate whether a channel listener state transition is valid + * + * This function takes two channel listener states and indicates whether a + * transition between them is permitted (see the state definitions and + * transition table in or.h at the channel_listener_state_t typedef). + */ + +int +channel_listener_state_can_transition(channel_listener_state_t from, + channel_listener_state_t to) +{ + int is_valid; + + switch (from) { + case CHANNEL_LISTENER_STATE_CLOSED: + is_valid = (to == CHANNEL_LISTENER_STATE_LISTENING); + break; + case CHANNEL_LISTENER_STATE_CLOSING: + is_valid = (to == CHANNEL_LISTENER_STATE_CLOSED || + to == CHANNEL_LISTENER_STATE_ERROR); + break; + case CHANNEL_LISTENER_STATE_ERROR: + is_valid = 0; + break; + case CHANNEL_LISTENER_STATE_LISTENING: + is_valid = (to == CHANNEL_LISTENER_STATE_CLOSING || + to == CHANNEL_LISTENER_STATE_ERROR); + break; + case CHANNEL_LISTENER_STATE_LAST: + default: + is_valid = 0; + } + + return is_valid; +} + +/** + * Return a human-readable description for a channel state + */ + +const char * +channel_state_to_string(channel_state_t state) +{ + const char *descr; + + switch (state) { + case CHANNEL_STATE_CLOSED: + descr = "closed"; + break; + case CHANNEL_STATE_CLOSING: + descr = "closing"; + break; + case CHANNEL_STATE_ERROR: + descr = "channel error"; + break; + case CHANNEL_STATE_MAINT: + descr = "temporarily suspended for maintenance"; + break; + case CHANNEL_STATE_OPENING: + descr = "opening"; + break; + case CHANNEL_STATE_OPEN: + descr = "open"; + break; + case CHANNEL_STATE_LAST: + default: + descr = "unknown or invalid channel state"; + } + + return descr; +} + +/** + * Return a human-readable description for a channel listenier state + */ + +const char * +channel_listener_state_to_string(channel_listener_state_t state) +{ + const char *descr; + + switch (state) { + case CHANNEL_LISTENER_STATE_CLOSED: + descr = "closed"; + break; + case CHANNEL_LISTENER_STATE_CLOSING: + descr = "closing"; + break; + case CHANNEL_LISTENER_STATE_ERROR: + descr = "channel listener error"; + break; + case CHANNEL_LISTENER_STATE_LISTENING: + descr = "listening"; + break; + case CHANNEL_LISTENER_STATE_LAST: + default: + descr = "unknown or invalid channel listener state"; + } + + return descr; +} + +/*************************************** + * Channel registration/unregistration * + ***************************************/ + +/** + * Register a channel + * + * This function registers a newly created channel in the global lists/maps + * of active channels. + */ + +void +channel_register(channel_t *chan) +{ + tor_assert(chan); + + /* No-op if already registered */ + if (chan->registered) return; + + log_debug(LD_CHANNEL, + "Registering channel %p (ID " U64_FORMAT ") " + "in state %s (%d) with digest %s", + chan, U64_PRINTF_ARG(chan->global_identifier), + channel_state_to_string(chan->state), chan->state, + hex_str(chan->identity_digest, DIGEST_LEN)); + + /* Make sure we have all_channels, then add it */ + if (!all_channels) all_channels = smartlist_new(); + smartlist_add(all_channels, chan); + + /* Is it finished? */ + if (chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR) { + /* Put it in the finished list, creating it if necessary */ + if (!finished_channels) finished_channels = smartlist_new(); + smartlist_add(finished_channels, chan); + } else { + /* Put it in the active list, creating it if necessary */ + if (!active_channels) active_channels = smartlist_new(); + smartlist_add(active_channels, chan); + + if (chan->state != CHANNEL_STATE_CLOSING) { + /* It should have a digest set */ + if (!tor_digest_is_zero(chan->identity_digest)) { + /* Yeah, we're good, add it to the map */ + channel_add_to_digest_map(chan); + } else { + log_info(LD_CHANNEL, + "Channel %p (global ID " U64_FORMAT ") " + "in state %s (%d) registered with no identity digest", + chan, U64_PRINTF_ARG(chan->global_identifier), + channel_state_to_string(chan->state), chan->state); + } + } + } + + /* Mark it as registered */ + chan->registered = 1; +} + +/** + * Unregister a channel + * + * This function removes a channel from the global lists and maps and is used + * when freeing a closed/errored channel. + */ + +void +channel_unregister(channel_t *chan) +{ + tor_assert(chan); + + /* No-op if not registered */ + if (!(chan->registered)) return; + + /* Is it finished? */ + if (chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR) { + /* Get it out of the finished list */ + if (finished_channels) smartlist_remove(finished_channels, chan); + } else { + /* Get it out of the active list */ + if (active_channels) smartlist_remove(active_channels, chan); + } + + /* Get it out of all_channels */ + if (all_channels) smartlist_remove(all_channels, chan); + + /* Mark it as unregistered */ + chan->registered = 0; + + /* Should it be in the digest map? */ + if (!tor_digest_is_zero(chan->identity_digest) && + !(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR)) { + /* Remove it */ + channel_remove_from_digest_map(chan); + } +} + +/** + * Register a channel listener + * + * This function registers a newly created channel listner in the global + * lists/maps of active channel listeners. + */ + +void +channel_listener_register(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + /* No-op if already registered */ + if (chan_l->registered) return; + + log_debug(LD_CHANNEL, + "Registering channel listener %p (ID " U64_FORMAT ") " + "in state %s (%d)", + chan_l, U64_PRINTF_ARG(chan_l->global_identifier), + channel_listener_state_to_string(chan_l->state), + chan_l->state); + + /* Make sure we have all_channels, then add it */ + if (!all_listeners) all_listeners = smartlist_new(); + smartlist_add(all_listeners, chan_l); + + /* Is it finished? */ + if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR) { + /* Put it in the finished list, creating it if necessary */ + if (!finished_listeners) finished_listeners = smartlist_new(); + smartlist_add(finished_listeners, chan_l); + } else { + /* Put it in the active list, creating it if necessary */ + if (!active_listeners) active_listeners = smartlist_new(); + smartlist_add(active_listeners, chan_l); + } + + /* Mark it as registered */ + chan_l->registered = 1; +} + +/** + * Unregister a channel listener + * + * This function removes a channel listener from the global lists and maps + * and is used when freeing a closed/errored channel listener. + */ + +void +channel_listener_unregister(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + /* No-op if not registered */ + if (!(chan_l->registered)) return; + + /* Is it finished? */ + if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR) { + /* Get it out of the finished list */ + if (finished_listeners) smartlist_remove(finished_listeners, chan_l); + } else { + /* Get it out of the active list */ + if (active_listeners) smartlist_remove(active_listeners, chan_l); + } + + /* Get it out of all_channels */ + if (all_listeners) smartlist_remove(all_listeners, chan_l); + + /* Mark it as unregistered */ + chan_l->registered = 0; +} + +/********************************* + * Channel digest map maintenance + *********************************/ + +/** + * Add a channel to the digest map + * + * This function adds a channel to the digest map and inserts it into the + * correct linked list if channels with that remote endpoint identity digest + * already exist. + */ + +static void +channel_add_to_digest_map(channel_t *chan) +{ + channel_idmap_entry_t *ent, search; + + tor_assert(chan); + + /* Assert that the state makes sense */ + tor_assert(!(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR)); + + /* Assert that there is a digest */ + tor_assert(!tor_digest_is_zero(chan->identity_digest)); + + memcpy(search.digest, chan->identity_digest, DIGEST_LEN); + ent = HT_FIND(channel_idmap, &channel_identity_map, &search); + if (! ent) { + ent = tor_malloc(sizeof(channel_idmap_entry_t)); + memcpy(ent->digest, chan->identity_digest, DIGEST_LEN); + TOR_LIST_INIT(&ent->channel_list); + HT_INSERT(channel_idmap, &channel_identity_map, ent); + } + TOR_LIST_INSERT_HEAD(&ent->channel_list, chan, next_with_same_id); + + log_debug(LD_CHANNEL, + "Added channel %p (global ID " U64_FORMAT ") " + "to identity map in state %s (%d) with digest %s", + chan, U64_PRINTF_ARG(chan->global_identifier), + channel_state_to_string(chan->state), chan->state, + hex_str(chan->identity_digest, DIGEST_LEN)); +} + +/** + * Remove a channel from the digest map + * + * This function removes a channel from the digest map and the linked list of + * channels for that digest if more than one exists. + */ + +static void +channel_remove_from_digest_map(channel_t *chan) +{ + channel_idmap_entry_t *ent, search; + + tor_assert(chan); + + /* Assert that there is a digest */ + tor_assert(!tor_digest_is_zero(chan->identity_digest)); + +#if 0 + /* Make sure we have a map */ + if (!channel_identity_map) { + /* + * No identity map, so we can't find it by definition. This + * case is similar to digestmap_get() failing below. + */ + log_warn(LD_BUG, + "Trying to remove channel %p (global ID " U64_FORMAT ") " + "with digest %s from identity map, but didn't have any identity " + "map", + chan, U64_PRINTF_ARG(chan->global_identifier), + hex_str(chan->identity_digest, DIGEST_LEN)); + /* Clear out its next/prev pointers */ + if (chan->next_with_same_id) { + chan->next_with_same_id->prev_with_same_id = chan->prev_with_same_id; + } + if (chan->prev_with_same_id) { + chan->prev_with_same_id->next_with_same_id = chan->next_with_same_id; + } + chan->next_with_same_id = NULL; + chan->prev_with_same_id = NULL; + + return; + } +#endif + + /* Pull it out of its list, wherever that list is */ + TOR_LIST_REMOVE(chan, next_with_same_id); + + memcpy(search.digest, chan->identity_digest, DIGEST_LEN); + ent = HT_FIND(channel_idmap, &channel_identity_map, &search); + + /* Look for it in the map */ + if (ent) { + /* Okay, it's here */ + + if (TOR_LIST_EMPTY(&ent->channel_list)) { + HT_REMOVE(channel_idmap, &channel_identity_map, ent); + tor_free(ent); + } + + log_debug(LD_CHANNEL, + "Removed channel %p (global ID " U64_FORMAT ") from " + "identity map in state %s (%d) with digest %s", + chan, U64_PRINTF_ARG(chan->global_identifier), + channel_state_to_string(chan->state), chan->state, + hex_str(chan->identity_digest, DIGEST_LEN)); + } else { + /* Shouldn't happen */ + log_warn(LD_BUG, + "Trying to remove channel %p (global ID " U64_FORMAT ") with " + "digest %s from identity map, but couldn't find any with " + "that digest", + chan, U64_PRINTF_ARG(chan->global_identifier), + hex_str(chan->identity_digest, DIGEST_LEN)); + } +} + +/**************************** + * Channel lookup functions * + ***************************/ + +/** + * Find channel by global ID + * + * This function searches for a channel by the global_identifier assigned + * at initialization time. This identifier is unique for the lifetime of the + * Tor process. + */ + +channel_t * +channel_find_by_global_id(uint64_t global_identifier) +{ + channel_t *rv = NULL; + + if (all_channels && smartlist_len(all_channels) > 0) { + SMARTLIST_FOREACH_BEGIN(all_channels, channel_t *, curr) { + if (curr->global_identifier == global_identifier) { + rv = curr; + break; + } + } SMARTLIST_FOREACH_END(curr); + } + + return rv; +} + +/** + * Find channel by digest of the remote endpoint + * + * This function looks up a channel by the digest of its remote endpoint in + * the channel digest map. It's possible that more than one channel to a + * given endpoint exists. Use channel_next_with_digest() to walk the list. + */ + +channel_t * +channel_find_by_remote_digest(const char *identity_digest) +{ + channel_t *rv = NULL; + channel_idmap_entry_t *ent, search; + + tor_assert(identity_digest); + + memcpy(search.digest, identity_digest, DIGEST_LEN); + ent = HT_FIND(channel_idmap, &channel_identity_map, &search); + if (ent) { + rv = TOR_LIST_FIRST(&ent->channel_list); + } + + return rv; +} + +/** + * Get next channel with digest + * + * This function takes a channel and finds the next channel in the list + * with the same digest. + */ + +channel_t * +channel_next_with_digest(channel_t *chan) +{ + tor_assert(chan); + + return TOR_LIST_NEXT(chan, next_with_same_id); +} + +/** + * Initialize a channel + * + * This function should be called by subclasses to set up some per-channel + * variables. I.e., this is the superclass constructor. Before this, the + * channel should be allocated with tor_malloc_zero(). + */ + +void +channel_init(channel_t *chan) +{ + tor_assert(chan); + + /* Assign an ID and bump the counter */ + chan->global_identifier = n_channels_allocated++; + + /* Init timestamp */ + chan->timestamp_last_added_nonpadding = time(NULL); + + /* Init next_circ_id */ + chan->next_circ_id = crypto_rand_int(1 << 15); + + /* Initialize queues. */ + TOR_SIMPLEQ_INIT(&chan->incoming_queue); + TOR_SIMPLEQ_INIT(&chan->outgoing_queue); + + /* Initialize list entries. */ + memset(&chan->next_with_same_id, 0, sizeof(chan->next_with_same_id)); + + /* Timestamp it */ + channel_timestamp_created(chan); + + /* It hasn't been open yet. */ + chan->has_been_open = 0; +} + +/** + * Initialize a channel listener + * + * This function should be called by subclasses to set up some per-channel + * variables. I.e., this is the superclass constructor. Before this, the + * channel listener should be allocated with tor_malloc_zero(). + */ + +void +channel_init_listener(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + /* Assign an ID and bump the counter */ + chan_l->global_identifier = n_channels_allocated++; + + /* Timestamp it */ + channel_listener_timestamp_created(chan_l); +} + +/** + * Free a channel; nothing outside of channel.c and subclasses should call + * this - it frees channels after they have closed and been unregistered. + */ + +void +channel_free(channel_t *chan) +{ + if (!chan) return; + + /* It must be closed or errored */ + tor_assert(chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR); + /* It must be deregistered */ + tor_assert(!(chan->registered)); + + log_debug(LD_CHANNEL, + "Freeing channel " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan->global_identifier), chan); + + /* + * Get rid of cmux policy before we do anything, so cmux policies don't + * see channels in weird half-freed states. + */ + if (chan->cmux) { + circuitmux_set_policy(chan->cmux, NULL); + } + + /* Call a free method if there is one */ + if (chan->free) chan->free(chan); + + channel_clear_remote_end(chan); + + /* Get rid of cmux */ + if (chan->cmux) { + circuitmux_detach_all_circuits(chan->cmux); + circuitmux_free(chan->cmux); + chan->cmux = NULL; + } + + /* We're in CLOSED or ERROR, so the cell queue is already empty */ + + tor_free(chan); +} + +/** + * Free a channel listener; nothing outside of channel.c and subclasses + * should call this - it frees channel listeners after they have closed and + * been unregistered. + */ + +void +channel_listener_free(channel_listener_t *chan_l) +{ + if (!chan_l) return; + + log_debug(LD_CHANNEL, + "Freeing channel_listener_t " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan_l->global_identifier), + chan_l); + + /* It must be closed or errored */ + tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR); + /* It must be deregistered */ + tor_assert(!(chan_l->registered)); + + /* Call a free method if there is one */ + if (chan_l->free) chan_l->free(chan_l); + + /* + * We're in CLOSED or ERROR, so the incoming channel queue is already + * empty. + */ + + tor_free(chan_l); +} + +/** + * Free a channel and skip the state/registration asserts; this internal- + * use-only function should be called only from channel_free_all() when + * shutting down the Tor process. + */ + +static void +channel_force_free(channel_t *chan) +{ + cell_queue_entry_t *cell, *cell_tmp; + tor_assert(chan); + + log_debug(LD_CHANNEL, + "Force-freeing channel " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan->global_identifier), chan); + + /* + * Get rid of cmux policy before we do anything, so cmux policies don't + * see channels in weird half-freed states. + */ + if (chan->cmux) { + circuitmux_set_policy(chan->cmux, NULL); + } + + /* Call a free method if there is one */ + if (chan->free) chan->free(chan); + + channel_clear_remote_end(chan); + + /* Get rid of cmux */ + if (chan->cmux) { + circuitmux_free(chan->cmux); + chan->cmux = NULL; + } + + /* We might still have a cell queue; kill it */ + TOR_SIMPLEQ_FOREACH_SAFE(cell, &chan->incoming_queue, next, cell_tmp) { + cell_queue_entry_free(cell, 0); + } + TOR_SIMPLEQ_INIT(&chan->incoming_queue); + + /* Outgoing cell queue is similar, but we can have to free packed cells */ + TOR_SIMPLEQ_FOREACH_SAFE(cell, &chan->outgoing_queue, next, cell_tmp) { + cell_queue_entry_free(cell, 0); + } + TOR_SIMPLEQ_INIT(&chan->outgoing_queue); + + tor_free(chan); +} + +/** + * Free a channel listener and skip the state/reigstration asserts; this + * internal-use-only function should be called only from channel_free_all() + * when shutting down the Tor process. + */ + +static void +channel_listener_force_free(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + log_debug(LD_CHANNEL, + "Force-freeing channel_listener_t " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan_l->global_identifier), + chan_l); + + /* Call a free method if there is one */ + if (chan_l->free) chan_l->free(chan_l); + + /* + * The incoming list just gets emptied and freed; we request close on + * any channels we find there, but since we got called while shutting + * down they will get deregistered and freed elsewhere anyway. + */ + if (chan_l->incoming_list) { + SMARTLIST_FOREACH_BEGIN(chan_l->incoming_list, + channel_t *, qchan) { + channel_mark_for_close(qchan); + } SMARTLIST_FOREACH_END(qchan); + + smartlist_free(chan_l->incoming_list); + chan_l->incoming_list = NULL; + } + + tor_free(chan_l); +} + +/** + * Return the current registered listener for a channel listener + * + * This function returns a function pointer to the current registered + * handler for new incoming channels on a channel listener. + */ + +channel_listener_fn_ptr +channel_listener_get_listener_fn(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + if (chan_l->state == CHANNEL_LISTENER_STATE_LISTENING) + return chan_l->listener; + + return NULL; +} + +/** + * Set the listener for a channel listener + * + * This function sets the handler for new incoming channels on a channel + * listener. + */ + +void +channel_listener_set_listener_fn(channel_listener_t *chan_l, + channel_listener_fn_ptr listener) +{ + tor_assert(chan_l); + tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_LISTENING); + + log_debug(LD_CHANNEL, + "Setting listener callback for channel listener %p " + "(global ID " U64_FORMAT ") to %p", + chan_l, U64_PRINTF_ARG(chan_l->global_identifier), + listener); + + chan_l->listener = listener; + if (chan_l->listener) channel_listener_process_incoming(chan_l); +} + +/** + * Return the fixed-length cell handler for a channel + * + * This function gets the handler for incoming fixed-length cells installed + * on a channel. + */ + +channel_cell_handler_fn_ptr +channel_get_cell_handler(channel_t *chan) +{ + tor_assert(chan); + + if (chan->state == CHANNEL_STATE_OPENING || + chan->state == CHANNEL_STATE_OPEN || + chan->state == CHANNEL_STATE_MAINT) + return chan->cell_handler; + + return NULL; +} + +/** + * Return the variable-length cell handler for a channel + * + * This function gets the handler for incoming variable-length cells + * installed on a channel. + */ + +channel_var_cell_handler_fn_ptr +channel_get_var_cell_handler(channel_t *chan) +{ + tor_assert(chan); + + if (chan->state == CHANNEL_STATE_OPENING || + chan->state == CHANNEL_STATE_OPEN || + chan->state == CHANNEL_STATE_MAINT) + return chan->var_cell_handler; + + return NULL; +} + +/** + * Set both cell handlers for a channel + * + * This function sets both the fixed-length and variable length cell handlers + * for a channel and processes any incoming cells that had been blocked in the + * queue because none were available. + */ + +void +channel_set_cell_handlers(channel_t *chan, + channel_cell_handler_fn_ptr cell_handler, + channel_var_cell_handler_fn_ptr + var_cell_handler) +{ + int try_again = 0; + + tor_assert(chan); + tor_assert(chan->state == CHANNEL_STATE_OPENING || + chan->state == CHANNEL_STATE_OPEN || + chan->state == CHANNEL_STATE_MAINT); + + log_debug(LD_CHANNEL, + "Setting cell_handler callback for channel %p to %p", + chan, cell_handler); + log_debug(LD_CHANNEL, + "Setting var_cell_handler callback for channel %p to %p", + chan, var_cell_handler); + + /* Should we try the queue? */ + if (cell_handler && + cell_handler != chan->cell_handler) try_again = 1; + if (var_cell_handler && + var_cell_handler != chan->var_cell_handler) try_again = 1; + + /* Change them */ + chan->cell_handler = cell_handler; + chan->var_cell_handler = var_cell_handler; + + /* Re-run the queue if we have one and there's any reason to */ + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue) && + try_again && + (chan->cell_handler || + chan->var_cell_handler)) channel_process_cells(chan); +} + +/* + * On closing channels + * + * There are three functions that close channels, for use in + * different circumstances: + * + * - Use channel_mark_for_close() for most cases + * - Use channel_close_from_lower_layer() if you are connection_or.c + * and the other end closes the underlying connection. + * - Use channel_close_for_error() if you are connection_or.c and + * some sort of error has occurred. + */ + +/** + * Mark a channel for closure + * + * This function tries to close a channel_t; it will go into the CLOSING + * state, and eventually the lower layer should put it into the CLOSED or + * ERROR state. Then, channel_run_cleanup() will eventually free it. + */ + +void +channel_mark_for_close(channel_t *chan) +{ + tor_assert(chan != NULL); + tor_assert(chan->close != NULL); + + /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */ + if (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR) return; + + log_debug(LD_CHANNEL, + "Closing channel %p (global ID " U64_FORMAT ") " + "by request", + chan, U64_PRINTF_ARG(chan->global_identifier)); + + /* Note closing by request from above */ + chan->reason_for_closing = CHANNEL_CLOSE_REQUESTED; + + /* Change state to CLOSING */ + channel_change_state(chan, CHANNEL_STATE_CLOSING); + + /* Tell the lower layer */ + chan->close(chan); + + /* + * It's up to the lower layer to change state to CLOSED or ERROR when we're + * ready; we'll try to free channels that are in the finished list from + * channel_run_cleanup(). The lower layer should do this by calling + * channel_closed(). + */ +} + +/** + * Mark a channel listener for closure + * + * This function tries to close a channel_listener_t; it will go into the + * CLOSING state, and eventually the lower layer should put it into the CLOSED + * or ERROR state. Then, channel_run_cleanup() will eventually free it. + */ + +void +channel_listener_mark_for_close(channel_listener_t *chan_l) +{ + tor_assert(chan_l != NULL); + tor_assert(chan_l->close != NULL); + + /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */ + if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSING || + chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return; + + log_debug(LD_CHANNEL, + "Closing channel listener %p (global ID " U64_FORMAT ") " + "by request", + chan_l, U64_PRINTF_ARG(chan_l->global_identifier)); + + /* Note closing by request from above */ + chan_l->reason_for_closing = CHANNEL_LISTENER_CLOSE_REQUESTED; + + /* Change state to CLOSING */ + channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING); + + /* Tell the lower layer */ + chan_l->close(chan_l); + + /* + * It's up to the lower layer to change state to CLOSED or ERROR when we're + * ready; we'll try to free channels that are in the finished list from + * channel_run_cleanup(). The lower layer should do this by calling + * channel_listener_closed(). + */ +} + +/** + * Close a channel from the lower layer + * + * Notify the channel code that the channel is being closed due to a non-error + * condition in the lower layer. This does not call the close() method, since + * the lower layer already knows. + */ + +void +channel_close_from_lower_layer(channel_t *chan) +{ + tor_assert(chan != NULL); + + /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */ + if (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR) return; + + log_debug(LD_CHANNEL, + "Closing channel %p (global ID " U64_FORMAT ") " + "due to lower-layer event", + chan, U64_PRINTF_ARG(chan->global_identifier)); + + /* Note closing by event from below */ + chan->reason_for_closing = CHANNEL_CLOSE_FROM_BELOW; + + /* Change state to CLOSING */ + channel_change_state(chan, CHANNEL_STATE_CLOSING); +} + +/** + * Close a channel listener from the lower layer + * + * Notify the channel code that the channel listener is being closed due to a + * non-error condition in the lower layer. This does not call the close() + * method, since the lower layer already knows. + */ + +void +channel_listener_close_from_lower_layer(channel_listener_t *chan_l) +{ + tor_assert(chan_l != NULL); + + /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */ + if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSING || + chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return; + + log_debug(LD_CHANNEL, + "Closing channel listener %p (global ID " U64_FORMAT ") " + "due to lower-layer event", + chan_l, U64_PRINTF_ARG(chan_l->global_identifier)); + + /* Note closing by event from below */ + chan_l->reason_for_closing = CHANNEL_LISTENER_CLOSE_FROM_BELOW; + + /* Change state to CLOSING */ + channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING); +} + +/** + * Notify that the channel is being closed due to an error condition + * + * This function is called by the lower layer implementing the transport + * when a channel must be closed due to an error condition. This does not + * call the channel's close method, since the lower layer already knows. + */ + +void +channel_close_for_error(channel_t *chan) +{ + tor_assert(chan != NULL); + + /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */ + if (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR) return; + + log_debug(LD_CHANNEL, + "Closing channel %p due to lower-layer error", + chan); + + /* Note closing by event from below */ + chan->reason_for_closing = CHANNEL_CLOSE_FOR_ERROR; + + /* Change state to CLOSING */ + channel_change_state(chan, CHANNEL_STATE_CLOSING); +} + +/** + * Notify that the channel listener is being closed due to an error condition + * + * This function is called by the lower layer implementing the transport + * when a channel listener must be closed due to an error condition. This + * does not call the channel listener's close method, since the lower layer + * already knows. + */ + +void +channel_listener_close_for_error(channel_listener_t *chan_l) +{ + tor_assert(chan_l != NULL); + + /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */ + if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSING || + chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return; + + log_debug(LD_CHANNEL, + "Closing channel listener %p (global ID " U64_FORMAT ") " + "due to lower-layer error", + chan_l, U64_PRINTF_ARG(chan_l->global_identifier)); + + /* Note closing by event from below */ + chan_l->reason_for_closing = CHANNEL_LISTENER_CLOSE_FOR_ERROR; + + /* Change state to CLOSING */ + channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING); +} + +/** + * Notify that the lower layer is finished closing the channel + * + * This function should be called by the lower layer when a channel + * is finished closing and it should be regarded as inactive and + * freed by the channel code. + */ + +void +channel_closed(channel_t *chan) +{ + tor_assert(chan); + tor_assert(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR); + + /* No-op if already inactive */ + if (chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR) return; + + /* Inform any pending (not attached) circs that they should + * give up. */ + if (! chan->has_been_open) + circuit_n_chan_done(chan, 0); + + /* Now close all the attached circuits on it. */ + circuit_unlink_all_from_channel(chan, END_CIRC_REASON_CHANNEL_CLOSED); + + if (chan->reason_for_closing != CHANNEL_CLOSE_FOR_ERROR) { + channel_change_state(chan, CHANNEL_STATE_CLOSED); + } else { + channel_change_state(chan, CHANNEL_STATE_ERROR); + } +} + +/** + * Notify that the lower layer is finished closing the channel listener + * + * This function should be called by the lower layer when a channel listener + * is finished closing and it should be regarded as inactive and + * freed by the channel code. + */ + +void +channel_listener_closed(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_CLOSING || + chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR); + + /* No-op if already inactive */ + if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return; + + if (chan_l->reason_for_closing != CHANNEL_LISTENER_CLOSE_FOR_ERROR) { + channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSED); + } else { + channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_ERROR); + } +} + +/** + * Clear the identity_digest of a channel + * + * This function clears the identity digest of the remote endpoint for a + * channel; this is intended for use by the lower layer. + */ + +void +channel_clear_identity_digest(channel_t *chan) +{ + int state_not_in_map; + + tor_assert(chan); + + log_debug(LD_CHANNEL, + "Clearing remote endpoint digest on channel %p with " + "global ID " U64_FORMAT, + chan, U64_PRINTF_ARG(chan->global_identifier)); + + state_not_in_map = + (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR); + + if (!state_not_in_map && chan->registered && + !tor_digest_is_zero(chan->identity_digest)) + /* if it's registered get it out of the digest map */ + channel_remove_from_digest_map(chan); + + memset(chan->identity_digest, 0, + sizeof(chan->identity_digest)); +} + +/** + * Set the identity_digest of a channel + * + * This function sets the identity digest of the remote endpoint for a + * channel; this is intended for use by the lower layer. + */ + +void +channel_set_identity_digest(channel_t *chan, + const char *identity_digest) +{ + int was_in_digest_map, should_be_in_digest_map, state_not_in_map; + + tor_assert(chan); + + log_debug(LD_CHANNEL, + "Setting remote endpoint digest on channel %p with " + "global ID " U64_FORMAT " to digest %s", + chan, U64_PRINTF_ARG(chan->global_identifier), + identity_digest ? + hex_str(identity_digest, DIGEST_LEN) : "(null)"); + + state_not_in_map = + (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR); + was_in_digest_map = + !state_not_in_map && + chan->registered && + !tor_digest_is_zero(chan->identity_digest); + should_be_in_digest_map = + !state_not_in_map && + chan->registered && + (identity_digest && + !tor_digest_is_zero(identity_digest)); + + if (was_in_digest_map) + /* We should always remove it; we'll add it back if we're writing + * in a new digest. + */ + channel_remove_from_digest_map(chan); + + if (identity_digest) { + memcpy(chan->identity_digest, + identity_digest, + sizeof(chan->identity_digest)); + } else { + memset(chan->identity_digest, 0, + sizeof(chan->identity_digest)); + } + + /* Put it in the digest map if we should */ + if (should_be_in_digest_map) + channel_add_to_digest_map(chan); +} + +/** + * Clear the remote end metadata (identity_digest/nickname) of a channel + * + * This function clears all the remote end info from a channel; this is + * intended for use by the lower layer. + */ + +void +channel_clear_remote_end(channel_t *chan) +{ + int state_not_in_map; + + tor_assert(chan); + + log_debug(LD_CHANNEL, + "Clearing remote endpoint identity on channel %p with " + "global ID " U64_FORMAT, + chan, U64_PRINTF_ARG(chan->global_identifier)); + + state_not_in_map = + (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR); + + if (!state_not_in_map && chan->registered && + !tor_digest_is_zero(chan->identity_digest)) + /* if it's registered get it out of the digest map */ + channel_remove_from_digest_map(chan); + + memset(chan->identity_digest, 0, + sizeof(chan->identity_digest)); + tor_free(chan->nickname); +} + +/** + * Set the remote end metadata (identity_digest/nickname) of a channel + * + * This function sets new remote end info on a channel; this is intended + * for use by the lower layer. + */ + +void +channel_set_remote_end(channel_t *chan, + const char *identity_digest, + const char *nickname) +{ + int was_in_digest_map, should_be_in_digest_map, state_not_in_map; + + tor_assert(chan); + + log_debug(LD_CHANNEL, + "Setting remote endpoint identity on channel %p with " + "global ID " U64_FORMAT " to nickname %s, digest %s", + chan, U64_PRINTF_ARG(chan->global_identifier), + nickname ? nickname : "(null)", + identity_digest ? + hex_str(identity_digest, DIGEST_LEN) : "(null)"); + + state_not_in_map = + (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR); + was_in_digest_map = + !state_not_in_map && + chan->registered && + !tor_digest_is_zero(chan->identity_digest); + should_be_in_digest_map = + !state_not_in_map && + chan->registered && + (identity_digest && + !tor_digest_is_zero(identity_digest)); + + if (was_in_digest_map) + /* We should always remove it; we'll add it back if we're writing + * in a new digest. + */ + channel_remove_from_digest_map(chan); + + if (identity_digest) { + memcpy(chan->identity_digest, + identity_digest, + sizeof(chan->identity_digest)); + + } else { + memset(chan->identity_digest, 0, + sizeof(chan->identity_digest)); + } + + tor_free(chan->nickname); + if (nickname) + chan->nickname = tor_strdup(nickname); + + /* Put it in the digest map if we should */ + if (should_be_in_digest_map) + channel_add_to_digest_map(chan); +} + +/** + * Duplicate a cell queue entry; this is a shallow copy intended for use + * in channel_write_cell_queue_entry(). + */ + +static cell_queue_entry_t * +cell_queue_entry_dup(cell_queue_entry_t *q) +{ + cell_queue_entry_t *rv = NULL; + + tor_assert(q); + + rv = tor_malloc(sizeof(*rv)); + memcpy(rv, q, sizeof(*rv)); + + return rv; +} + +/** + * Free a cell_queue_entry_t; the handed_off parameter indicates whether + * the contents were passed to the lower layer (it is responsible for + * them) or not (we should free). + */ + +static void +cell_queue_entry_free(cell_queue_entry_t *q, int handed_off) +{ + if (!q) return; + + if (!handed_off) { + /* + * If we handed it off, the recipient becomes responsible (or + * with packed cells the channel_t subclass calls packed_cell + * free after writing out its contents; see, e.g., + * channel_tls_write_packed_cell_method(). Otherwise, we have + * to take care of it here if possible. + */ + switch (q->type) { + case CELL_QUEUE_FIXED: + if (q->u.fixed.cell) { + /* + * There doesn't seem to be a cell_free() function anywhere in the + * pre-channel code; just use tor_free() + */ + tor_free(q->u.fixed.cell); + } + break; + case CELL_QUEUE_PACKED: + if (q->u.packed.packed_cell) { + packed_cell_free(q->u.packed.packed_cell); + } + break; + case CELL_QUEUE_VAR: + if (q->u.var.var_cell) { + /* + * This one's in connection_or.c; it'd be nice to figure out the + * whole flow of cells from one end to the other and factor the + * cell memory management functions like this out of the specific + * TLS lower layer. + */ + var_cell_free(q->u.var.var_cell); + } + break; + default: + /* + * Nothing we can do if we don't know the type; this will + * have been warned about elsewhere. + */ + break; + } + } + tor_free(q); +} + +/** + * Check whether a cell queue entry is padding; this is a helper function + * for channel_write_cell_queue_entry() + */ + +static int +cell_queue_entry_is_padding(cell_queue_entry_t *q) +{ + tor_assert(q); + + if (q->type == CELL_QUEUE_FIXED) { + if (q->u.fixed.cell) { + if (q->u.fixed.cell->command == CELL_PADDING || + q->u.fixed.cell->command == CELL_VPADDING) { + return 1; + } + } + } else if (q->type == CELL_QUEUE_VAR) { + if (q->u.var.var_cell) { + if (q->u.var.var_cell->command == CELL_PADDING || + q->u.var.var_cell->command == CELL_VPADDING) { + return 1; + } + } + } + + return 0; +} + +/** + * Allocate a new cell queue entry for a fixed-size cell + */ + +static cell_queue_entry_t * +cell_queue_entry_new_fixed(cell_t *cell) +{ + cell_queue_entry_t *q = NULL; + + tor_assert(cell); + + q = tor_malloc(sizeof(*q)); + q->type = CELL_QUEUE_FIXED; + q->u.fixed.cell = cell; + + return q; +} + +/** + * Allocate a new cell queue entry for a variable-size cell + */ + +static cell_queue_entry_t * +cell_queue_entry_new_var(var_cell_t *var_cell) +{ + cell_queue_entry_t *q = NULL; + + tor_assert(var_cell); + + q = tor_malloc(sizeof(*q)); + q->type = CELL_QUEUE_VAR; + q->u.var.var_cell = var_cell; + + return q; +} + +/** + * Write to a channel based on a cell_queue_entry_t + * + * Given a cell_queue_entry_t filled out by the caller, try to send the cell + * and queue it if we can't. + */ + +static void +channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q) +{ + int result = 0, sent = 0; + cell_queue_entry_t *tmp = NULL; + + tor_assert(chan); + tor_assert(q); + + /* Assert that the state makes sense for a cell write */ + tor_assert(chan->state == CHANNEL_STATE_OPENING || + chan->state == CHANNEL_STATE_OPEN || + chan->state == CHANNEL_STATE_MAINT); + + /* Increment the timestamp unless it's padding */ + if (!cell_queue_entry_is_padding(q)) { + chan->timestamp_last_added_nonpadding = approx_time(); + } + + /* Can we send it right out? If so, try */ + if (TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue) && + chan->state == CHANNEL_STATE_OPEN) { + /* Pick the right write function for this cell type and save the result */ + switch (q->type) { + case CELL_QUEUE_FIXED: + tor_assert(chan->write_cell); + tor_assert(q->u.fixed.cell); + result = chan->write_cell(chan, q->u.fixed.cell); + break; + case CELL_QUEUE_PACKED: + tor_assert(chan->write_packed_cell); + tor_assert(q->u.packed.packed_cell); + result = chan->write_packed_cell(chan, q->u.packed.packed_cell); + break; + case CELL_QUEUE_VAR: + tor_assert(chan->write_var_cell); + tor_assert(q->u.var.var_cell); + result = chan->write_var_cell(chan, q->u.var.var_cell); + break; + default: + tor_assert(1); + } + + /* Check if we got it out */ + if (result > 0) { + sent = 1; + /* Timestamp for transmission */ + channel_timestamp_xmit(chan); + /* If we're here the queue is empty, so it's drained too */ + channel_timestamp_drained(chan); + /* Update the counter */ + ++(chan->n_cells_xmitted); + } + } + + if (!sent) { + /* Not sent, queue it */ + /* + * We have to copy the queue entry passed in, since the caller probably + * used the stack. + */ + tmp = cell_queue_entry_dup(q); + TOR_SIMPLEQ_INSERT_TAIL(&chan->outgoing_queue, tmp, next); + /* Try to process the queue? */ + if (chan->state == CHANNEL_STATE_OPEN) channel_flush_cells(chan); + } +} + +/** + * Write a cell to a channel + * + * Write a fixed-length cell to a channel using the write_cell() method. + * This is equivalent to the pre-channels connection_or_write_cell_to_buf(); + * it is called by the transport-independent code to deliver a cell to a + * channel for transmission. + */ + +void +channel_write_cell(channel_t *chan, cell_t *cell) +{ + cell_queue_entry_t q; + + tor_assert(chan); + tor_assert(cell); + + if (chan->state == CHANNEL_STATE_CLOSING) { + log_debug(LD_CHANNEL, "Discarding cell_t %p on closing channel %p with " + "global ID "U64_FORMAT, cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + tor_free(cell); + return; + } + + log_debug(LD_CHANNEL, + "Writing cell_t %p to channel %p with global ID " + U64_FORMAT, + cell, chan, U64_PRINTF_ARG(chan->global_identifier)); + + q.type = CELL_QUEUE_FIXED; + q.u.fixed.cell = cell; + channel_write_cell_queue_entry(chan, &q); +} + +/** + * Write a packed cell to a channel + * + * Write a packed cell to a channel using the write_cell() method. This is + * called by the transport-independent code to deliver a packed cell to a + * channel for transmission. + */ + +void +channel_write_packed_cell(channel_t *chan, packed_cell_t *packed_cell) +{ + cell_queue_entry_t q; + + tor_assert(chan); + tor_assert(packed_cell); + + if (chan->state == CHANNEL_STATE_CLOSING) { + log_debug(LD_CHANNEL, "Discarding packed_cell_t %p on closing channel %p " + "with global ID "U64_FORMAT, packed_cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + packed_cell_free(packed_cell); + return; + } + + log_debug(LD_CHANNEL, + "Writing packed_cell_t %p to channel %p with global ID " + U64_FORMAT, + packed_cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + + q.type = CELL_QUEUE_PACKED; + q.u.packed.packed_cell = packed_cell; + channel_write_cell_queue_entry(chan, &q); +} + +/** + * Write a variable-length cell to a channel + * + * Write a variable-length cell to a channel using the write_cell() method. + * This is equivalent to the pre-channels + * connection_or_write_var_cell_to_buf(); it's called by the transport- + * independent code to deliver a var_cell to a channel for transmission. + */ + +void +channel_write_var_cell(channel_t *chan, var_cell_t *var_cell) +{ + cell_queue_entry_t q; + + tor_assert(chan); + tor_assert(var_cell); + + if (chan->state == CHANNEL_STATE_CLOSING) { + log_debug(LD_CHANNEL, "Discarding var_cell_t %p on closing channel %p " + "with global ID "U64_FORMAT, var_cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + var_cell_free(var_cell); + return; + } + + log_debug(LD_CHANNEL, + "Writing var_cell_t %p to channel %p with global ID " + U64_FORMAT, + var_cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + + q.type = CELL_QUEUE_VAR; + q.u.var.var_cell = var_cell; + channel_write_cell_queue_entry(chan, &q); +} + +/** + * Change channel state + * + * This internal and subclass use only function is used to change channel + * state, performing all transition validity checks and whatever actions + * are appropriate to the state transition in question. + */ + +void +channel_change_state(channel_t *chan, channel_state_t to_state) +{ + channel_state_t from_state; + unsigned char was_active, is_active; + unsigned char was_in_id_map, is_in_id_map; + + tor_assert(chan); + from_state = chan->state; + + tor_assert(channel_state_is_valid(from_state)); + tor_assert(channel_state_is_valid(to_state)); + tor_assert(channel_state_can_transition(chan->state, to_state)); + + /* Check for no-op transitions */ + if (from_state == to_state) { + log_debug(LD_CHANNEL, + "Got no-op transition from \"%s\" to itself on channel %p" + "(global ID " U64_FORMAT ")", + channel_state_to_string(to_state), + chan, U64_PRINTF_ARG(chan->global_identifier)); + return; + } + + /* If we're going to a closing or closed state, we must have a reason set */ + if (to_state == CHANNEL_STATE_CLOSING || + to_state == CHANNEL_STATE_CLOSED || + to_state == CHANNEL_STATE_ERROR) { + tor_assert(chan->reason_for_closing != CHANNEL_NOT_CLOSING); + } + + /* + * We need to maintain the queues here for some transitions: + * when we enter CHANNEL_STATE_OPEN (especially from CHANNEL_STATE_MAINT) + * we may have a backlog of cells to transmit, so drain the queues in + * that case, and when going to CHANNEL_STATE_CLOSED the subclass + * should have made sure to finish sending things (or gone to + * CHANNEL_STATE_ERROR if not possible), so we assert for that here. + */ + + log_debug(LD_CHANNEL, + "Changing state of channel %p (global ID " U64_FORMAT + ") from \"%s\" to \"%s\"", + chan, + U64_PRINTF_ARG(chan->global_identifier), + channel_state_to_string(chan->state), + channel_state_to_string(to_state)); + + chan->state = to_state; + + /* Need to add to the right lists if the channel is registered */ + if (chan->registered) { + was_active = !(from_state == CHANNEL_STATE_CLOSED || + from_state == CHANNEL_STATE_ERROR); + is_active = !(to_state == CHANNEL_STATE_CLOSED || + to_state == CHANNEL_STATE_ERROR); + + /* Need to take off active list and put on finished list? */ + if (was_active && !is_active) { + if (active_channels) smartlist_remove(active_channels, chan); + if (!finished_channels) finished_channels = smartlist_new(); + smartlist_add(finished_channels, chan); + } + /* Need to put on active list? */ + else if (!was_active && is_active) { + if (finished_channels) smartlist_remove(finished_channels, chan); + if (!active_channels) active_channels = smartlist_new(); + smartlist_add(active_channels, chan); + } + + if (!tor_digest_is_zero(chan->identity_digest)) { + /* Now we need to handle the identity map */ + was_in_id_map = !(from_state == CHANNEL_STATE_CLOSING || + from_state == CHANNEL_STATE_CLOSED || + from_state == CHANNEL_STATE_ERROR); + is_in_id_map = !(to_state == CHANNEL_STATE_CLOSING || + to_state == CHANNEL_STATE_CLOSED || + to_state == CHANNEL_STATE_ERROR); + + if (!was_in_id_map && is_in_id_map) channel_add_to_digest_map(chan); + else if (was_in_id_map && !is_in_id_map) + channel_remove_from_digest_map(chan); + } + } + + /* Tell circuits if we opened and stuff */ + if (to_state == CHANNEL_STATE_OPEN) { + channel_do_open_actions(chan); + chan->has_been_open = 1; + + /* Check for queued cells to process */ + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) + channel_process_cells(chan); + if (! TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) + channel_flush_cells(chan); + } else if (to_state == CHANNEL_STATE_CLOSED || + to_state == CHANNEL_STATE_ERROR) { + /* Assert that all queues are empty */ + tor_assert(TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)); + tor_assert(TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)); + } +} + +/** + * Change channel listener state + * + * This internal and subclass use only function is used to change channel + * listener state, performing all transition validity checks and whatever + * actions are appropriate to the state transition in question. + */ + +void +channel_listener_change_state(channel_listener_t *chan_l, + channel_listener_state_t to_state) +{ + channel_listener_state_t from_state; + unsigned char was_active, is_active; + + tor_assert(chan_l); + from_state = chan_l->state; + + tor_assert(channel_listener_state_is_valid(from_state)); + tor_assert(channel_listener_state_is_valid(to_state)); + tor_assert(channel_listener_state_can_transition(chan_l->state, to_state)); + + /* Check for no-op transitions */ + if (from_state == to_state) { + log_debug(LD_CHANNEL, + "Got no-op transition from \"%s\" to itself on channel " + "listener %p (global ID " U64_FORMAT ")", + channel_listener_state_to_string(to_state), + chan_l, U64_PRINTF_ARG(chan_l->global_identifier)); + return; + } + + /* If we're going to a closing or closed state, we must have a reason set */ + if (to_state == CHANNEL_LISTENER_STATE_CLOSING || + to_state == CHANNEL_LISTENER_STATE_CLOSED || + to_state == CHANNEL_LISTENER_STATE_ERROR) { + tor_assert(chan_l->reason_for_closing != CHANNEL_LISTENER_NOT_CLOSING); + } + + /* + * We need to maintain the queues here for some transitions: + * when we enter CHANNEL_STATE_OPEN (especially from CHANNEL_STATE_MAINT) + * we may have a backlog of cells to transmit, so drain the queues in + * that case, and when going to CHANNEL_STATE_CLOSED the subclass + * should have made sure to finish sending things (or gone to + * CHANNEL_STATE_ERROR if not possible), so we assert for that here. + */ + + log_debug(LD_CHANNEL, + "Changing state of channel listener %p (global ID " U64_FORMAT + "from \"%s\" to \"%s\"", + chan_l, U64_PRINTF_ARG(chan_l->global_identifier), + channel_listener_state_to_string(chan_l->state), + channel_listener_state_to_string(to_state)); + + chan_l->state = to_state; + + /* Need to add to the right lists if the channel listener is registered */ + if (chan_l->registered) { + was_active = !(from_state == CHANNEL_LISTENER_STATE_CLOSED || + from_state == CHANNEL_LISTENER_STATE_ERROR); + is_active = !(to_state == CHANNEL_LISTENER_STATE_CLOSED || + to_state == CHANNEL_LISTENER_STATE_ERROR); + + /* Need to take off active list and put on finished list? */ + if (was_active && !is_active) { + if (active_listeners) smartlist_remove(active_listeners, chan_l); + if (!finished_listeners) finished_listeners = smartlist_new(); + smartlist_add(finished_listeners, chan_l); + } + /* Need to put on active list? */ + else if (!was_active && is_active) { + if (finished_listeners) smartlist_remove(finished_listeners, chan_l); + if (!active_listeners) active_listeners = smartlist_new(); + smartlist_add(active_listeners, chan_l); + } + } + + if (to_state == CHANNEL_LISTENER_STATE_CLOSED || + to_state == CHANNEL_LISTENER_STATE_ERROR) { + /* Assert that the queue is empty */ + tor_assert(!(chan_l->incoming_list) || + smartlist_len(chan_l->incoming_list) == 0); + } +} + +/** + * Try to flush cells to the lower layer + * + * this is called by the lower layer to indicate that it wants more cells; + * it will try to write up to num_cells cells from the channel's cell queue or + * from circuits active on that channel, or as many as it has available if + * num_cells == -1. + */ + +#define MAX_CELLS_TO_GET_FROM_CIRCUITS_FOR_UNLIMITED 256 + +ssize_t +channel_flush_some_cells(channel_t *chan, ssize_t num_cells) +{ + unsigned int unlimited = 0; + ssize_t flushed = 0; + int num_cells_from_circs, clamped_num_cells; + + tor_assert(chan); + + if (num_cells < 0) unlimited = 1; + if (!unlimited && num_cells <= flushed) goto done; + + /* If we aren't in CHANNEL_STATE_OPEN, nothing goes through */ + if (chan->state == CHANNEL_STATE_OPEN) { + /* Try to flush as much as we can that's already queued */ + flushed += channel_flush_some_cells_from_outgoing_queue(chan, + (unlimited ? -1 : num_cells - flushed)); + if (!unlimited && num_cells <= flushed) goto done; + + if (circuitmux_num_cells(chan->cmux) > 0) { + /* Calculate number of cells, including clamp */ + if (unlimited) { + clamped_num_cells = MAX_CELLS_TO_GET_FROM_CIRCUITS_FOR_UNLIMITED; + } else { + if (num_cells - flushed > + MAX_CELLS_TO_GET_FROM_CIRCUITS_FOR_UNLIMITED) { + clamped_num_cells = MAX_CELLS_TO_GET_FROM_CIRCUITS_FOR_UNLIMITED; + } else { + clamped_num_cells = (int)(num_cells - flushed); + } + } + /* Try to get more cells from any active circuits */ + num_cells_from_circs = channel_flush_from_first_active_circuit( + chan, clamped_num_cells); + + /* If it claims we got some, process the queue again */ + if (num_cells_from_circs > 0) { + flushed += channel_flush_some_cells_from_outgoing_queue(chan, + (unlimited ? -1 : num_cells - flushed)); + } + } + } + + done: + return flushed; +} + +/** + * Flush cells from just the channel's outgoing cell queue + * + * This gets called from channel_flush_some_cells() above to flush cells + * just from the queue without trying for active_circuits. + */ + +static ssize_t +channel_flush_some_cells_from_outgoing_queue(channel_t *chan, + ssize_t num_cells) +{ + unsigned int unlimited = 0; + ssize_t flushed = 0; + cell_queue_entry_t *q = NULL; + + tor_assert(chan); + tor_assert(chan->write_cell); + tor_assert(chan->write_packed_cell); + tor_assert(chan->write_var_cell); + + if (num_cells < 0) unlimited = 1; + if (!unlimited && num_cells <= flushed) return 0; + + /* If we aren't in CHANNEL_STATE_OPEN, nothing goes through */ + if (chan->state == CHANNEL_STATE_OPEN) { + while ((unlimited || num_cells > flushed) && + NULL != (q = TOR_SIMPLEQ_FIRST(&chan->outgoing_queue))) { + + if (1) { + /* + * Okay, we have a good queue entry, try to give it to the lower + * layer. + */ + switch (q->type) { + case CELL_QUEUE_FIXED: + if (q->u.fixed.cell) { + if (chan->write_cell(chan, + q->u.fixed.cell)) { + ++flushed; + channel_timestamp_xmit(chan); + ++(chan->n_cells_xmitted); + cell_queue_entry_free(q, 1); + q = NULL; + } + /* Else couldn't write it; leave it on the queue */ + } else { + /* This shouldn't happen */ + log_info(LD_CHANNEL, + "Saw broken cell queue entry of type CELL_QUEUE_FIXED " + "with no cell on channel %p " + "(global ID " U64_FORMAT ").", + chan, U64_PRINTF_ARG(chan->global_identifier)); + /* Throw it away */ + cell_queue_entry_free(q, 0); + q = NULL; + } + break; + case CELL_QUEUE_PACKED: + if (q->u.packed.packed_cell) { + if (chan->write_packed_cell(chan, + q->u.packed.packed_cell)) { + ++flushed; + channel_timestamp_xmit(chan); + ++(chan->n_cells_xmitted); + cell_queue_entry_free(q, 1); + q = NULL; + } + /* Else couldn't write it; leave it on the queue */ + } else { + /* This shouldn't happen */ + log_info(LD_CHANNEL, + "Saw broken cell queue entry of type CELL_QUEUE_PACKED " + "with no cell on channel %p " + "(global ID " U64_FORMAT ").", + chan, U64_PRINTF_ARG(chan->global_identifier)); + /* Throw it away */ + cell_queue_entry_free(q, 0); + q = NULL; + } + break; + case CELL_QUEUE_VAR: + if (q->u.var.var_cell) { + if (chan->write_var_cell(chan, + q->u.var.var_cell)) { + ++flushed; + channel_timestamp_xmit(chan); + ++(chan->n_cells_xmitted); + cell_queue_entry_free(q, 1); + q = NULL; + } + /* Else couldn't write it; leave it on the queue */ + } else { + /* This shouldn't happen */ + log_info(LD_CHANNEL, + "Saw broken cell queue entry of type CELL_QUEUE_VAR " + "with no cell on channel %p " + "(global ID " U64_FORMAT ").", + chan, U64_PRINTF_ARG(chan->global_identifier)); + /* Throw it away */ + cell_queue_entry_free(q, 0); + q = NULL; + } + break; + default: + /* Unknown type, log and free it */ + log_info(LD_CHANNEL, + "Saw an unknown cell queue entry type %d on channel %p " + "(global ID " U64_FORMAT "; ignoring it." + " Someone should fix this.", + q->type, chan, U64_PRINTF_ARG(chan->global_identifier)); + cell_queue_entry_free(q, 0); + q = NULL; + } + + /* if q got NULLed out, we used it and should remove the queue entry */ + if (!q) TOR_SIMPLEQ_REMOVE_HEAD(&chan->outgoing_queue, next); + /* No cell removed from list, so we can't go on any further */ + else break; + } + } + } + + /* Did we drain the queue? */ + if (TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) { + channel_timestamp_drained(chan); + } + + return flushed; +} + +/** + * Flush as many cells as we possibly can from the queue + * + * This tries to flush as many cells from the queue as the lower layer + * will take. It just calls channel_flush_some_cells_from_outgoing_queue() + * in unlimited mode. + */ + +void +channel_flush_cells(channel_t *chan) +{ + channel_flush_some_cells_from_outgoing_queue(chan, -1); +} + +/** + * Check if any cells are available + * + * This gets used from the lower layer to check if any more cells are + * available. + */ + +int +channel_more_to_flush(channel_t *chan) +{ + tor_assert(chan); + + /* Check if we have any queued */ + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) + return 1; + + /* Check if any circuits would like to queue some */ + if (circuitmux_num_cells(chan->cmux) > 0) return 1; + + /* Else no */ + return 0; +} + +/** + * Notify the channel we're done flushing the output in the lower layer + * + * Connection.c will call this when we've flushed the output; there's some + * dirreq-related maintenance to do. + */ + +void +channel_notify_flushed(channel_t *chan) +{ + tor_assert(chan); + + if (chan->dirreq_id != 0) + geoip_change_dirreq_state(chan->dirreq_id, + DIRREQ_TUNNELED, + DIRREQ_CHANNEL_BUFFER_FLUSHED); +} + +/** + * Process the queue of incoming channels on a listener + * + * Use a listener's registered callback to process as many entries in the + * queue of incoming channels as possible. + */ + +void +channel_listener_process_incoming(channel_listener_t *listener) +{ + tor_assert(listener); + + /* + * CHANNEL_LISTENER_STATE_CLOSING permitted because we drain the queue + * while closing a listener. + */ + tor_assert(listener->state == CHANNEL_LISTENER_STATE_LISTENING || + listener->state == CHANNEL_LISTENER_STATE_CLOSING); + tor_assert(listener->listener); + + log_debug(LD_CHANNEL, + "Processing queue of incoming connections for channel " + "listener %p (global ID " U64_FORMAT ")", + listener, U64_PRINTF_ARG(listener->global_identifier)); + + if (!(listener->incoming_list)) return; + + SMARTLIST_FOREACH_BEGIN(listener->incoming_list, + channel_t *, chan) { + tor_assert(chan); + + log_debug(LD_CHANNEL, + "Handling incoming channel %p (" U64_FORMAT ") " + "for listener %p (" U64_FORMAT ")", + chan, + U64_PRINTF_ARG(chan->global_identifier), + listener, + U64_PRINTF_ARG(listener->global_identifier)); + /* Make sure this is set correctly */ + channel_mark_incoming(chan); + listener->listener(listener, chan); + } SMARTLIST_FOREACH_END(chan); + + smartlist_free(listener->incoming_list); + listener->incoming_list = NULL; +} + +/** + * Take actions required when a channel becomes open + * + * Handle actions we should do when we know a channel is open; a lot of + * this comes from the old connection_or_set_state_open() of connection_or.c. + * + * Because of this mechanism, future channel_t subclasses should take care + * not to change a channel to from CHANNEL_STATE_OPENING to CHANNEL_STATE_OPEN + * until there is positive confirmation that the network is operational. + * In particular, anything UDP-based should not make this transition until a + * packet is received from the other side. + */ + +void +channel_do_open_actions(channel_t *chan) +{ + tor_addr_t remote_addr; + int started_here, not_using = 0; + time_t now = time(NULL); + + tor_assert(chan); + + started_here = channel_is_outgoing(chan); + + if (started_here) { + circuit_build_times_network_is_live(&circ_times); + rep_hist_note_connect_succeeded(chan->identity_digest, now); + if (entry_guard_register_connect_status( + chan->identity_digest, 1, 0, now) < 0) { + /* Close any circuits pending on this channel. We leave it in state + * 'open' though, because it didn't actually *fail* -- we just + * chose not to use it. */ + log_debug(LD_OR, + "New entry guard was reachable, but closing this " + "connection so we can retry the earlier entry guards."); + circuit_n_chan_done(chan, 0); + not_using = 1; + } + router_set_status(chan->identity_digest, 1); + } else { + /* only report it to the geoip module if it's not a known router */ + if (!router_get_by_id_digest(chan->identity_digest)) { + if (channel_get_addr_if_possible(chan, &remote_addr)) { + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &remote_addr, + now); + } + /* Otherwise the underlying transport can't tell us this, so skip it */ + } + } + + if (!not_using) circuit_n_chan_done(chan, 1); +} + +/** + * Queue an incoming channel on a listener + * + * Internal and subclass use only function to queue an incoming channel from + * a listener. A subclass of channel_listener_t should call this when a new + * incoming channel is created. + */ + +void +channel_listener_queue_incoming(channel_listener_t *listener, + channel_t *incoming) +{ + int need_to_queue = 0; + + tor_assert(listener); + tor_assert(listener->state == CHANNEL_LISTENER_STATE_LISTENING); + tor_assert(incoming); + + log_debug(LD_CHANNEL, + "Queueing incoming channel %p (global ID " U64_FORMAT ") on " + "channel listener %p (global ID " U64_FORMAT ")", + incoming, U64_PRINTF_ARG(incoming->global_identifier), + listener, U64_PRINTF_ARG(listener->global_identifier)); + + /* Do we need to queue it, or can we just call the listener right away? */ + if (!(listener->listener)) need_to_queue = 1; + if (listener->incoming_list && + (smartlist_len(listener->incoming_list) > 0)) + need_to_queue = 1; + + /* If we need to queue and have no queue, create one */ + if (need_to_queue && !(listener->incoming_list)) { + listener->incoming_list = smartlist_new(); + } + + /* Bump the counter and timestamp it */ + channel_listener_timestamp_active(listener); + channel_listener_timestamp_accepted(listener); + ++(listener->n_accepted); + + /* If we don't need to queue, process it right away */ + if (!need_to_queue) { + tor_assert(listener->listener); + listener->listener(listener, incoming); + } + /* + * Otherwise, we need to queue; queue and then process the queue if + * we can. + */ + else { + tor_assert(listener->incoming_list); + smartlist_add(listener->incoming_list, incoming); + if (listener->listener) channel_listener_process_incoming(listener); + } +} + +/** + * Process queued incoming cells + * + * Process as many queued cells as we can from the incoming + * cell queue. + */ + +void +channel_process_cells(channel_t *chan) +{ + cell_queue_entry_t *q; + tor_assert(chan); + tor_assert(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_MAINT || + chan->state == CHANNEL_STATE_OPEN); + + log_debug(LD_CHANNEL, + "Processing as many incoming cells as we can for channel %p", + chan); + + /* Nothing we can do if we have no registered cell handlers */ + if (!(chan->cell_handler || + chan->var_cell_handler)) return; + /* Nothing we can do if we have no cells */ + if (TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) return; + + /* + * Process cells until we're done or find one we have no current handler + * for. + */ + while (NULL != (q = TOR_SIMPLEQ_FIRST(&chan->incoming_queue))) { + tor_assert(q); + tor_assert(q->type == CELL_QUEUE_FIXED || + q->type == CELL_QUEUE_VAR); + + if (q->type == CELL_QUEUE_FIXED && + chan->cell_handler) { + /* Handle a fixed-length cell */ + TOR_SIMPLEQ_REMOVE_HEAD(&chan->incoming_queue, next); + tor_assert(q->u.fixed.cell); + log_debug(LD_CHANNEL, + "Processing incoming cell_t %p for channel %p (global ID " + U64_FORMAT ")", + q->u.fixed.cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + chan->cell_handler(chan, q->u.fixed.cell); + tor_free(q); + } else if (q->type == CELL_QUEUE_VAR && + chan->var_cell_handler) { + /* Handle a variable-length cell */ + TOR_SIMPLEQ_REMOVE_HEAD(&chan->incoming_queue, next); + tor_assert(q->u.var.var_cell); + log_debug(LD_CHANNEL, + "Processing incoming var_cell_t %p for channel %p (global ID " + U64_FORMAT ")", + q->u.var.var_cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + chan->var_cell_handler(chan, q->u.var.var_cell); + tor_free(q); + } else { + /* Can't handle this one */ + break; + } + } +} + +/** + * Queue incoming cell + * + * This should be called by a channel_t subclass to queue an incoming fixed- + * length cell for processing, and process it if possible. + */ + +void +channel_queue_cell(channel_t *chan, cell_t *cell) +{ + int need_to_queue = 0; + cell_queue_entry_t *q; + + tor_assert(chan); + tor_assert(cell); + tor_assert(chan->state == CHANNEL_STATE_OPEN); + + /* Do we need to queue it, or can we just call the handler right away? */ + if (!(chan->cell_handler)) need_to_queue = 1; + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) + need_to_queue = 1; + + /* Timestamp for receiving */ + channel_timestamp_recv(chan); + + /* Update the counter */ + ++(chan->n_cells_recved); + + /* If we don't need to queue we can just call cell_handler */ + if (!need_to_queue) { + tor_assert(chan->cell_handler); + log_debug(LD_CHANNEL, + "Directly handling incoming cell_t %p for channel %p " + "(global ID " U64_FORMAT ")", + cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + chan->cell_handler(chan, cell); + } else { + /* Otherwise queue it and then process the queue if possible. */ + q = cell_queue_entry_new_fixed(cell); + log_debug(LD_CHANNEL, + "Queueing incoming cell_t %p for channel %p " + "(global ID " U64_FORMAT ")", + cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + TOR_SIMPLEQ_INSERT_TAIL(&chan->incoming_queue, q, next); + if (chan->cell_handler || + chan->var_cell_handler) { + channel_process_cells(chan); + } + } +} + +/** + * Queue incoming variable-length cell + * + * This should be called by a channel_t subclass to queue an incoming + * variable-length cell for processing, and process it if possible. + */ + +void +channel_queue_var_cell(channel_t *chan, var_cell_t *var_cell) +{ + int need_to_queue = 0; + cell_queue_entry_t *q; + + tor_assert(chan); + tor_assert(var_cell); + tor_assert(chan->state == CHANNEL_STATE_OPEN); + + /* Do we need to queue it, or can we just call the handler right away? */ + if (!(chan->var_cell_handler)) need_to_queue = 1; + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) + need_to_queue = 1; + + /* Timestamp for receiving */ + channel_timestamp_recv(chan); + + /* Update the counter */ + ++(chan->n_cells_recved); + + /* If we don't need to queue we can just call cell_handler */ + if (!need_to_queue) { + tor_assert(chan->var_cell_handler); + log_debug(LD_CHANNEL, + "Directly handling incoming var_cell_t %p for channel %p " + "(global ID " U64_FORMAT ")", + var_cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + chan->var_cell_handler(chan, var_cell); + } else { + /* Otherwise queue it and then process the queue if possible. */ + q = cell_queue_entry_new_var(var_cell); + log_debug(LD_CHANNEL, + "Queueing incoming var_cell_t %p for channel %p " + "(global ID " U64_FORMAT ")", + var_cell, chan, + U64_PRINTF_ARG(chan->global_identifier)); + TOR_SIMPLEQ_INSERT_TAIL(&chan->incoming_queue, q, next); + if (chan->cell_handler || + chan->var_cell_handler) { + channel_process_cells(chan); + } + } +} + +/** + * Send destroy cell on a channel + * + * Write a destroy cell with circ ID <b>circ_id</b> and reason <b>reason</b> + * onto channel <b>chan</b>. Don't perform range-checking on reason: + * we may want to propagate reasons from other cells. + */ + +int +channel_send_destroy(circid_t circ_id, channel_t *chan, int reason) +{ + cell_t cell; + + tor_assert(chan); + + /* Check to make sure we can send on this channel first */ + if (!(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR)) { + memset(&cell, 0, sizeof(cell_t)); + cell.circ_id = circ_id; + cell.command = CELL_DESTROY; + cell.payload[0] = (uint8_t) reason; + log_debug(LD_OR, + "Sending destroy (circID %u) on channel %p " + "(global ID " U64_FORMAT ")", + (unsigned)circ_id, chan, + U64_PRINTF_ARG(chan->global_identifier)); + + channel_write_cell(chan, &cell); + } else { + log_warn(LD_BUG, + "Someone called channel_send_destroy() for circID %u " + "on a channel " U64_FORMAT " at %p in state %s (%d)", + (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier), + chan, channel_state_to_string(chan->state), + chan->state); + } + + return 0; +} + +/** + * Dump channel statistics to the log + * + * This is called from dumpstats() in main.c and spams the log with + * statistics on channels. + */ + +void +channel_dumpstats(int severity) +{ + if (all_channels && smartlist_len(all_channels) > 0) { + tor_log(severity, LD_GENERAL, + "Dumping statistics about %d channels:", + smartlist_len(all_channels)); + tor_log(severity, LD_GENERAL, + "%d are active, and %d are done and waiting for cleanup", + (active_channels != NULL) ? + smartlist_len(active_channels) : 0, + (finished_channels != NULL) ? + smartlist_len(finished_channels) : 0); + + SMARTLIST_FOREACH(all_channels, channel_t *, chan, + channel_dump_statistics(chan, severity)); + + tor_log(severity, LD_GENERAL, + "Done spamming about channels now"); + } else { + tor_log(severity, LD_GENERAL, + "No channels to dump"); + } +} + +/** + * Dump channel listener statistics to the log + * + * This is called from dumpstats() in main.c and spams the log with + * statistics on channel listeners. + */ + +void +channel_listener_dumpstats(int severity) +{ + if (all_listeners && smartlist_len(all_listeners) > 0) { + tor_log(severity, LD_GENERAL, + "Dumping statistics about %d channel listeners:", + smartlist_len(all_listeners)); + tor_log(severity, LD_GENERAL, + "%d are active and %d are done and waiting for cleanup", + (active_listeners != NULL) ? + smartlist_len(active_listeners) : 0, + (finished_listeners != NULL) ? + smartlist_len(finished_listeners) : 0); + + SMARTLIST_FOREACH(all_listeners, channel_listener_t *, chan_l, + channel_listener_dump_statistics(chan_l, severity)); + + tor_log(severity, LD_GENERAL, + "Done spamming about channel listeners now"); + } else { + tor_log(severity, LD_GENERAL, + "No channel listeners to dump"); + } +} + +/** + * Set the cmux policy on all active channels + */ + +void +channel_set_cmux_policy_everywhere(circuitmux_policy_t *pol) +{ + if (!active_channels) return; + + SMARTLIST_FOREACH_BEGIN(active_channels, channel_t *, curr) { + if (curr->cmux) { + circuitmux_set_policy(curr->cmux, pol); + } + } SMARTLIST_FOREACH_END(curr); +} + +/** + * Clean up channels + * + * This gets called periodically from run_scheduled_events() in main.c; + * it cleans up after closed channels. + */ + +void +channel_run_cleanup(void) +{ + channel_t *tmp = NULL; + + /* Check if we need to do anything */ + if (!finished_channels || smartlist_len(finished_channels) == 0) return; + + /* Iterate through finished_channels and get rid of them */ + SMARTLIST_FOREACH_BEGIN(finished_channels, channel_t *, curr) { + tmp = curr; + /* Remove it from the list */ + SMARTLIST_DEL_CURRENT(finished_channels, curr); + /* Also unregister it */ + channel_unregister(tmp); + /* ... and free it */ + channel_free(tmp); + } SMARTLIST_FOREACH_END(curr); +} + +/** + * Clean up channel listeners + * + * This gets called periodically from run_scheduled_events() in main.c; + * it cleans up after closed channel listeners. + */ + +void +channel_listener_run_cleanup(void) +{ + channel_listener_t *tmp = NULL; + + /* Check if we need to do anything */ + if (!finished_listeners || smartlist_len(finished_listeners) == 0) return; + + /* Iterate through finished_channels and get rid of them */ + SMARTLIST_FOREACH_BEGIN(finished_listeners, channel_listener_t *, curr) { + tmp = curr; + /* Remove it from the list */ + SMARTLIST_DEL_CURRENT(finished_listeners, curr); + /* Also unregister it */ + channel_listener_unregister(tmp); + /* ... and free it */ + channel_listener_free(tmp); + } SMARTLIST_FOREACH_END(curr); +} + +/** + * Free a list of channels for channel_free_all() + */ + +static void +channel_free_list(smartlist_t *channels, int mark_for_close) +{ + if (!channels) return; + + SMARTLIST_FOREACH_BEGIN(channels, channel_t *, curr) { + /* Deregister and free it */ + tor_assert(curr); + log_debug(LD_CHANNEL, + "Cleaning up channel %p (global ID " U64_FORMAT ") " + "in state %s (%d)", + curr, U64_PRINTF_ARG(curr->global_identifier), + channel_state_to_string(curr->state), curr->state); + /* Detach circuits early so they can find the channel */ + if (curr->cmux) { + circuitmux_detach_all_circuits(curr->cmux); + } + channel_unregister(curr); + if (mark_for_close) { + if (!(curr->state == CHANNEL_STATE_CLOSING || + curr->state == CHANNEL_STATE_CLOSED || + curr->state == CHANNEL_STATE_ERROR)) { + channel_mark_for_close(curr); + } + channel_force_free(curr); + } else channel_free(curr); + } SMARTLIST_FOREACH_END(curr); +} + +/** + * Free a list of channel listeners for channel_free_all() + */ + +static void +channel_listener_free_list(smartlist_t *listeners, int mark_for_close) +{ + if (!listeners) return; + + SMARTLIST_FOREACH_BEGIN(listeners, channel_listener_t *, curr) { + /* Deregister and free it */ + tor_assert(curr); + log_debug(LD_CHANNEL, + "Cleaning up channel listener %p (global ID " U64_FORMAT ") " + "in state %s (%d)", + curr, U64_PRINTF_ARG(curr->global_identifier), + channel_listener_state_to_string(curr->state), curr->state); + channel_listener_unregister(curr); + if (mark_for_close) { + if (!(curr->state == CHANNEL_LISTENER_STATE_CLOSING || + curr->state == CHANNEL_LISTENER_STATE_CLOSED || + curr->state == CHANNEL_LISTENER_STATE_ERROR)) { + channel_listener_mark_for_close(curr); + } + channel_listener_force_free(curr); + } else channel_listener_free(curr); + } SMARTLIST_FOREACH_END(curr); +} + +/** + * Close all channels and free everything + * + * This gets called from tor_free_all() in main.c to clean up on exit. + * It will close all registered channels and free associated storage, + * then free the all_channels, active_channels, listening_channels and + * finished_channels lists and also channel_identity_map. + */ + +void +channel_free_all(void) +{ + log_debug(LD_CHANNEL, + "Shutting down channels..."); + + /* First, let's go for finished channels */ + if (finished_channels) { + channel_free_list(finished_channels, 0); + smartlist_free(finished_channels); + finished_channels = NULL; + } + + /* Now the finished listeners */ + if (finished_listeners) { + channel_listener_free_list(finished_listeners, 0); + smartlist_free(finished_listeners); + finished_listeners = NULL; + } + + /* Now all active channels */ + if (active_channels) { + channel_free_list(active_channels, 1); + smartlist_free(active_channels); + active_channels = NULL; + } + + /* Now all active listeners */ + if (active_listeners) { + channel_listener_free_list(active_listeners, 1); + smartlist_free(active_listeners); + active_listeners = NULL; + } + + /* Now all channels, in case any are left over */ + if (all_channels) { + channel_free_list(all_channels, 1); + smartlist_free(all_channels); + all_channels = NULL; + } + + /* Now all listeners, in case any are left over */ + if (all_listeners) { + channel_listener_free_list(all_listeners, 1); + smartlist_free(all_listeners); + all_listeners = NULL; + } + + /* Now free channel_identity_map */ + log_debug(LD_CHANNEL, + "Freeing channel_identity_map"); + /* Geez, anything still left over just won't die ... let it leak then */ + HT_CLEAR(channel_idmap, &channel_identity_map); + + log_debug(LD_CHANNEL, + "Done cleaning up after channels"); +} + +/** + * Connect to a given addr/port/digest + * + * This sets up a new outgoing channel; in the future if multiple + * channel_t subclasses are available, this is where the selection policy + * should go. It may also be desirable to fold port into tor_addr_t + * or make a new type including a tor_addr_t and port, so we have a + * single abstract object encapsulating all the protocol details of + * how to contact an OR. + */ + +channel_t * +channel_connect(const tor_addr_t *addr, uint16_t port, + const char *id_digest) +{ + return channel_tls_connect(addr, port, id_digest); +} + +/** + * Decide which of two channels to prefer for extending a circuit + * + * This function is called while extending a circuit and returns true iff + * a is 'better' than b. The most important criterion here is that a + * canonical channel is always better than a non-canonical one, but the + * number of circuits and the age are used as tie-breakers. + * + * This is based on the former connection_or_is_better() of connection_or.c + */ + +int +channel_is_better(time_t now, channel_t *a, channel_t *b, + int forgive_new_connections) +{ + int a_grace, b_grace; + int a_is_canonical, b_is_canonical; + int a_has_circs, b_has_circs; + + /* + * Do not definitively deprecate a new channel with no circuits on it + * until this much time has passed. + */ +#define NEW_CHAN_GRACE_PERIOD (15*60) + + tor_assert(a); + tor_assert(b); + + /* Check if one is canonical and the other isn't first */ + a_is_canonical = channel_is_canonical(a); + b_is_canonical = channel_is_canonical(b); + + if (a_is_canonical && !b_is_canonical) return 1; + if (!a_is_canonical && b_is_canonical) return 0; + + /* + * Okay, if we're here they tied on canonicity. Next we check if + * they have any circuits, and if one does and the other doesn't, + * we prefer the one that does, unless we are forgiving and the + * one that has no circuits is in its grace period. + */ + + a_has_circs = (channel_num_circuits(a) > 0); + b_has_circs = (channel_num_circuits(b) > 0); + a_grace = (forgive_new_connections && + (now < channel_when_created(a) + NEW_CHAN_GRACE_PERIOD)); + b_grace = (forgive_new_connections && + (now < channel_when_created(b) + NEW_CHAN_GRACE_PERIOD)); + + if (a_has_circs && !b_has_circs && !b_grace) return 1; + if (!a_has_circs && b_has_circs && !a_grace) return 0; + + /* They tied on circuits too; just prefer whichever is newer */ + + if (channel_when_created(a) > channel_when_created(b)) return 1; + else return 0; +} + +/** + * Get a channel to extend a circuit + * + * Pick a suitable channel to extend a circuit to given the desired digest + * the address we believe is correct for that digest; this tries to see + * if we already have one for the requested endpoint, but if there is no good + * channel, set *msg_out to a message describing the channel's state + * and our next action, and set *launch_out to a boolean indicated whether + * the caller should try to launch a new channel with channel_connect(). + */ + +channel_t * +channel_get_for_extend(const char *digest, + const tor_addr_t *target_addr, + const char **msg_out, + int *launch_out) +{ + channel_t *chan, *best = NULL; + int n_inprogress_goodaddr = 0, n_old = 0; + int n_noncanonical = 0, n_possible = 0; + time_t now = approx_time(); + + tor_assert(msg_out); + tor_assert(launch_out); + + chan = channel_find_by_remote_digest(digest); + + /* Walk the list, unrefing the old one and refing the new at each + * iteration. + */ + for (; chan; chan = channel_next_with_digest(chan)) { + tor_assert(tor_memeq(chan->identity_digest, + digest, DIGEST_LEN)); + + if (chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR) + continue; + + /* Never return a channel on which the other end appears to be + * a client. */ + if (channel_is_client(chan)) { + continue; + } + + /* Never return a non-open connection. */ + if (chan->state != CHANNEL_STATE_OPEN) { + /* If the address matches, don't launch a new connection for this + * circuit. */ + if (channel_matches_target_addr_for_extend(chan, target_addr)) + ++n_inprogress_goodaddr; + continue; + } + + /* Never return a connection that shouldn't be used for circs. */ + if (channel_is_bad_for_new_circs(chan)) { + ++n_old; + continue; + } + + /* Never return a non-canonical connection using a recent link protocol + * if the address is not what we wanted. + * + * The channel_is_canonical_is_reliable() function asks the lower layer + * if we should trust channel_is_canonical(). The below is from the + * comments of the old circuit_or_get_for_extend() and applies when + * the lower-layer transport is channel_tls_t. + * + * (For old link protocols, we can't rely on is_canonical getting + * set properly if we're talking to the right address, since we might + * have an out-of-date descriptor, and we will get no NETINFO cell to + * tell us about the right address.) + */ + if (!channel_is_canonical(chan) && + channel_is_canonical_is_reliable(chan) && + !channel_matches_target_addr_for_extend(chan, target_addr)) { + ++n_noncanonical; + continue; + } + + ++n_possible; + + if (!best) { + best = chan; /* If we have no 'best' so far, this one is good enough. */ + continue; + } + + if (channel_is_better(now, chan, best, 0)) + best = chan; + } + + if (best) { + *msg_out = "Connection is fine; using it."; + *launch_out = 0; + return best; + } else if (n_inprogress_goodaddr) { + *msg_out = "Connection in progress; waiting."; + *launch_out = 0; + return NULL; + } else if (n_old || n_noncanonical) { + *msg_out = "Connections all too old, or too non-canonical. " + " Launching a new one."; + *launch_out = 1; + return NULL; + } else { + *msg_out = "Not connected. Connecting."; + *launch_out = 1; + return NULL; + } +} + +/** + * Describe the transport subclass for a channel + * + * Invoke a method to get a string description of the lower-layer + * transport for this channel. + */ + +const char * +channel_describe_transport(channel_t *chan) +{ + tor_assert(chan); + tor_assert(chan->describe_transport); + + return chan->describe_transport(chan); +} + +/** + * Describe the transport subclass for a channel listener + * + * Invoke a method to get a string description of the lower-layer + * transport for this channel listener. + */ + +const char * +channel_listener_describe_transport(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + tor_assert(chan_l->describe_transport); + + return chan_l->describe_transport(chan_l); +} + +/** + * Return the number of entries in <b>queue</b> + */ +static int +chan_cell_queue_len(const chan_cell_queue_t *queue) +{ + int r = 0; + cell_queue_entry_t *cell; + TOR_SIMPLEQ_FOREACH(cell, queue, next) + ++r; + return r; +} + +/** + * Dump channel statistics + * + * Dump statistics for one channel to the log + */ + +void +channel_dump_statistics(channel_t *chan, int severity) +{ + double avg, interval, age; + time_t now = time(NULL); + tor_addr_t remote_addr; + int have_remote_addr; + char *remote_addr_str; + + tor_assert(chan); + + age = (double)(now - chan->timestamp_created); + + tor_log(severity, LD_GENERAL, + "Channel " U64_FORMAT " (at %p) with transport %s is in state " + "%s (%d)", + U64_PRINTF_ARG(chan->global_identifier), chan, + channel_describe_transport(chan), + channel_state_to_string(chan->state), chan->state); + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " was created at " U64_FORMAT + " (" U64_FORMAT " seconds ago) " + "and last active at " U64_FORMAT " (" U64_FORMAT " seconds ago)", + U64_PRINTF_ARG(chan->global_identifier), + U64_PRINTF_ARG(chan->timestamp_created), + U64_PRINTF_ARG(now - chan->timestamp_created), + U64_PRINTF_ARG(chan->timestamp_active), + U64_PRINTF_ARG(now - chan->timestamp_active)); + + /* Handle digest and nickname */ + if (!tor_digest_is_zero(chan->identity_digest)) { + if (chan->nickname) { + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " says it is connected " + "to an OR with digest %s and nickname %s", + U64_PRINTF_ARG(chan->global_identifier), + hex_str(chan->identity_digest, DIGEST_LEN), + chan->nickname); + } else { + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " says it is connected " + "to an OR with digest %s and no known nickname", + U64_PRINTF_ARG(chan->global_identifier), + hex_str(chan->identity_digest, DIGEST_LEN)); + } + } else { + if (chan->nickname) { + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " does not know the digest" + " of the OR it is connected to, but reports its nickname is %s", + U64_PRINTF_ARG(chan->global_identifier), + chan->nickname); + } else { + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " does not know the digest" + " or the nickname of the OR it is connected to", + U64_PRINTF_ARG(chan->global_identifier)); + } + } + + /* Handle remote address and descriptions */ + have_remote_addr = channel_get_addr_if_possible(chan, &remote_addr); + if (have_remote_addr) { + char *actual = tor_strdup(channel_get_actual_remote_descr(chan)); + remote_addr_str = tor_dup_addr(&remote_addr); + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " says its remote address" + " is %s, and gives a canonical description of \"%s\" and an " + "actual description of \"%s\"", + U64_PRINTF_ARG(chan->global_identifier), + remote_addr_str, + channel_get_canonical_remote_descr(chan), + actual); + tor_free(remote_addr_str); + tor_free(actual); + } else { + char *actual = tor_strdup(channel_get_actual_remote_descr(chan)); + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " does not know its remote " + "address, but gives a canonical description of \"%s\" and an " + "actual description of \"%s\"", + U64_PRINTF_ARG(chan->global_identifier), + channel_get_canonical_remote_descr(chan), + actual); + tor_free(actual); + } + + /* Handle marks */ + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has these marks: %s %s %s " + "%s %s %s", + U64_PRINTF_ARG(chan->global_identifier), + channel_is_bad_for_new_circs(chan) ? + "bad_for_new_circs" : "!bad_for_new_circs", + channel_is_canonical(chan) ? + "canonical" : "!canonical", + channel_is_canonical_is_reliable(chan) ? + "is_canonical_is_reliable" : + "!is_canonical_is_reliable", + channel_is_client(chan) ? + "client" : "!client", + channel_is_local(chan) ? + "local" : "!local", + channel_is_incoming(chan) ? + "incoming" : "outgoing"); + + /* Describe queues */ + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has %d queued incoming cells" + " and %d queued outgoing cells", + U64_PRINTF_ARG(chan->global_identifier), + chan_cell_queue_len(&chan->incoming_queue), + chan_cell_queue_len(&chan->outgoing_queue)); + + /* Describe circuits */ + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has %d active circuits out of" + " %d in total", + U64_PRINTF_ARG(chan->global_identifier), + (chan->cmux != NULL) ? + circuitmux_num_active_circuits(chan->cmux) : 0, + (chan->cmux != NULL) ? + circuitmux_num_circuits(chan->cmux) : 0); + + /* Describe timestamps */ + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " was last used by a " + "client at " U64_FORMAT " (" U64_FORMAT " seconds ago)", + U64_PRINTF_ARG(chan->global_identifier), + U64_PRINTF_ARG(chan->timestamp_client), + U64_PRINTF_ARG(now - chan->timestamp_client)); + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " was last drained at " + U64_FORMAT " (" U64_FORMAT " seconds ago)", + U64_PRINTF_ARG(chan->global_identifier), + U64_PRINTF_ARG(chan->timestamp_drained), + U64_PRINTF_ARG(now - chan->timestamp_drained)); + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " last received a cell " + "at " U64_FORMAT " (" U64_FORMAT " seconds ago)", + U64_PRINTF_ARG(chan->global_identifier), + U64_PRINTF_ARG(chan->timestamp_recv), + U64_PRINTF_ARG(now - chan->timestamp_recv)); + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " last trasmitted a cell " + "at " U64_FORMAT " (" U64_FORMAT " seconds ago)", + U64_PRINTF_ARG(chan->global_identifier), + U64_PRINTF_ARG(chan->timestamp_xmit), + U64_PRINTF_ARG(now - chan->timestamp_xmit)); + + /* Describe counters and rates */ + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has received " + U64_FORMAT " cells and transmitted " U64_FORMAT, + U64_PRINTF_ARG(chan->global_identifier), + U64_PRINTF_ARG(chan->n_cells_recved), + U64_PRINTF_ARG(chan->n_cells_xmitted)); + if (now > chan->timestamp_created && + chan->timestamp_created > 0) { + if (chan->n_cells_recved > 0) { + avg = (double)(chan->n_cells_recved) / age; + if (avg >= 1.0) { + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has averaged %f " + "cells received per second", + U64_PRINTF_ARG(chan->global_identifier), avg); + } else if (avg >= 0.0) { + interval = 1.0 / avg; + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has averaged %f " + "seconds between received cells", + U64_PRINTF_ARG(chan->global_identifier), interval); + } + } + if (chan->n_cells_xmitted > 0) { + avg = (double)(chan->n_cells_xmitted) / age; + if (avg >= 1.0) { + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has averaged %f " + "cells transmitted per second", + U64_PRINTF_ARG(chan->global_identifier), avg); + } else if (avg >= 0.0) { + interval = 1.0 / avg; + tor_log(severity, LD_GENERAL, + " * Channel " U64_FORMAT " has averaged %f " + "seconds between transmitted cells", + U64_PRINTF_ARG(chan->global_identifier), interval); + } + } + } + + /* Dump anything the lower layer has to say */ + channel_dump_transport_statistics(chan, severity); +} + +/** + * Dump channel listener statistics + * + * Dump statistics for one channel listener to the log + */ + +void +channel_listener_dump_statistics(channel_listener_t *chan_l, int severity) +{ + double avg, interval, age; + time_t now = time(NULL); + + tor_assert(chan_l); + + age = (double)(now - chan_l->timestamp_created); + + tor_log(severity, LD_GENERAL, + "Channel listener " U64_FORMAT " (at %p) with transport %s is in " + "state %s (%d)", + U64_PRINTF_ARG(chan_l->global_identifier), chan_l, + channel_listener_describe_transport(chan_l), + channel_listener_state_to_string(chan_l->state), chan_l->state); + tor_log(severity, LD_GENERAL, + " * Channel listener " U64_FORMAT " was created at " U64_FORMAT + " (" U64_FORMAT " seconds ago) " + "and last active at " U64_FORMAT " (" U64_FORMAT " seconds ago)", + U64_PRINTF_ARG(chan_l->global_identifier), + U64_PRINTF_ARG(chan_l->timestamp_created), + U64_PRINTF_ARG(now - chan_l->timestamp_created), + U64_PRINTF_ARG(chan_l->timestamp_active), + U64_PRINTF_ARG(now - chan_l->timestamp_active)); + + tor_log(severity, LD_GENERAL, + " * Channel listener " U64_FORMAT " last accepted an incoming " + "channel at " U64_FORMAT " (" U64_FORMAT " seconds ago) " + "and has accepted " U64_FORMAT " channels in total", + U64_PRINTF_ARG(chan_l->global_identifier), + U64_PRINTF_ARG(chan_l->timestamp_accepted), + U64_PRINTF_ARG(now - chan_l->timestamp_accepted), + U64_PRINTF_ARG(chan_l->n_accepted)); + + /* + * If it's sensible to do so, get the rate of incoming channels on this + * listener + */ + if (now > chan_l->timestamp_created && + chan_l->timestamp_created > 0 && + chan_l->n_accepted > 0) { + avg = (double)(chan_l->n_accepted) / age; + if (avg >= 1.0) { + tor_log(severity, LD_GENERAL, + " * Channel listener " U64_FORMAT " has averaged %f incoming " + "channels per second", + U64_PRINTF_ARG(chan_l->global_identifier), avg); + } else if (avg >= 0.0) { + interval = 1.0 / avg; + tor_log(severity, LD_GENERAL, + " * Channel listener " U64_FORMAT " has averaged %f seconds " + "between incoming channels", + U64_PRINTF_ARG(chan_l->global_identifier), interval); + } + } + + /* Dump anything the lower layer has to say */ + channel_listener_dump_transport_statistics(chan_l, severity); +} + +/** + * Invoke transport-specific stats dump for channel + * + * If there is a lower-layer statistics dump method, invoke it + */ + +void +channel_dump_transport_statistics(channel_t *chan, int severity) +{ + tor_assert(chan); + + if (chan->dumpstats) chan->dumpstats(chan, severity); +} + +/** + * Invoke transport-specific stats dump for channel listener + * + * If there is a lower-layer statistics dump method, invoke it + */ + +void +channel_listener_dump_transport_statistics(channel_listener_t *chan_l, + int severity) +{ + tor_assert(chan_l); + + if (chan_l->dumpstats) chan_l->dumpstats(chan_l, severity); +} + +/** + * Return text description of the remote endpoint + * + * This function return a test provided by the lower layer of the remote + * endpoint for this channel; it should specify the actual address connected + * to/from. + * + * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr} + * may invalidate the return value from this function. + */ +const char * +channel_get_actual_remote_descr(channel_t *chan) +{ + tor_assert(chan); + tor_assert(chan->get_remote_descr); + + /* Param 1 indicates the actual description */ + return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL); +} + +/** + * Return the text address of the remote endpoint. + * + * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr} + * may invalidate the return value from this function. + */ +const char * +channel_get_actual_remote_address(channel_t *chan) +{ + /* Param 1 indicates the actual description */ + return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL|GRD_FLAG_ADDR_ONLY); +} + +/** + * Return text description of the remote endpoint canonical address + * + * This function return a test provided by the lower layer of the remote + * endpoint for this channel; it should use the known canonical address for + * this OR's identity digest if possible. + * + * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr} + * may invalidate the return value from this function. + */ +const char * +channel_get_canonical_remote_descr(channel_t *chan) +{ + tor_assert(chan); + tor_assert(chan->get_remote_descr); + + /* Param 0 indicates the canonicalized description */ + return chan->get_remote_descr(chan, 0); +} + +/** + * Get remote address if possible. + * + * Write the remote address out to a tor_addr_t if the underlying transport + * supports this operation, and return 1. Return 0 if the underlying transport + * doesn't let us do this. + */ +int +channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out) +{ + tor_assert(chan); + tor_assert(addr_out); + + if (chan->get_remote_addr) + return chan->get_remote_addr(chan, addr_out); + /* Else no support, method not implemented */ + else return 0; +} + +/** + * Check if there are outgoing queue writes on this channel + * + * Indicate if either we have queued cells, or if not, whether the underlying + * lower-layer transport thinks it has an output queue. + */ + +int +channel_has_queued_writes(channel_t *chan) +{ + int has_writes = 0; + + tor_assert(chan); + tor_assert(chan->has_queued_writes); + + if (! TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) { + has_writes = 1; + } else { + /* Check with the lower layer */ + has_writes = chan->has_queued_writes(chan); + } + + return has_writes; +} + +/** + * Check the is_bad_for_new_circs flag + * + * This function returns the is_bad_for_new_circs flag of the specified + * channel. + */ + +int +channel_is_bad_for_new_circs(channel_t *chan) +{ + tor_assert(chan); + + return chan->is_bad_for_new_circs; +} + +/** + * Mark a channel as bad for new circuits + * + * Set the is_bad_for_new_circs_flag on chan. + */ + +void +channel_mark_bad_for_new_circs(channel_t *chan) +{ + tor_assert(chan); + + chan->is_bad_for_new_circs = 1; +} + +/** + * Get the client flag + * + * This returns the client flag of a channel, which will be set if + * command_process_create_cell() in command.c thinks this is a connection + * from a client. + */ + +int +channel_is_client(channel_t *chan) +{ + tor_assert(chan); + + return chan->is_client; +} + +/** + * Set the client flag + * + * Mark a channel as being from a client + */ + +void +channel_mark_client(channel_t *chan) +{ + tor_assert(chan); + + chan->is_client = 1; +} + +/** + * Get the canonical flag for a channel + * + * This returns the is_canonical for a channel; this flag is determined by + * the lower layer and can't be set in a transport-independent way. + */ + +int +channel_is_canonical(channel_t *chan) +{ + tor_assert(chan); + tor_assert(chan->is_canonical); + + return chan->is_canonical(chan, 0); +} + +/** + * Test if the canonical flag is reliable + * + * This function asks if the lower layer thinks it's safe to trust the + * result of channel_is_canonical() + */ + +int +channel_is_canonical_is_reliable(channel_t *chan) +{ + tor_assert(chan); + tor_assert(chan->is_canonical); + + return chan->is_canonical(chan, 1); +} + +/** + * Test incoming flag + * + * This function gets the incoming flag; this is set when a listener spawns + * a channel. If this returns true the channel was remotely initiated. + */ + +int +channel_is_incoming(channel_t *chan) +{ + tor_assert(chan); + + return chan->is_incoming; +} + +/** + * Set the incoming flag + * + * This function is called when a channel arrives on a listening channel + * to mark it as incoming. + */ + +void +channel_mark_incoming(channel_t *chan) +{ + tor_assert(chan); + + chan->is_incoming = 1; +} + +/** + * Test local flag + * + * This function gets the local flag; the lower layer should set this when + * setting up the channel if is_local_addr() is true for all of the + * destinations it will communicate with on behalf of this channel. It's + * used to decide whether to declare the network reachable when seeing incoming + * traffic on the channel. + */ + +int +channel_is_local(channel_t *chan) +{ + tor_assert(chan); + + return chan->is_local; +} + +/** + * Set the local flag + * + * This internal-only function should be called by the lower layer if the + * channel is to a local address. See channel_is_local() above or the + * description of the is_local bit in channel.h + */ + +void +channel_mark_local(channel_t *chan) +{ + tor_assert(chan); + + chan->is_local = 1; +} + +/** + * Test outgoing flag + * + * This function gets the outgoing flag; this is the inverse of the incoming + * bit set when a listener spawns a channel. If this returns true the channel + * was locally initiated. + */ + +int +channel_is_outgoing(channel_t *chan) +{ + tor_assert(chan); + + return !(chan->is_incoming); +} + +/** + * Mark a channel as outgoing + * + * This function clears the incoming flag and thus marks a channel as + * outgoing. + */ + +void +channel_mark_outgoing(channel_t *chan) +{ + tor_assert(chan); + + chan->is_incoming = 0; +} + +/********************* + * Timestamp updates * + ********************/ + +/** + * Update the created timestamp for a channel + * + * This updates the channel's created timestamp and should only be called + * from channel_init(). + */ + +void +channel_timestamp_created(channel_t *chan) +{ + time_t now = time(NULL); + + tor_assert(chan); + + chan->timestamp_created = now; +} + +/** + * Update the created timestamp for a channel listener + * + * This updates the channel listener's created timestamp and should only be + * called from channel_init_listener(). + */ + +void +channel_listener_timestamp_created(channel_listener_t *chan_l) +{ + time_t now = time(NULL); + + tor_assert(chan_l); + + chan_l->timestamp_created = now; +} + +/** + * Update the last active timestamp for a channel + * + * This function updates the channel's last active timestamp; it should be + * called by the lower layer whenever there is activity on the channel which + * does not lead to a cell being transmitted or received; the active timestamp + * is also updated from channel_timestamp_recv() and channel_timestamp_xmit(), + * but it should be updated for things like the v3 handshake and stuff that + * produce activity only visible to the lower layer. + */ + +void +channel_timestamp_active(channel_t *chan) +{ + time_t now = time(NULL); + + tor_assert(chan); + + chan->timestamp_active = now; +} + +/** + * Update the last active timestamp for a channel listener + */ + +void +channel_listener_timestamp_active(channel_listener_t *chan_l) +{ + time_t now = time(NULL); + + tor_assert(chan_l); + + chan_l->timestamp_active = now; +} + +/** + * Update the last accepted timestamp. + * + * This function updates the channel listener's last accepted timestamp; it + * should be called whenever a new incoming channel is accepted on a + * listener. + */ + +void +channel_listener_timestamp_accepted(channel_listener_t *chan_l) +{ + time_t now = time(NULL); + + tor_assert(chan_l); + + chan_l->timestamp_active = now; + chan_l->timestamp_accepted = now; +} + +/** + * Update client timestamp + * + * This function is called by relay.c to timestamp a channel that appears to + * be used as a client. + */ + +void +channel_timestamp_client(channel_t *chan) +{ + time_t now = time(NULL); + + tor_assert(chan); + + chan->timestamp_client = now; +} + +/** + * Update the last drained timestamp + * + * This is called whenever we transmit a cell which leaves the outgoing cell + * queue completely empty. It also updates the xmit time and the active time. + */ + +void +channel_timestamp_drained(channel_t *chan) +{ + time_t now = time(NULL); + + tor_assert(chan); + + chan->timestamp_active = now; + chan->timestamp_drained = now; + chan->timestamp_xmit = now; +} + +/** + * Update the recv timestamp + * + * This is called whenever we get an incoming cell from the lower layer. + * This also updates the active timestamp. + */ + +void +channel_timestamp_recv(channel_t *chan) +{ + time_t now = time(NULL); + + tor_assert(chan); + + chan->timestamp_active = now; + chan->timestamp_recv = now; +} + +/** + * Update the xmit timestamp + * This is called whenever we pass an outgoing cell to the lower layer. This + * also updates the active timestamp. + */ + +void +channel_timestamp_xmit(channel_t *chan) +{ + time_t now = time(NULL); + + tor_assert(chan); + + chan->timestamp_active = now; + chan->timestamp_xmit = now; +} + +/*************************************************************** + * Timestamp queries - see above for definitions of timestamps * + **************************************************************/ + +/** + * Query created timestamp for a channel + */ + +time_t +channel_when_created(channel_t *chan) +{ + tor_assert(chan); + + return chan->timestamp_created; +} + +/** + * Query created timestamp for a channel listener + */ + +time_t +channel_listener_when_created(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + return chan_l->timestamp_created; +} + +/** + * Query last active timestamp for a channel + */ + +time_t +channel_when_last_active(channel_t *chan) +{ + tor_assert(chan); + + return chan->timestamp_active; +} + +/** + * Query last active timestamp for a channel listener + */ + +time_t +channel_listener_when_last_active(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + return chan_l->timestamp_active; +} + +/** + * Query last accepted timestamp for a channel listener + */ + +time_t +channel_listener_when_last_accepted(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + return chan_l->timestamp_accepted; +} + +/** + * Query client timestamp + */ + +time_t +channel_when_last_client(channel_t *chan) +{ + tor_assert(chan); + + return chan->timestamp_client; +} + +/** + * Query drained timestamp + */ + +time_t +channel_when_last_drained(channel_t *chan) +{ + tor_assert(chan); + + return chan->timestamp_drained; +} + +/** + * Query recv timestamp + */ + +time_t +channel_when_last_recv(channel_t *chan) +{ + tor_assert(chan); + + return chan->timestamp_recv; +} + +/** + * Query xmit timestamp + */ + +time_t +channel_when_last_xmit(channel_t *chan) +{ + tor_assert(chan); + + return chan->timestamp_xmit; +} + +/** + * Query accepted counter + */ + +uint64_t +channel_listener_count_accepted(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + return chan_l->n_accepted; +} + +/** + * Query received cell counter + */ + +uint64_t +channel_count_recved(channel_t *chan) +{ + tor_assert(chan); + + return chan->n_cells_recved; +} + +/** + * Query transmitted cell counter + */ + +uint64_t +channel_count_xmitted(channel_t *chan) +{ + tor_assert(chan); + + return chan->n_cells_xmitted; +} + +/** + * Check if a channel matches an extend_info_t + * + * This function calls the lower layer and asks if this channel matches a + * given extend_info_t. + */ + +int +channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info) +{ + tor_assert(chan); + tor_assert(chan->matches_extend_info); + tor_assert(extend_info); + + return chan->matches_extend_info(chan, extend_info); +} + +/** + * Check if a channel matches a given target address; return true iff we do. + * + * This function calls into the lower layer and asks if this channel thinks + * it matches a given target address for circuit extension purposes. + */ + +int +channel_matches_target_addr_for_extend(channel_t *chan, + const tor_addr_t *target) +{ + tor_assert(chan); + tor_assert(chan->matches_target); + tor_assert(target); + + return chan->matches_target(chan, target); +} + +/** + * Return the total number of circuits used by a channel + * + * @param chan Channel to query + * @return Number of circuits using this as n_chan or p_chan + */ + +unsigned int +channel_num_circuits(channel_t *chan) +{ + tor_assert(chan); + + return chan->num_n_circuits + + chan->num_p_circuits; +} + +/** + * Set up circuit ID generation + * + * This is called when setting up a channel and replaces the old + * connection_or_set_circid_type() + */ +void +channel_set_circid_type(channel_t *chan, + crypto_pk_t *identity_rcvd, + int consider_identity) +{ + int started_here; + crypto_pk_t *our_identity; + + tor_assert(chan); + + started_here = channel_is_outgoing(chan); + + if (! consider_identity) { + if (started_here) + chan->circ_id_type = CIRC_ID_TYPE_HIGHER; + else + chan->circ_id_type = CIRC_ID_TYPE_LOWER; + return; + } + + our_identity = started_here ? + get_tlsclient_identity_key() : get_server_identity_key(); + + if (identity_rcvd) { + if (crypto_pk_cmp_keys(our_identity, identity_rcvd) < 0) { + chan->circ_id_type = CIRC_ID_TYPE_LOWER; + } else { + chan->circ_id_type = CIRC_ID_TYPE_HIGHER; + } + } else { + chan->circ_id_type = CIRC_ID_TYPE_NEITHER; + } +} + diff --git a/src/or/channel.h b/src/or/channel.h new file mode 100644 index 0000000000..29ba40e326 --- /dev/null +++ b/src/or/channel.h @@ -0,0 +1,486 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file channel.h + * \brief Header file for channel.c + **/ + +#ifndef TOR_CHANNEL_H +#define TOR_CHANNEL_H + +#include "or.h" +#include "tor_queue.h" +#include "circuitmux.h" + +/* Channel handler function pointer typedefs */ +typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *); +typedef void (*channel_cell_handler_fn_ptr)(channel_t *, cell_t *); +typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_cell_t *); + +struct cell_queue_entry_s; +TOR_SIMPLEQ_HEAD(chan_cell_queue, cell_queue_entry_s) incoming_queue; +typedef struct chan_cell_queue chan_cell_queue_t; + +/* + * Channel struct; see the channel_t typedef in or.h. A channel is an + * abstract interface for the OR-to-OR connection, similar to connection_or_t, + * but without the strong coupling to the underlying TLS implementation. They + * are constructed by calling a protocol-specific function to open a channel + * to a particular node, and once constructed support the abstract operations + * defined below. + */ + +struct channel_s { + /* Magic number for type-checking cast macros */ + uint32_t magic; + + /* Current channel state */ + channel_state_t state; + + /* Globally unique ID number for a channel over the lifetime of a Tor + * process. + */ + uint64_t global_identifier; + + /* Should we expect to see this channel in the channel lists? */ + unsigned char registered:1; + + /** has this channel ever been open? */ + unsigned int has_been_open:1; + + /** Why did we close? + */ + enum { + CHANNEL_NOT_CLOSING = 0, + CHANNEL_CLOSE_REQUESTED, + CHANNEL_CLOSE_FROM_BELOW, + CHANNEL_CLOSE_FOR_ERROR + } reason_for_closing; + + /* Timestamps for both cell channels and listeners */ + time_t timestamp_created; /* Channel created */ + time_t timestamp_active; /* Any activity */ + + /* Methods implemented by the lower layer */ + + /* Free a channel */ + void (*free)(channel_t *); + /* Close an open channel */ + void (*close)(channel_t *); + /* Describe the transport subclass for this channel */ + const char * (*describe_transport)(channel_t *); + /* Optional method to dump transport-specific statistics on the channel */ + void (*dumpstats)(channel_t *, int); + + /* Registered handlers for incoming cells */ + channel_cell_handler_fn_ptr cell_handler; + channel_var_cell_handler_fn_ptr var_cell_handler; + + /* Methods implemented by the lower layer */ + + /* + * Ask the underlying transport what the remote endpoint address is, in + * a tor_addr_t. This is optional and subclasses may leave this NULL. + * If they implement it, they should write the address out to the + * provided tor_addr_t *, and return 1 if successful or 0 if no address + * available. + */ + int (*get_remote_addr)(channel_t *, tor_addr_t *); +#define GRD_FLAG_ORIGINAL 1 +#define GRD_FLAG_ADDR_ONLY 2 + /* + * Get a text description of the remote endpoint; canonicalized if the flag + * GRD_FLAG_ORIGINAL is not set, or the one we originally connected + * to/received from if it is. If GRD_FLAG_ADDR_ONLY is set, we return only + * the original address. + */ + const char * (*get_remote_descr)(channel_t *, int); + /* Check if the lower layer has queued writes */ + int (*has_queued_writes)(channel_t *); + /* + * If the second param is zero, ask the lower layer if this is + * 'canonical', for a transport-specific definition of canonical; if + * it is 1, ask if the answer to the preceding query is safe to rely + * on. + */ + int (*is_canonical)(channel_t *, int); + /* Check if this channel matches a specified extend_info_t */ + int (*matches_extend_info)(channel_t *, extend_info_t *); + /* Check if this channel matches a target address when extending */ + int (*matches_target)(channel_t *, const tor_addr_t *); + /* Write a cell to an open channel */ + int (*write_cell)(channel_t *, cell_t *); + /* Write a packed cell to an open channel */ + int (*write_packed_cell)(channel_t *, packed_cell_t *); + /* Write a variable-length cell to an open channel */ + int (*write_var_cell)(channel_t *, var_cell_t *); + + /* + * Hash of the public RSA key for the other side's identity key, or + * zeroes if the other side hasn't shown us a valid identity key. + */ + char identity_digest[DIGEST_LEN]; + /* Nickname of the OR on the other side, or NULL if none. */ + char *nickname; + + /* + * Linked list of channels with the same identity digest, for the + * digest->channel map + */ + TOR_LIST_ENTRY(channel_s) next_with_same_id; + + /* List of incoming cells to handle */ + chan_cell_queue_t incoming_queue; + + /* List of queued outgoing cells */ + chan_cell_queue_t outgoing_queue; + + /* Circuit mux for circuits sending on this channel */ + circuitmux_t *cmux; + + /* Circuit ID generation stuff for use by circuitbuild.c */ + + /* + * When we send CREATE cells along this connection, which half of the + * space should we use? + */ + ENUM_BF(circ_id_type_t) circ_id_type:2; + /** DOCDOC*/ + unsigned wide_circ_ids:1; + /** Have we logged a warning about circID exhaustion on this channel? */ + unsigned warned_circ_ids_exhausted:1; + /* + * Which circ_id do we try to use next on this connection? This is + * always in the range 0..1<<15-1. + */ + circid_t next_circ_id; + + /* For how many circuits are we n_chan? What about p_chan? */ + unsigned int num_n_circuits, num_p_circuits; + + /* + * True iff this channel shouldn't get any new circs attached to it, + * 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; + + /** True iff we have decided that the other end of this connection + * is a client. Channels with this flag set should never be used + * to satisfy an EXTEND request. */ + unsigned int is_client:1; + + /** Set if the channel was initiated remotely (came from a listener) */ + unsigned int is_incoming:1; + + /** Set by lower layer if this is local; i.e., everything it communicates + * with for this channel returns true for is_local_addr(). This is used + * to decide whether to declare reachability when we receive something on + * this channel in circuitbuild.c + */ + unsigned int is_local:1; + + /** Channel timestamps for cell channels */ + time_t timestamp_client; /* Client used this, according to relay.c */ + time_t timestamp_drained; /* Output queue empty */ + time_t timestamp_recv; /* Cell received from lower layer */ + time_t timestamp_xmit; /* Cell sent to lower layer */ + + /* Timestamp for relay.c */ + time_t timestamp_last_added_nonpadding; + + /** Unique ID for measuring direct network status requests;vtunneled ones + * come over a circuit_t, which has a dirreq_id field as well, but is a + * distinct namespace. */ + uint64_t dirreq_id; + + /** Channel counters for cell channels */ + uint64_t n_cells_recved; + uint64_t n_cells_xmitted; +}; + +struct channel_listener_s { + /* Current channel listener state */ + channel_listener_state_t state; + + /* Globally unique ID number for a channel over the lifetime of a Tor + * process. + */ + uint64_t global_identifier; + + /* Should we expect to see this channel in the channel lists? */ + unsigned char registered:1; + + /** Why did we close? + */ + enum { + CHANNEL_LISTENER_NOT_CLOSING = 0, + CHANNEL_LISTENER_CLOSE_REQUESTED, + CHANNEL_LISTENER_CLOSE_FROM_BELOW, + CHANNEL_LISTENER_CLOSE_FOR_ERROR + } reason_for_closing; + + /* Timestamps for both cell channels and listeners */ + time_t timestamp_created; /* Channel created */ + time_t timestamp_active; /* Any activity */ + + /* Methods implemented by the lower layer */ + + /* Free a channel */ + void (*free)(channel_listener_t *); + /* Close an open channel */ + void (*close)(channel_listener_t *); + /* Describe the transport subclass for this channel */ + const char * (*describe_transport)(channel_listener_t *); + /* Optional method to dump transport-specific statistics on the channel */ + void (*dumpstats)(channel_listener_t *, int); + + /* Registered listen handler to call on incoming connection */ + channel_listener_fn_ptr listener; + + /* List of pending incoming connections */ + smartlist_t *incoming_list; + + /* Timestamps for listeners */ + time_t timestamp_accepted; + + /* Counters for listeners */ + uint64_t n_accepted; +}; + +/* Channel state manipulations */ + +int channel_state_is_valid(channel_state_t state); +int channel_listener_state_is_valid(channel_listener_state_t state); + +int channel_state_can_transition(channel_state_t from, channel_state_t to); +int channel_listener_state_can_transition(channel_listener_state_t from, + channel_listener_state_t to); + +const char * channel_state_to_string(channel_state_t state); +const char * +channel_listener_state_to_string(channel_listener_state_t state); + +/* Abstract channel operations */ + +void channel_mark_for_close(channel_t *chan); +void channel_write_cell(channel_t *chan, cell_t *cell); +void channel_write_packed_cell(channel_t *chan, packed_cell_t *cell); +void channel_write_var_cell(channel_t *chan, var_cell_t *cell); + +void channel_listener_mark_for_close(channel_listener_t *chan_l); + +/* Channel callback registrations */ + +/* Listener callback */ +channel_listener_fn_ptr +channel_listener_get_listener_fn(channel_listener_t *chan); + +void channel_listener_set_listener_fn(channel_listener_t *chan, + channel_listener_fn_ptr listener); + +/* Incoming cell callbacks */ +channel_cell_handler_fn_ptr channel_get_cell_handler(channel_t *chan); + +channel_var_cell_handler_fn_ptr +channel_get_var_cell_handler(channel_t *chan); + +void channel_set_cell_handlers(channel_t *chan, + channel_cell_handler_fn_ptr cell_handler, + channel_var_cell_handler_fn_ptr + var_cell_handler); + +/* Clean up closed channels and channel listeners periodically; these are + * called from run_scheduled_events() in main.c. + */ +void channel_run_cleanup(void); +void channel_listener_run_cleanup(void); + +/* Close all channels and deallocate everything */ +void channel_free_all(void); + +/* Dump some statistics in the log */ +void channel_dumpstats(int severity); +void channel_listener_dumpstats(int severity); + +/* Set the cmux policy on all active channels */ +void channel_set_cmux_policy_everywhere(circuitmux_policy_t *pol); + +#ifdef TOR_CHANNEL_INTERNAL_ + +/* Channel operations for subclasses and internal use only */ + +/* Initialize a newly allocated channel - do this first in subclass + * constructors. + */ + +void channel_init(channel_t *chan); +void channel_init_listener(channel_listener_t *chan); + +/* Channel registration/unregistration */ +void channel_register(channel_t *chan); +void channel_unregister(channel_t *chan); + +/* Channel listener registration/unregistration */ +void channel_listener_register(channel_listener_t *chan_l); +void channel_listener_unregister(channel_listener_t *chan_l); + +/* Close from below */ +void channel_close_from_lower_layer(channel_t *chan); +void channel_close_for_error(channel_t *chan); +void channel_closed(channel_t *chan); + +void channel_listener_close_from_lower_layer(channel_listener_t *chan_l); +void channel_listener_close_for_error(channel_listener_t *chan_l); +void channel_listener_closed(channel_listener_t *chan_l); + +/* Free a channel */ +void channel_free(channel_t *chan); +void channel_listener_free(channel_listener_t *chan_l); + +/* State/metadata setters */ + +void channel_change_state(channel_t *chan, channel_state_t to_state); +void channel_clear_identity_digest(channel_t *chan); +void channel_clear_remote_end(channel_t *chan); +void channel_mark_local(channel_t *chan); +void channel_mark_incoming(channel_t *chan); +void channel_mark_outgoing(channel_t *chan); +void channel_set_identity_digest(channel_t *chan, + const char *identity_digest); +void channel_set_remote_end(channel_t *chan, + const char *identity_digest, + const char *nickname); + +void channel_listener_change_state(channel_listener_t *chan_l, + channel_listener_state_t to_state); + +/* Timestamp updates */ +void channel_timestamp_created(channel_t *chan); +void channel_timestamp_active(channel_t *chan); +void channel_timestamp_drained(channel_t *chan); +void channel_timestamp_recv(channel_t *chan); +void channel_timestamp_xmit(channel_t *chan); + +void channel_listener_timestamp_created(channel_listener_t *chan_l); +void channel_listener_timestamp_active(channel_listener_t *chan_l); +void channel_listener_timestamp_accepted(channel_listener_t *chan_l); + +/* Incoming channel handling */ +void channel_listener_process_incoming(channel_listener_t *listener); +void channel_listener_queue_incoming(channel_listener_t *listener, + channel_t *incoming); + +/* Incoming cell handling */ +void channel_process_cells(channel_t *chan); +void channel_queue_cell(channel_t *chan, cell_t *cell); +void channel_queue_var_cell(channel_t *chan, var_cell_t *var_cell); + +/* Outgoing cell handling */ +void channel_flush_cells(channel_t *chan); + +/* Request from lower layer for more cells if available */ +ssize_t channel_flush_some_cells(channel_t *chan, ssize_t num_cells); + +/* Query if data available on this channel */ +int channel_more_to_flush(channel_t *chan); + +/* Notify flushed outgoing for dirreq handling */ +void channel_notify_flushed(channel_t *chan); + +/* Handle stuff we need to do on open like notifying circuits */ +void channel_do_open_actions(channel_t *chan); + +#endif + +/* Helper functions to perform operations on channels */ + +int channel_send_destroy(circid_t circ_id, channel_t *chan, + int reason); + +/* + * Outside abstract interfaces that should eventually get turned into + * something transport/address format independent. + */ + +channel_t * channel_connect(const tor_addr_t *addr, uint16_t port, + const char *id_digest); + +channel_t * channel_get_for_extend(const char *digest, + const tor_addr_t *target_addr, + const char **msg_out, + int *launch_out); + +/* Ask which of two channels is better for circuit-extension purposes */ +int channel_is_better(time_t now, + channel_t *a, channel_t *b, + int forgive_new_connections); + +/** Channel lookups + */ + +channel_t * channel_find_by_global_id(uint64_t global_identifier); +channel_t * channel_find_by_remote_digest(const char *identity_digest); + +/** For things returned by channel_find_by_remote_digest(), walk the list. + */ +channel_t * channel_next_with_digest(channel_t *chan); + +/* + * Metadata queries/updates + */ + +const char * channel_describe_transport(channel_t *chan); +void channel_dump_statistics(channel_t *chan, int severity); +void channel_dump_transport_statistics(channel_t *chan, int severity); +const char * channel_get_actual_remote_descr(channel_t *chan); +const char * channel_get_actual_remote_address(channel_t *chan); +int channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out); +const char * channel_get_canonical_remote_descr(channel_t *chan); +int channel_has_queued_writes(channel_t *chan); +int channel_is_bad_for_new_circs(channel_t *chan); +void channel_mark_bad_for_new_circs(channel_t *chan); +int channel_is_canonical(channel_t *chan); +int channel_is_canonical_is_reliable(channel_t *chan); +int channel_is_client(channel_t *chan); +int channel_is_local(channel_t *chan); +int channel_is_incoming(channel_t *chan); +int channel_is_outgoing(channel_t *chan); +void channel_mark_client(channel_t *chan); +int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info); +int channel_matches_target_addr_for_extend(channel_t *chan, + const tor_addr_t *target); +unsigned int channel_num_circuits(channel_t *chan); +void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd, + int consider_identity); +void channel_timestamp_client(channel_t *chan); + +const char * channel_listener_describe_transport(channel_listener_t *chan_l); +void channel_listener_dump_statistics(channel_listener_t *chan_l, + int severity); +void channel_listener_dump_transport_statistics(channel_listener_t *chan_l, + int severity); + +/* Timestamp queries */ +time_t channel_when_created(channel_t *chan); +time_t channel_when_last_active(channel_t *chan); +time_t channel_when_last_client(channel_t *chan); +time_t channel_when_last_drained(channel_t *chan); +time_t channel_when_last_recv(channel_t *chan); +time_t channel_when_last_xmit(channel_t *chan); + +time_t channel_listener_when_created(channel_listener_t *chan_l); +time_t channel_listener_when_last_active(channel_listener_t *chan_l); +time_t channel_listener_when_last_accepted(channel_listener_t *chan_l); + +/* Counter queries */ +uint64_t channel_count_recved(channel_t *chan); +uint64_t channel_count_xmitted(channel_t *chan); + +uint64_t channel_listener_count_accepted(channel_listener_t *chan_l); + +#endif + diff --git a/src/or/channeltls.c b/src/or/channeltls.c new file mode 100644 index 0000000000..d5428c1abd --- /dev/null +++ b/src/or/channeltls.c @@ -0,0 +1,2037 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file channeltls.c + * \brief channel_t concrete subclass using or_connection_t + **/ + +/* + * Define this so channel.h gives us things only channel_t subclasses + * should touch. + */ + +#define TOR_CHANNEL_INTERNAL_ + +#include "or.h" +#include "channel.h" +#include "channeltls.h" +#include "circuitmux.h" +#include "circuitmux_ewma.h" +#include "config.h" +#include "connection.h" +#include "connection_or.h" +#include "control.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; +/** How many CELL_VERSIONS cells have we received, ever? */ +uint64_t stats_n_versions_cells_processed = 0; +/** How many CELL_NETINFO cells have we received, ever? */ +uint64_t stats_n_netinfo_cells_processed = 0; +/** How many CELL_VPADDING cells have we received, ever? */ +uint64_t stats_n_vpadding_cells_processed = 0; +/** How many CELL_CERTS cells have we received, ever? */ +uint64_t stats_n_certs_cells_processed = 0; +/** How many CELL_AUTH_CHALLENGE cells have we received, ever? */ +uint64_t stats_n_auth_challenge_cells_processed = 0; +/** How many CELL_AUTHENTICATE cells have we received, ever? */ +uint64_t stats_n_authenticate_cells_processed = 0; +/** How many CELL_AUTHORIZE cells have we received, ever? */ +uint64_t stats_n_authorize_cells_processed = 0; + +/** Active listener, if any */ +channel_listener_t *channel_tls_listener = NULL; + +/* Utility function declarations */ +static void channel_tls_common_init(channel_tls_t *tlschan); + +/* channel_tls_t method declarations */ + +static void channel_tls_close_method(channel_t *chan); +static const char * channel_tls_describe_transport_method(channel_t *chan); +static void channel_tls_free_method(channel_t *chan); +static int +channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out); +static const char * +channel_tls_get_remote_descr_method(channel_t *chan, int flags); +static int channel_tls_has_queued_writes_method(channel_t *chan); +static int channel_tls_is_canonical_method(channel_t *chan, int req); +static int +channel_tls_matches_extend_info_method(channel_t *chan, + extend_info_t *extend_info); +static int channel_tls_matches_target_method(channel_t *chan, + const tor_addr_t *target); +static int channel_tls_write_cell_method(channel_t *chan, + cell_t *cell); +static int channel_tls_write_packed_cell_method(channel_t *chan, + packed_cell_t *packed_cell); +static int channel_tls_write_var_cell_method(channel_t *chan, + var_cell_t *var_cell); + +/* channel_listener_tls_t method declarations */ + +static void channel_tls_listener_close_method(channel_listener_t *chan_l); +static const char * +channel_tls_listener_describe_transport_method(channel_listener_t *chan_l); + +/** Handle incoming cells for the handshake stuff here rather than + * passing them on up. */ + +static void channel_tls_process_versions_cell(var_cell_t *cell, + channel_tls_t *tlschan); +static void channel_tls_process_netinfo_cell(cell_t *cell, + channel_tls_t *tlschan); +static void channel_tls_process_certs_cell(var_cell_t *cell, + channel_tls_t *tlschan); +static void channel_tls_process_auth_challenge_cell(var_cell_t *cell, + channel_tls_t *tlschan); +static void channel_tls_process_authenticate_cell(var_cell_t *cell, + channel_tls_t *tlschan); +static int command_allowed_before_handshake(uint8_t command); +static int enter_v3_handshake_with_cell(var_cell_t *cell, + channel_tls_t *tlschan); + +/** + * Do parts of channel_tls_t initialization common to channel_tls_connect() + * and channel_tls_handle_incoming(). + */ + +static void +channel_tls_common_init(channel_tls_t *tlschan) +{ + channel_t *chan; + + tor_assert(tlschan); + + chan = &(tlschan->base_); + channel_init(chan); + chan->magic = TLS_CHAN_MAGIC; + chan->state = CHANNEL_STATE_OPENING; + chan->close = channel_tls_close_method; + chan->describe_transport = channel_tls_describe_transport_method; + chan->free = channel_tls_free_method; + chan->get_remote_addr = channel_tls_get_remote_addr_method; + chan->get_remote_descr = channel_tls_get_remote_descr_method; + chan->has_queued_writes = channel_tls_has_queued_writes_method; + chan->is_canonical = channel_tls_is_canonical_method; + chan->matches_extend_info = channel_tls_matches_extend_info_method; + chan->matches_target = channel_tls_matches_target_method; + chan->write_cell = channel_tls_write_cell_method; + chan->write_packed_cell = channel_tls_write_packed_cell_method; + chan->write_var_cell = channel_tls_write_var_cell_method; + + chan->cmux = circuitmux_alloc(); + if (cell_ewma_enabled()) { + circuitmux_set_policy(chan->cmux, &ewma_policy); + } +} + +/** + * Start a new TLS channel + * + * Launch a new OR connection to <b>addr</b>:<b>port</b> and expect to + * handshake with an OR with identity digest <b>id_digest</b>, and wrap + * it in a channel_tls_t. + */ + +channel_t * +channel_tls_connect(const tor_addr_t *addr, uint16_t port, + const char *id_digest) +{ + channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan)); + channel_t *chan = &(tlschan->base_); + + channel_tls_common_init(tlschan); + + log_debug(LD_CHANNEL, + "In channel_tls_connect() for channel %p " + "(global id " U64_FORMAT ")", + tlschan, + U64_PRINTF_ARG(chan->global_identifier)); + + if (is_local_addr(addr)) channel_mark_local(chan); + channel_mark_outgoing(chan); + + /* Set up or_connection stuff */ + tlschan->conn = connection_or_connect(addr, port, id_digest, tlschan); + /* connection_or_connect() will fill in tlschan->conn */ + if (!(tlschan->conn)) { + chan->reason_for_closing = CHANNEL_CLOSE_FOR_ERROR; + channel_change_state(chan, CHANNEL_STATE_ERROR); + goto err; + } + + log_debug(LD_CHANNEL, + "Got orconn %p for channel with global id " U64_FORMAT, + tlschan->conn, U64_PRINTF_ARG(chan->global_identifier)); + + goto done; + + err: + circuitmux_free(chan->cmux); + tor_free(tlschan); + chan = NULL; + + done: + /* If we got one, we should register it */ + if (chan) channel_register(chan); + + return chan; +} + +/** + * Return the current channel_tls_t listener + * + * Returns the current channel listener for incoming TLS connections, or + * NULL if none has been established + */ + +channel_listener_t * +channel_tls_get_listener(void) +{ + return channel_tls_listener; +} + +/** + * Start a channel_tls_t listener if necessary + * + * Return the current channel_tls_t listener, or start one if we haven't yet, + * and return that. + */ + +channel_listener_t * +channel_tls_start_listener(void) +{ + channel_listener_t *listener; + + if (!channel_tls_listener) { + listener = tor_malloc_zero(sizeof(*listener)); + channel_init_listener(listener); + listener->state = CHANNEL_LISTENER_STATE_LISTENING; + listener->close = channel_tls_listener_close_method; + listener->describe_transport = + channel_tls_listener_describe_transport_method; + + channel_tls_listener = listener; + + log_debug(LD_CHANNEL, + "Starting TLS channel listener %p with global id " U64_FORMAT, + listener, U64_PRINTF_ARG(listener->global_identifier)); + + channel_listener_register(listener); + } else listener = channel_tls_listener; + + return listener; +} + +/** + * Free everything on shutdown + * + * Not much to do here, since channel_free_all() takes care of a lot, but let's + * get rid of the listener. + */ + +void +channel_tls_free_all(void) +{ + channel_listener_t *old_listener = NULL; + + log_debug(LD_CHANNEL, + "Shutting down TLS channels..."); + + if (channel_tls_listener) { + /* + * When we close it, channel_tls_listener will get nulled out, so save + * a pointer so we can free it. + */ + old_listener = channel_tls_listener; + log_debug(LD_CHANNEL, + "Closing channel_tls_listener with ID " U64_FORMAT + " at %p.", + U64_PRINTF_ARG(old_listener->global_identifier), + old_listener); + channel_listener_unregister(old_listener); + channel_listener_mark_for_close(old_listener); + channel_listener_free(old_listener); + tor_assert(channel_tls_listener == NULL); + } + + log_debug(LD_CHANNEL, + "Done shutting down TLS channels"); +} + +/** + * Create a new channel around an incoming or_connection_t + */ + +channel_t * +channel_tls_handle_incoming(or_connection_t *orconn) +{ + channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan)); + channel_t *chan = &(tlschan->base_); + + tor_assert(orconn); + tor_assert(!(orconn->chan)); + + channel_tls_common_init(tlschan); + + /* Link the channel and orconn to each other */ + tlschan->conn = orconn; + orconn->chan = tlschan; + + if (is_local_addr(&(TO_CONN(orconn)->addr))) channel_mark_local(chan); + channel_mark_incoming(chan); + + /* If we got one, we should register it */ + if (chan) channel_register(chan); + + return chan; +} + +/********* + * Casts * + ********/ + +/** + * Cast a channel_tls_t to a channel_t. + */ + +channel_t * +channel_tls_to_base(channel_tls_t *tlschan) +{ + if (!tlschan) return NULL; + + return &(tlschan->base_); +} + +/** + * Cast a channel_t to a channel_tls_t, with appropriate type-checking + * asserts. + */ + +channel_tls_t * +channel_tls_from_base(channel_t *chan) +{ + if (!chan) return NULL; + + tor_assert(chan->magic == TLS_CHAN_MAGIC); + + return (channel_tls_t *)(chan); +} + +/******************************************** + * Method implementations for channel_tls_t * + *******************************************/ + +/** + * Close a channel_tls_t + * + * This implements the close method for channel_tls_t + */ + +static void +channel_tls_close_method(channel_t *chan) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + + if (tlschan->conn) connection_or_close_normally(tlschan->conn, 1); + else { + /* Weird - we'll have to change the state ourselves, I guess */ + log_info(LD_CHANNEL, + "Tried to close channel_tls_t %p with NULL conn", + tlschan); + channel_change_state(chan, CHANNEL_STATE_ERROR); + } +} + +/** + * Describe the transport for a channel_tls_t + * + * This returns the string "TLS channel on connection <id>" to the upper + * layer. + */ + +static const char * +channel_tls_describe_transport_method(channel_t *chan) +{ + static char *buf = NULL; + uint64_t id; + channel_tls_t *tlschan; + const char *rv = NULL; + + tor_assert(chan); + + tlschan = BASE_CHAN_TO_TLS(chan); + + if (tlschan->conn) { + id = TO_CONN(tlschan->conn)->global_identifier; + + if (buf) tor_free(buf); + tor_asprintf(&buf, + "TLS channel (connection " U64_FORMAT ")", + U64_PRINTF_ARG(id)); + + rv = buf; + } else { + rv = "TLS channel (no connection)"; + } + + return rv; +} + +/** + * Free a channel_tls_t + * + * This is called by the generic channel layer when freeing a channel_tls_t; + * this happens either on a channel which has already reached + * CHANNEL_STATE_CLOSED or CHANNEL_STATE_ERROR from channel_run_cleanup() or + * on shutdown from channel_free_all(). In the latter case we might still + * have an orconn active (which connection_free_all() will get to later), + * so we should null out its channel pointer now. + */ + +static void +channel_tls_free_method(channel_t *chan) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + + if (tlschan->conn) { + tlschan->conn->chan = NULL; + tlschan->conn = NULL; + } +} + +/** + * Get the remote address of a channel_tls_t + * + * This implements the get_remote_addr method for channel_tls_t; copy the + * remote endpoint of the channel to addr_out and return 1 (always + * succeeds for this transport). + */ + +static int +channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out) +{ + int rv = 0; + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + tor_assert(addr_out); + + if (tlschan->conn) { + tor_addr_copy(addr_out, &(TO_CONN(tlschan->conn)->addr)); + rv = 1; + } else tor_addr_make_unspec(addr_out); + + return rv; +} + +/** + * Get endpoint description of a channel_tls_t + * + * This implements the get_remote_descr method for channel_tls_t; it returns + * a text description of the remote endpoint of the channel suitable for use + * in log messages. The req parameter is 0 for the canonical address or 1 for + * the actual address seen. + */ + +static const char * +channel_tls_get_remote_descr_method(channel_t *chan, int flags) +{ +#define MAX_DESCR_LEN 32 + + static char buf[MAX_DESCR_LEN + 1]; + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + connection_t *conn; + const char *answer = NULL; + char *addr_str; + + tor_assert(tlschan); + + if (tlschan->conn) { + conn = TO_CONN(tlschan->conn); + switch (flags) { + case 0: + /* Canonical address with port*/ + tor_snprintf(buf, MAX_DESCR_LEN + 1, + "%s:%u", conn->address, conn->port); + answer = buf; + break; + case GRD_FLAG_ORIGINAL: + /* Actual address with port */ + addr_str = tor_dup_addr(&(tlschan->conn->real_addr)); + tor_snprintf(buf, MAX_DESCR_LEN + 1, + "%s:%u", addr_str, conn->port); + tor_free(addr_str); + answer = buf; + break; + case GRD_FLAG_ADDR_ONLY: + /* Canonical address, no port */ + strlcpy(buf, conn->address, sizeof(buf)); + answer = buf; + break; + case GRD_FLAG_ORIGINAL|GRD_FLAG_ADDR_ONLY: + /* Actual address, no port */ + addr_str = tor_dup_addr(&(tlschan->conn->real_addr)); + strlcpy(buf, addr_str, sizeof(buf)); + tor_free(addr_str); + answer = buf; + break; + default: + /* Something's broken in channel.c */ + tor_assert(1); + } + } else { + strlcpy(buf, "(No connection)", sizeof(buf)); + answer = buf; + } + + return answer; +} + +/** + * Tell the upper layer if we have queued writes + * + * This implements the has_queued_writes method for channel_tls t_; it returns + * 1 iff we have queued writes on the outbuf of the underlying or_connection_t. + */ + +static int +channel_tls_has_queued_writes_method(channel_t *chan) +{ + size_t outbuf_len; + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + if (!(tlschan->conn)) { + log_info(LD_CHANNEL, + "something called has_queued_writes on a tlschan " + "(%p with ID " U64_FORMAT " but no conn", + chan, U64_PRINTF_ARG(chan->global_identifier)); + } + + outbuf_len = (tlschan->conn != NULL) ? + connection_get_outbuf_len(TO_CONN(tlschan->conn)) : + 0; + + return (outbuf_len > 0); +} + +/** + * Tell the upper layer if we're canonical + * + * This implements the is_canonical method for channel_tls_t; if req is zero, + * it returns whether this is a canonical channel, and if it is one it returns + * whether that can be relied upon. + */ + +static int +channel_tls_is_canonical_method(channel_t *chan, int req) +{ + int answer = 0; + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + + if (tlschan->conn) { + switch (req) { + case 0: + answer = tlschan->conn->is_canonical; + break; + case 1: + /* + * Is the is_canonical bit reliable? In protocols version 2 and up + * we get the canonical address from a NETINFO cell, but in older + * versions it might be based on an obsolete descriptor. + */ + answer = (tlschan->conn->link_proto >= 2); + break; + default: + /* This shouldn't happen; channel.c is broken if it does */ + tor_assert(1); + } + } + /* else return 0 for tlschan->conn == NULL */ + + return answer; +} + +/** + * Check if we match an extend_info_t + * + * This implements the matches_extend_info method for channel_tls_t; the upper + * layer wants to know if this channel matches an extend_info_t. + */ + +static int +channel_tls_matches_extend_info_method(channel_t *chan, + extend_info_t *extend_info) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + tor_assert(extend_info); + + /* Never match if we have no conn */ + if (!(tlschan->conn)) { + log_info(LD_CHANNEL, + "something called matches_extend_info on a tlschan " + "(%p with ID " U64_FORMAT " but no conn", + chan, U64_PRINTF_ARG(chan->global_identifier)); + return 0; + } + + return (tor_addr_eq(&(extend_info->addr), + &(TO_CONN(tlschan->conn)->addr)) && + (extend_info->port == TO_CONN(tlschan->conn)->port)); +} + +/** + * Check if we match a target address; return true iff we do. + * + * This implements the matches_target method for channel_tls t_; the upper + * layer wants to know if this channel matches a target address when extending + * a circuit. + */ + +static int +channel_tls_matches_target_method(channel_t *chan, + const tor_addr_t *target) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + + tor_assert(tlschan); + tor_assert(target); + + /* Never match if we have no conn */ + if (!(tlschan->conn)) { + log_info(LD_CHANNEL, + "something called matches_target on a tlschan " + "(%p with ID " U64_FORMAT " but no conn", + chan, U64_PRINTF_ARG(chan->global_identifier)); + return 0; + } + + return tor_addr_eq(&(tlschan->conn->real_addr), target); +} + +/** + * Write a cell to a channel_tls_t + * + * This implements the write_cell method for channel_tls_t; given a + * channel_tls_t and a cell_t, transmit the cell_t. + */ + +static int +channel_tls_write_cell_method(channel_t *chan, cell_t *cell) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + int written = 0; + + tor_assert(tlschan); + tor_assert(cell); + + if (tlschan->conn) { + connection_or_write_cell_to_buf(cell, tlschan->conn); + ++written; + } else { + log_info(LD_CHANNEL, + "something called write_cell on a tlschan " + "(%p with ID " U64_FORMAT " but no conn", + chan, U64_PRINTF_ARG(chan->global_identifier)); + } + + return written; +} + +/** + * Write a packed cell to a channel_tls_t + * + * This implements the write_packed_cell method for channel_tls_t; given a + * channel_tls_t and a packed_cell_t, transmit the packed_cell_t. + */ + +static int +channel_tls_write_packed_cell_method(channel_t *chan, + packed_cell_t *packed_cell) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + size_t cell_network_size = get_cell_network_size(chan->wide_circ_ids); + int written = 0; + + tor_assert(tlschan); + tor_assert(packed_cell); + + if (tlschan->conn) { + connection_write_to_buf(packed_cell->body, cell_network_size, + TO_CONN(tlschan->conn)); + + /* This is where the cell is finished; used to be done from relay.c */ + packed_cell_free(packed_cell); + ++written; + } else { + log_info(LD_CHANNEL, + "something called write_packed_cell on a tlschan " + "(%p with ID " U64_FORMAT " but no conn", + chan, U64_PRINTF_ARG(chan->global_identifier)); + } + + return written; +} + +/** + * Write a variable-length cell to a channel_tls_t + * + * This implements the write_var_cell method for channel_tls_t; given a + * channel_tls_t and a var_cell_t, transmit the var_cell_t. + */ + +static int +channel_tls_write_var_cell_method(channel_t *chan, var_cell_t *var_cell) +{ + channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); + int written = 0; + + tor_assert(tlschan); + tor_assert(var_cell); + + if (tlschan->conn) { + connection_or_write_var_cell_to_buf(var_cell, tlschan->conn); + ++written; + } else { + log_info(LD_CHANNEL, + "something called write_var_cell on a tlschan " + "(%p with ID " U64_FORMAT " but no conn", + chan, U64_PRINTF_ARG(chan->global_identifier)); + } + + return written; +} + +/************************************************* + * Method implementations for channel_listener_t * + ************************************************/ + +/** + * Close a channel_listener_t + * + * This implements the close method for channel_listener_t + */ + +static void +channel_tls_listener_close_method(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + /* + * Listeners we just go ahead and change state through to CLOSED, but + * make sure to check if they're channel_tls_listener to NULL it out. + */ + if (chan_l == channel_tls_listener) + channel_tls_listener = NULL; + + if (!(chan_l->state == CHANNEL_LISTENER_STATE_CLOSING || + chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR)) { + channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING); + } + + if (chan_l->incoming_list) { + SMARTLIST_FOREACH_BEGIN(chan_l->incoming_list, + channel_t *, ichan) { + channel_mark_for_close(ichan); + } SMARTLIST_FOREACH_END(ichan); + + smartlist_free(chan_l->incoming_list); + chan_l->incoming_list = NULL; + } + + if (!(chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || + chan_l->state == CHANNEL_LISTENER_STATE_ERROR)) { + channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSED); + } +} + +/** + * Describe the transport for a channel_listener_t + * + * This returns the string "TLS channel (listening)" to the upper + * layer. + */ + +static const char * +channel_tls_listener_describe_transport_method(channel_listener_t *chan_l) +{ + tor_assert(chan_l); + + return "TLS channel (listening)"; +} + +/******************************************************* + * Functions for handling events on an or_connection_t * + ******************************************************/ + +/** + * Handle an orconn state change + * + * This function will be called by connection_or.c when the or_connection_t + * associated with this channel_tls_t changes state. + */ + +void +channel_tls_handle_state_change_on_orconn(channel_tls_t *chan, + or_connection_t *conn, + uint8_t old_state, + uint8_t state) +{ + channel_t *base_chan; + + tor_assert(chan); + tor_assert(conn); + tor_assert(conn->chan == chan); + tor_assert(chan->conn == conn); + /* -Werror appeasement */ + tor_assert(old_state == old_state); + + base_chan = TLS_CHAN_TO_BASE(chan); + + /* Make sure the base connection state makes sense - shouldn't be error, + * closed or listening. */ + + tor_assert(base_chan->state == CHANNEL_STATE_OPENING || + base_chan->state == CHANNEL_STATE_OPEN || + base_chan->state == CHANNEL_STATE_MAINT || + base_chan->state == CHANNEL_STATE_CLOSING); + + /* Did we just go to state open? */ + if (state == OR_CONN_STATE_OPEN) { + /* + * We can go to CHANNEL_STATE_OPEN from CHANNEL_STATE_OPENING or + * CHANNEL_STATE_MAINT on this. + */ + channel_change_state(base_chan, CHANNEL_STATE_OPEN); + } else { + /* + * Not open, so from CHANNEL_STATE_OPEN we go to CHANNEL_STATE_MAINT, + * otherwise no change. + */ + if (base_chan->state == CHANNEL_STATE_OPEN) { + channel_change_state(base_chan, CHANNEL_STATE_MAINT); + } + } +} + +/** + * Flush cells from a channel_tls_t + * + * Try to flush up to about num_cells cells, and return how many we flushed. + */ + +ssize_t +channel_tls_flush_some_cells(channel_tls_t *chan, ssize_t num_cells) +{ + ssize_t flushed = 0; + + tor_assert(chan); + + if (flushed >= num_cells) goto done; + + /* + * If channel_tls_t ever buffers anything below the channel_t layer, flush + * that first here. + */ + + flushed += channel_flush_some_cells(TLS_CHAN_TO_BASE(chan), + num_cells - flushed); + + /* + * If channel_tls_t ever buffers anything below the channel_t layer, check + * how much we actually got and push it on down here. + */ + + done: + return flushed; +} + +/** + * Check if a channel_tls_t has anything to flush + * + * Return true if there is any more to flush on this channel (cells in queue + * or active circuits). + */ + +int +channel_tls_more_to_flush(channel_tls_t *chan) +{ + tor_assert(chan); + + /* + * If channel_tls_t ever buffers anything below channel_t, the + * check for that should go here first. + */ + + return channel_more_to_flush(TLS_CHAN_TO_BASE(chan)); +} + +#ifdef KEEP_TIMING_STATS + +/** + * Timing states wrapper + * + * This is a wrapper function around the actual function that processes the + * <b>cell</b> that just arrived on <b>chan</b>. Increment <b>*time</b> + * by the number of microseconds used by the call to <b>*func(cell, chan)</b>. + */ + +static void +channel_tls_time_process_cell(cell_t *cell, channel_tls_t *chan, int *time, + void (*func)(cell_t *, channel_tls_t *)) +{ + struct timeval start, end; + long time_passed; + + tor_gettimeofday(&start); + + (*func)(cell, chan); + + tor_gettimeofday(&end); + time_passed = tv_udiff(&start, &end) ; + + if (time_passed > 10000) { /* more than 10ms */ + log_debug(LD_OR,"That call just took %ld ms.",time_passed/1000); + } + + if (time_passed < 0) { + log_info(LD_GENERAL,"That call took us back in time!"); + time_passed = 0; + } + + *time += time_passed; +} +#endif + +/** + * Handle an incoming cell on a channel_tls_t + * + * This is called from connection_or.c to handle an arriving cell; it checks + * for cell types specific to the handshake for this transport protocol and + * handles them, and queues all other cells to the channel_t layer, which + * eventually will hand them off to command.c. + */ + +void +channel_tls_handle_cell(cell_t *cell, or_connection_t *conn) +{ + channel_tls_t *chan; + int handshaking; + +#ifdef KEEP_TIMING_STATS +#define PROCESS_CELL(tp, cl, cn) STMT_BEGIN { \ + ++num ## tp; \ + channel_tls_time_process_cell(cl, cn, & tp ## time , \ + channel_tls_process_ ## tp ## _cell); \ + } STMT_END +#else +#define PROCESS_CELL(tp, cl, cn) channel_tls_process_ ## tp ## _cell(cl, cn) +#endif + + tor_assert(cell); + tor_assert(conn); + + chan = conn->chan; + + if (!chan) { + log_warn(LD_CHANNEL, + "Got a cell_t on an OR connection with no channel"); + return; + } + + handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN); + + if (conn->base_.marked_for_close) + return; + + /* Reject all but VERSIONS and NETINFO when handshaking. */ + /* (VERSIONS should actually be impossible; it's variable-length.) */ + if (handshaking && cell->command != CELL_VERSIONS && + cell->command != CELL_NETINFO) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received unexpected cell command %d in chan state %s / " + "conn state %s; closing the connection.", + (int)cell->command, + channel_state_to_string(TLS_CHAN_TO_BASE(chan)->state), + conn_state_to_string(CONN_TYPE_OR, TO_CONN(conn)->state)); + connection_or_close_for_error(conn, 0); + return; + } + + if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) + or_handshake_state_record_cell(conn, conn->handshake_state, cell, 1); + + switch (cell->command) { + case CELL_PADDING: + ++stats_n_padding_cells_processed; + /* do nothing */ + break; + case CELL_VERSIONS: + tor_fragile_assert(); + break; + case CELL_NETINFO: + ++stats_n_netinfo_cells_processed; + PROCESS_CELL(netinfo, cell, chan); + break; + case CELL_CREATE: + case CELL_CREATE_FAST: + case CELL_CREATED: + case CELL_CREATED_FAST: + case CELL_RELAY: + case CELL_RELAY_EARLY: + case CELL_DESTROY: + case CELL_CREATE2: + case CELL_CREATED2: + /* + * These are all transport independent and we pass them up through the + * channel_t mechanism. They are ultimately handled in command.c. + */ + channel_queue_cell(TLS_CHAN_TO_BASE(chan), cell); + break; + default: + log_fn(LOG_INFO, LD_PROTOCOL, + "Cell of unknown type (%d) received in channeltls.c. " + "Dropping.", + cell->command); + break; + } +} + +/** + * Handle an incoming variable-length cell on a channel_tls_t + * + * Process a <b>var_cell</b> that was just received on <b>conn</b>. Keep + * internal statistics about how many of each cell we've processed so far + * this second, and the total number of microseconds it took to + * process each type of cell. All the var_cell commands are handshake- + * related and live below the channel_t layer, so no variable-length + * cells ever get delivered in the current implementation, but I've left + * the mechanism in place for future use. + */ + +void +channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn) +{ + channel_tls_t *chan; + +#ifdef KEEP_TIMING_STATS + /* how many of each cell have we seen so far this second? needs better + * name. */ + static int num_versions = 0, num_certs = 0; + static time_t current_second = 0; /* from previous calls to time */ + time_t now = time(NULL); + + if (current_second == 0) current_second = now; + if (now > current_second) { /* the second has rolled over */ + /* print stats */ + log_info(LD_OR, + "At end of second: %d versions (%d ms), %d certs (%d ms)", + num_versions, versions_time / ((now - current_second) * 1000), + num_certs, certs_time / ((now - current_second) * 1000)); + + num_versions = num_certs = 0; + versions_time = certs_time = 0; + + /* remember which second it is, for next time */ + current_second = now; + } +#endif + + tor_assert(var_cell); + tor_assert(conn); + + chan = conn->chan; + + if (!chan) { + log_warn(LD_CHANNEL, + "Got a var_cell_t on an OR connection with no channel"); + return; + } + + if (TO_CONN(conn)->marked_for_close) + return; + + switch (TO_CONN(conn)->state) { + case OR_CONN_STATE_OR_HANDSHAKING_V2: + if (var_cell->command != CELL_VERSIONS) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received a cell with command %d in unexpected " + "orconn state \"%s\" [%d], channel state \"%s\" [%d]; " + "closing the connection.", + (int)(var_cell->command), + conn_state_to_string(CONN_TYPE_OR, TO_CONN(conn)->state), + TO_CONN(conn)->state, + channel_state_to_string(TLS_CHAN_TO_BASE(chan)->state), + (int)(TLS_CHAN_TO_BASE(chan)->state)); + /* + * The code in connection_or.c will tell channel_t to close for + * error; it will go to CHANNEL_STATE_CLOSING, and then to + * CHANNEL_STATE_ERROR when conn is closed. + */ + connection_or_close_for_error(conn, 0); + return; + } + break; + case OR_CONN_STATE_TLS_HANDSHAKING: + /* If we're using bufferevents, it's entirely possible for us to + * notice "hey, data arrived!" before we notice "hey, the handshake + * finished!" And we need to be accepting both at once to handle both + * the v2 and v3 handshakes. */ + + /* fall through */ + case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: + if (!(command_allowed_before_handshake(var_cell->command))) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received a cell with command %d in unexpected " + "orconn state \"%s\" [%d], channel state \"%s\" [%d]; " + "closing the connection.", + (int)(var_cell->command), + conn_state_to_string(CONN_TYPE_OR, TO_CONN(conn)->state), + (int)(TO_CONN(conn)->state), + channel_state_to_string(TLS_CHAN_TO_BASE(chan)->state), + (int)(TLS_CHAN_TO_BASE(chan)->state)); + /* see above comment about CHANNEL_STATE_ERROR */ + connection_or_close_for_error(conn, 0); + return; + } else { + if (enter_v3_handshake_with_cell(var_cell, chan) < 0) + return; + } + break; + case OR_CONN_STATE_OR_HANDSHAKING_V3: + if (var_cell->command != CELL_AUTHENTICATE) + or_handshake_state_record_var_cell(conn, conn->handshake_state, + var_cell, 1); + break; /* Everything is allowed */ + case OR_CONN_STATE_OPEN: + if (conn->link_proto < 3) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received a variable-length cell with command %d in orconn " + "state %s [%d], channel state %s [%d] with link protocol %d; " + "ignoring it.", + (int)(var_cell->command), + conn_state_to_string(CONN_TYPE_OR, TO_CONN(conn)->state), + (int)(TO_CONN(conn)->state), + channel_state_to_string(TLS_CHAN_TO_BASE(chan)->state), + (int)(TLS_CHAN_TO_BASE(chan)->state), + (int)(conn->link_proto)); + return; + } + break; + default: + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received var-length cell with command %d in unexpected " + "orconn state \"%s\" [%d], channel state \"%s\" [%d]; " + "ignoring it.", + (int)(var_cell->command), + conn_state_to_string(CONN_TYPE_OR, TO_CONN(conn)->state), + (int)(TO_CONN(conn)->state), + channel_state_to_string(TLS_CHAN_TO_BASE(chan)->state), + (int)(TLS_CHAN_TO_BASE(chan)->state)); + return; + } + + /* Now handle the cell */ + + switch (var_cell->command) { + case CELL_VERSIONS: + ++stats_n_versions_cells_processed; + PROCESS_CELL(versions, var_cell, chan); + break; + case CELL_VPADDING: + ++stats_n_vpadding_cells_processed; + /* Do nothing */ + break; + case CELL_CERTS: + ++stats_n_certs_cells_processed; + PROCESS_CELL(certs, var_cell, chan); + break; + case CELL_AUTH_CHALLENGE: + ++stats_n_auth_challenge_cells_processed; + PROCESS_CELL(auth_challenge, var_cell, chan); + break; + case CELL_AUTHENTICATE: + ++stats_n_authenticate_cells_processed; + PROCESS_CELL(authenticate, var_cell, chan); + break; + case CELL_AUTHORIZE: + ++stats_n_authorize_cells_processed; + /* Ignored so far. */ + break; + default: + log_fn(LOG_INFO, LD_PROTOCOL, + "Variable-length cell of unknown type (%d) received.", + (int)(var_cell->command)); + break; + } +} + +/** + * Check if this cell type is allowed before the handshake is finished + * + * Return true if <b>command</b> is a cell command that's allowed to start a + * V3 handshake. + */ + +static int +command_allowed_before_handshake(uint8_t command) +{ + switch (command) { + case CELL_VERSIONS: + case CELL_VPADDING: + case CELL_AUTHORIZE: + return 1; + default: + return 0; + } +} + +/** + * Start a V3 handshake on an incoming connection + * + * Called when we as a server receive an appropriate cell while waiting + * either for a cell or a TLS handshake. Set the connection's state to + * "handshaking_v3', initializes the or_handshake_state field as needed, + * and add the cell to the hash of incoming cells.) + */ + +static int +enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan) +{ + int started_here = 0; + + tor_assert(cell); + tor_assert(chan); + tor_assert(chan->conn); + + started_here = connection_or_nonopen_was_started_here(chan->conn); + + tor_assert(TO_CONN(chan->conn)->state == OR_CONN_STATE_TLS_HANDSHAKING || + TO_CONN(chan->conn)->state == + OR_CONN_STATE_TLS_SERVER_RENEGOTIATING); + + if (started_here) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Received a cell while TLS-handshaking, not in " + "OR_HANDSHAKING_V3, on a connection we originated."); + } + connection_or_block_renegotiation(chan->conn); + chan->conn->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; + if (connection_init_or_handshake_state(chan->conn, started_here) < 0) { + connection_or_close_for_error(chan->conn, 0); + return -1; + } + or_handshake_state_record_var_cell(chan->conn, + chan->conn->handshake_state, cell, 1); + return 0; +} + +/** + * Process a 'versions' cell. + * + * This function is called to handle an incoming VERSIONS cell; the current + * link protocol version must be 0 to indicate that no version has yet been + * negotiated. We compare the versions in the cell to the list of versions + * we support, pick the highest version we have in common, and continue the + * negotiation from there. + */ + +static void +channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan) +{ + int highest_supported_version = 0; + const uint8_t *cp, *end; + int started_here = 0; + + tor_assert(cell); + tor_assert(chan); + tor_assert(chan->conn); + + started_here = connection_or_nonopen_was_started_here(chan->conn); + + if (chan->conn->link_proto != 0 || + (chan->conn->handshake_state && + chan->conn->handshake_state->received_versions)) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Received a VERSIONS cell on a connection with its version " + "already set to %d; dropping", + (int)(chan->conn->link_proto)); + return; + } + switch (chan->conn->base_.state) + { + case OR_CONN_STATE_OR_HANDSHAKING_V2: + case OR_CONN_STATE_OR_HANDSHAKING_V3: + break; + case OR_CONN_STATE_TLS_HANDSHAKING: + case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: + default: + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "VERSIONS cell while in unexpected state"); + return; + } + + tor_assert(chan->conn->handshake_state); + end = cell->payload + cell->payload_len; + for (cp = cell->payload; cp+1 < end; cp += 2) { + uint16_t v = ntohs(get_uint16(cp)); + if (is_or_protocol_version_known(v) && v > highest_supported_version) + highest_supported_version = v; + } + if (!highest_supported_version) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Couldn't find a version in common between my version list and the " + "list in the VERSIONS cell; closing connection."); + connection_or_close_for_error(chan->conn, 0); + return; + } else if (highest_supported_version == 1) { + /* Negotiating version 1 makes no sense, since version 1 has no VERSIONS + * cells. */ + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Used version negotiation protocol to negotiate a v1 connection. " + "That's crazily non-compliant. Closing connection."); + connection_or_close_for_error(chan->conn, 0); + return; + } else if (highest_supported_version < 3 && + chan->conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Negotiated link protocol 2 or lower after doing a v3 TLS " + "handshake. Closing connection."); + connection_or_close_for_error(chan->conn, 0); + return; + } else if (highest_supported_version != 2 && + chan->conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V2) { + /* XXXX This should eventually be a log_protocol_warn */ + log_fn(LOG_WARN, LD_OR, + "Negotiated link with non-2 protocol after doing a v2 TLS " + "handshake with %s. Closing connection.", + fmt_addr(&chan->conn->base_.addr)); + connection_or_close_for_error(chan->conn, 0); + return; + } + + chan->conn->link_proto = highest_supported_version; + chan->conn->handshake_state->received_versions = 1; + + if (chan->conn->link_proto == 2) { + log_info(LD_OR, + "Negotiated version %d with %s:%d; sending NETINFO.", + highest_supported_version, + safe_str_client(chan->conn->base_.address), + chan->conn->base_.port); + + if (connection_or_send_netinfo(chan->conn) < 0) { + connection_or_close_for_error(chan->conn, 0); + return; + } + } else { + const int send_versions = !started_here; + /* If we want to authenticate, send a CERTS cell */ + const int send_certs = !started_here || public_server_mode(get_options()); + /* If we're a host that got a connection, ask for authentication. */ + const int send_chall = !started_here; + /* If our certs cell will authenticate us, we can send a netinfo cell + * right now. */ + const int send_netinfo = !started_here; + const int send_any = + send_versions || send_certs || send_chall || send_netinfo; + tor_assert(chan->conn->link_proto >= 3); + + log_info(LD_OR, + "Negotiated version %d with %s:%d; %s%s%s%s%s", + highest_supported_version, + safe_str_client(chan->conn->base_.address), + chan->conn->base_.port, + send_any ? "Sending cells:" : "Waiting for CERTS cell", + send_versions ? " VERSIONS" : "", + send_certs ? " CERTS" : "", + send_chall ? " AUTH_CHALLENGE" : "", + send_netinfo ? " NETINFO" : ""); + +#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE + if (1) { + connection_or_close_normally(chan->conn, 1); + return; + } +#endif + + if (send_versions) { + if (connection_or_send_versions(chan->conn, 1) < 0) { + log_warn(LD_OR, "Couldn't send versions cell"); + connection_or_close_for_error(chan->conn, 0); + return; + } + } + + /* We set this after sending the verions cell. */ + /*XXXXX symbolic const.*/ + chan->base_.wide_circ_ids = + chan->conn->link_proto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; + chan->conn->wide_circ_ids = chan->base_.wide_circ_ids; + + if (send_certs) { + if (connection_or_send_certs_cell(chan->conn) < 0) { + log_warn(LD_OR, "Couldn't send certs cell"); + connection_or_close_for_error(chan->conn, 0); + return; + } + } + if (send_chall) { + if (connection_or_send_auth_challenge_cell(chan->conn) < 0) { + log_warn(LD_OR, "Couldn't send auth_challenge cell"); + connection_or_close_for_error(chan->conn, 0); + return; + } + } + if (send_netinfo) { + if (connection_or_send_netinfo(chan->conn) < 0) { + log_warn(LD_OR, "Couldn't send netinfo cell"); + connection_or_close_for_error(chan->conn, 0); + return; + } + } + } +} + +/** + * Process a 'netinfo' cell + * + * This function is called to handle an incoming NETINFO cell; read and act + * on its contents, and set the connection state to "open". + */ + +static void +channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan) +{ + time_t timestamp; + uint8_t my_addr_type; + uint8_t my_addr_len; + const uint8_t *my_addr_ptr; + const uint8_t *cp, *end; + uint8_t n_other_addrs; + time_t now = time(NULL); + + long apparent_skew = 0; + tor_addr_t my_apparent_addr = TOR_ADDR_NULL; + + tor_assert(cell); + tor_assert(chan); + tor_assert(chan->conn); + + if (chan->conn->link_proto < 2) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Received a NETINFO cell on %s connection; dropping.", + chan->conn->link_proto == 0 ? "non-versioned" : "a v1"); + return; + } + if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V2 && + chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Received a NETINFO cell on non-handshaking connection; dropping."); + return; + } + tor_assert(chan->conn->handshake_state && + chan->conn->handshake_state->received_versions); + + if (chan->conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) { + tor_assert(chan->conn->link_proto >= 3); + if (chan->conn->handshake_state->started_here) { + if (!(chan->conn->handshake_state->authenticated)) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Got a NETINFO cell from server, " + "but no authentication. Closing the connection."); + connection_or_close_for_error(chan->conn, 0); + return; + } + } else { + /* we're the server. If the client never authenticated, we have + some housekeeping to do.*/ + if (!(chan->conn->handshake_state->authenticated)) { + tor_assert(tor_digest_is_zero( + (const char*)(chan->conn->handshake_state-> + authenticated_peer_id))); + channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL, + chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); + + connection_or_init_conn_from_address(chan->conn, + &(chan->conn->base_.addr), + chan->conn->base_.port, + (const char*)(chan->conn->handshake_state-> + authenticated_peer_id), + 0); + } + } + } + + /* Decode the cell. */ + timestamp = ntohl(get_uint32(cell->payload)); + if (labs(now - chan->conn->handshake_state->sent_versions_at) < 180) { + apparent_skew = now - timestamp; + } + + my_addr_type = (uint8_t) cell->payload[4]; + my_addr_len = (uint8_t) cell->payload[5]; + my_addr_ptr = (uint8_t*) cell->payload + 6; + end = cell->payload + CELL_PAYLOAD_SIZE; + cp = cell->payload + 6 + my_addr_len; + if (cp >= end) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Addresses too long in netinfo cell; closing connection."); + connection_or_close_for_error(chan->conn, 0); + return; + } else if (my_addr_type == RESOLVED_TYPE_IPV4 && my_addr_len == 4) { + tor_addr_from_ipv4n(&my_apparent_addr, get_uint32(my_addr_ptr)); + } else if (my_addr_type == RESOLVED_TYPE_IPV6 && my_addr_len == 16) { + tor_addr_from_ipv6_bytes(&my_apparent_addr, (const char *) my_addr_ptr); + } + + n_other_addrs = (uint8_t) *cp++; + while (n_other_addrs && cp < end-2) { + /* Consider all the other addresses; if any matches, this connection is + * "canonical." */ + tor_addr_t addr; + const uint8_t *next = + decode_address_from_payload(&addr, cp, (int)(end-cp)); + if (next == NULL) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Bad address in netinfo cell; closing connection."); + connection_or_close_for_error(chan->conn, 0); + return; + } + if (tor_addr_eq(&addr, &(chan->conn->real_addr))) { + chan->conn->is_canonical = 1; + break; + } + cp = next; + --n_other_addrs; + } + + /* Act on apparent skew. */ + /** Warn when we get a netinfo skew with at least this value. */ +#define NETINFO_NOTICE_SKEW 3600 + if (labs(apparent_skew) > NETINFO_NOTICE_SKEW && + router_get_by_id_digest(chan->conn->identity_digest)) { + char dbuf[64]; + int severity; + /*XXXX be smarter about when everybody says we are skewed. */ + if (router_digest_is_trusted_dir(chan->conn->identity_digest)) + severity = LOG_WARN; + else + severity = LOG_INFO; + format_time_interval(dbuf, sizeof(dbuf), apparent_skew); + log_fn(severity, LD_GENERAL, + "Received NETINFO cell with skewed time from " + "server at %s:%d. It seems that our clock is %s by %s, or " + "that theirs is %s. Tor requires an accurate clock to work: " + "please check your time and date settings.", + chan->conn->base_.address, + (int)(chan->conn->base_.port), + apparent_skew > 0 ? "ahead" : "behind", + dbuf, + apparent_skew > 0 ? "behind" : "ahead"); + if (severity == LOG_WARN) /* only tell the controller if an authority */ + control_event_general_status(LOG_WARN, + "CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d", + apparent_skew, + chan->conn->base_.address, + chan->conn->base_.port); + } + + /* XXX maybe act on my_apparent_addr, if the source is sufficiently + * trustworthy. */ + + if (! chan->conn->handshake_state->sent_netinfo) { + /* If we were prepared to authenticate, but we never got an AUTH_CHALLENGE + * cell, then we would not previously have sent a NETINFO cell. Do so + * now. */ + if (connection_or_send_netinfo(chan->conn) < 0) { + connection_or_close_for_error(chan->conn, 0); + return; + } + } + + if (connection_or_set_state_open(chan->conn) < 0) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Got good NETINFO cell from %s:%d; but " + "was unable to make the OR connection become open.", + safe_str_client(chan->conn->base_.address), + chan->conn->base_.port); + connection_or_close_for_error(chan->conn, 0); + } else { + log_info(LD_OR, + "Got good NETINFO cell from %s:%d; OR connection is now " + "open, using protocol version %d. Its ID digest is %s. " + "Our address is apparently %s.", + safe_str_client(chan->conn->base_.address), + chan->conn->base_.port, + (int)(chan->conn->link_proto), + hex_str(TLS_CHAN_TO_BASE(chan)->identity_digest, + DIGEST_LEN), + tor_addr_is_null(&my_apparent_addr) ? + "<none>" : fmt_and_decorate_addr(&my_apparent_addr)); + } + assert_connection_ok(TO_CONN(chan->conn),time(NULL)); +} + +/** + * Process a CERTS cell from a channel. + * + * This function is called to process an incoming CERTS cell on a + * channel_tls_t: + * + * If the other side should not have sent us a CERTS cell, or the cell is + * malformed, or it is supposed to authenticate the TLS key but it doesn't, + * then mark the connection. + * + * If the cell has a good cert chain and we're doing a v3 handshake, then + * store the certificates in or_handshake_state. If this is the client side + * of the connection, we then authenticate the server or mark the connection. + * If it's the server side, wait for an AUTHENTICATE cell. + */ + +static void +channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan) +{ + tor_cert_t *link_cert = NULL; + tor_cert_t *id_cert = NULL; + tor_cert_t *auth_cert = NULL; + uint8_t *ptr; + int n_certs, i; + int send_netinfo = 0; + + tor_assert(cell); + tor_assert(chan); + tor_assert(chan->conn); + +#define ERR(s) \ + do { \ + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ + "Received a bad CERTS cell from %s:%d: %s", \ + safe_str(chan->conn->base_.address), \ + chan->conn->base_.port, (s)); \ + connection_or_close_for_error(chan->conn, 0); \ + goto err; \ + } while (0) + + if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) + ERR("We're not doing a v3 handshake!"); + if (chan->conn->link_proto < 3) + ERR("We're not using link protocol >= 3"); + if (chan->conn->handshake_state->received_certs_cell) + ERR("We already got one"); + if (chan->conn->handshake_state->authenticated) { + /* Should be unreachable, but let's make sure. */ + ERR("We're already authenticated!"); + } + if (cell->payload_len < 1) + ERR("It had no body"); + if (cell->circ_id) + ERR("It had a nonzero circuit ID"); + + n_certs = cell->payload[0]; + ptr = cell->payload + 1; + for (i = 0; i < n_certs; ++i) { + uint8_t cert_type; + uint16_t cert_len; + if (ptr + 3 > cell->payload + cell->payload_len) { + goto truncated; + } + cert_type = *ptr; + cert_len = ntohs(get_uint16(ptr+1)); + if (ptr + 3 + cert_len > cell->payload + cell->payload_len) { + goto truncated; + } + if (cert_type == OR_CERT_TYPE_TLS_LINK || + cert_type == OR_CERT_TYPE_ID_1024 || + cert_type == OR_CERT_TYPE_AUTH_1024) { + tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len); + if (!cert) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received undecodable certificate in CERTS cell from %s:%d", + safe_str(chan->conn->base_.address), + chan->conn->base_.port); + } else { + if (cert_type == OR_CERT_TYPE_TLS_LINK) { + if (link_cert) { + tor_cert_free(cert); + ERR("Too many TLS_LINK certificates"); + } + link_cert = cert; + } else if (cert_type == OR_CERT_TYPE_ID_1024) { + if (id_cert) { + tor_cert_free(cert); + ERR("Too many ID_1024 certificates"); + } + id_cert = cert; + } else if (cert_type == OR_CERT_TYPE_AUTH_1024) { + if (auth_cert) { + tor_cert_free(cert); + ERR("Too many AUTH_1024 certificates"); + } + auth_cert = cert; + } else { + tor_cert_free(cert); + } + } + } + ptr += 3 + cert_len; + continue; + + truncated: + ERR("It ends in the middle of a certificate"); + } + + if (chan->conn->handshake_state->started_here) { + int severity; + if (! (id_cert && link_cert)) + ERR("The certs we wanted were missing"); + /* Okay. We should be able to check the certificates now. */ + if (! tor_tls_cert_matches_key(chan->conn->tls, link_cert)) { + ERR("The link certificate didn't match the TLS public key"); + } + /* Note that this warns more loudly about time and validity if we were + * _trying_ to connect to an authority, not necessarily if we _did_ connect + * to one. */ + if (router_digest_is_trusted_dir( + TLS_CHAN_TO_BASE(chan)->identity_digest)) + severity = LOG_WARN; + else + severity = LOG_PROTOCOL_WARN; + + if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0)) + ERR("The link certificate was not valid"); + if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1)) + ERR("The ID certificate was not valid"); + + chan->conn->handshake_state->authenticated = 1; + { + const digests_t *id_digests = tor_cert_get_id_digests(id_cert); + crypto_pk_t *identity_rcvd; + if (!id_digests) + ERR("Couldn't compute digests for key in ID cert"); + + identity_rcvd = tor_tls_cert_get_key(id_cert); + if (!identity_rcvd) + ERR("Internal error: Couldn't get RSA key from ID cert."); + memcpy(chan->conn->handshake_state->authenticated_peer_id, + id_digests->d[DIGEST_SHA1], DIGEST_LEN); + channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd, + chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); + crypto_pk_free(identity_rcvd); + } + + if (connection_or_client_learned_peer_id(chan->conn, + chan->conn->handshake_state->authenticated_peer_id) < 0) + ERR("Problem setting or checking peer id"); + + log_info(LD_OR, + "Got some good certificates from %s:%d: Authenticated it.", + safe_str(chan->conn->base_.address), chan->conn->base_.port); + + chan->conn->handshake_state->id_cert = id_cert; + id_cert = NULL; + + if (!public_server_mode(get_options())) { + /* If we initiated the connection and we are not a public server, we + * aren't planning to authenticate at all. At this point we know who we + * are talking to, so we can just send a netinfo now. */ + send_netinfo = 1; + } + } else { + if (! (id_cert && auth_cert)) + ERR("The certs we wanted were missing"); + + /* Remember these certificates so we can check an AUTHENTICATE cell */ + if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, 1)) + ERR("The authentication certificate was not valid"); + if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1)) + ERR("The ID certificate was not valid"); + + log_info(LD_OR, + "Got some good certificates from %s:%d: " + "Waiting for AUTHENTICATE.", + safe_str(chan->conn->base_.address), + chan->conn->base_.port); + /* XXXX check more stuff? */ + + chan->conn->handshake_state->id_cert = id_cert; + chan->conn->handshake_state->auth_cert = auth_cert; + id_cert = auth_cert = NULL; + } + + chan->conn->handshake_state->received_certs_cell = 1; + + if (send_netinfo) { + if (connection_or_send_netinfo(chan->conn) < 0) { + log_warn(LD_OR, "Couldn't send netinfo cell"); + connection_or_close_for_error(chan->conn, 0); + goto err; + } + } + + err: + tor_cert_free(id_cert); + tor_cert_free(link_cert); + tor_cert_free(auth_cert); +#undef ERR +} + +/** + * Process an AUTH_CHALLENGE cell from a channel_tls_t + * + * This function is called to handle an incoming AUTH_CHALLENGE cell on a + * channel_tls_t; if we weren't supposed to get one (for example, because we're + * not the originator of the channel), or it's ill-formed, or we aren't doing + * a v3 handshake, mark the channel. If the cell is well-formed but we don't + * want to authenticate, just drop it. If the cell is well-formed *and* we + * want to authenticate, send an AUTHENTICATE cell and then a NETINFO cell. + */ + +static void +channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan) +{ + int n_types, i, use_type = -1; + uint8_t *cp; + + tor_assert(cell); + tor_assert(chan); + tor_assert(chan->conn); + +#define ERR(s) \ + do { \ + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ + "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \ + safe_str(chan->conn->base_.address), \ + chan->conn->base_.port, (s)); \ + connection_or_close_for_error(chan->conn, 0); \ + return; \ + } while (0) + + if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) + ERR("We're not currently doing a v3 handshake"); + if (chan->conn->link_proto < 3) + ERR("We're not using link protocol >= 3"); + if (!(chan->conn->handshake_state->started_here)) + ERR("We didn't originate this connection"); + if (chan->conn->handshake_state->received_auth_challenge) + ERR("We already received one"); + if (!(chan->conn->handshake_state->received_certs_cell)) + ERR("We haven't gotten a CERTS cell yet"); + if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2) + ERR("It was too short"); + if (cell->circ_id) + ERR("It had a nonzero circuit ID"); + + n_types = ntohs(get_uint16(cell->payload + OR_AUTH_CHALLENGE_LEN)); + if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2 + 2*n_types) + ERR("It looks truncated"); + + /* Now see if there is an authentication type we can use */ + cp = cell->payload+OR_AUTH_CHALLENGE_LEN + 2; + for (i = 0; i < n_types; ++i, cp += 2) { + uint16_t authtype = ntohs(get_uint16(cp)); + if (authtype == AUTHTYPE_RSA_SHA256_TLSSECRET) + use_type = authtype; + } + + chan->conn->handshake_state->received_auth_challenge = 1; + + if (! public_server_mode(get_options())) { + /* If we're not a public server then we don't want to authenticate on a + connection we originated, and we already sent a NETINFO cell when we + got the CERTS cell. We have nothing more to do. */ + return; + } + + if (use_type >= 0) { + log_info(LD_OR, + "Got an AUTH_CHALLENGE cell from %s:%d: Sending " + "authentication", + safe_str(chan->conn->base_.address), + chan->conn->base_.port); + + if (connection_or_send_authenticate_cell(chan->conn, use_type) < 0) { + log_warn(LD_OR, + "Couldn't send authenticate cell"); + connection_or_close_for_error(chan->conn, 0); + return; + } + } else { + log_info(LD_OR, + "Got an AUTH_CHALLENGE cell from %s:%d, but we don't " + "know any of its authentication types. Not authenticating.", + safe_str(chan->conn->base_.address), + chan->conn->base_.port); + } + + if (connection_or_send_netinfo(chan->conn) < 0) { + log_warn(LD_OR, "Couldn't send netinfo cell"); + connection_or_close_for_error(chan->conn, 0); + return; + } + +#undef ERR +} + +/** + * Process an AUTHENTICATE cell from a channel_tls_t + * + * If it's ill-formed or we weren't supposed to get one or we're not doing a + * v3 handshake, then mark the connection. If it does not authenticate the + * other side of the connection successfully (because it isn't signed right, + * we didn't get a CERTS cell, etc) mark the connection. Otherwise, accept + * the identity of the router on the other side of the connection. + */ + +static void +channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan) +{ + uint8_t expected[V3_AUTH_FIXED_PART_LEN]; + const uint8_t *auth; + int authlen; + + tor_assert(cell); + tor_assert(chan); + tor_assert(chan->conn); + +#define ERR(s) \ + do { \ + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ + "Received a bad AUTHENTICATE cell from %s:%d: %s", \ + safe_str(chan->conn->base_.address), \ + chan->conn->base_.port, (s)); \ + connection_or_close_for_error(chan->conn, 0); \ + return; \ + } while (0) + + if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) + ERR("We're not doing a v3 handshake"); + if (chan->conn->link_proto < 3) + ERR("We're not using link protocol >= 3"); + if (chan->conn->handshake_state->started_here) + ERR("We originated this connection"); + if (chan->conn->handshake_state->received_authenticate) + ERR("We already got one!"); + if (chan->conn->handshake_state->authenticated) { + /* Should be impossible given other checks */ + ERR("The peer is already authenticated"); + } + if (!(chan->conn->handshake_state->received_certs_cell)) + ERR("We never got a certs cell"); + if (chan->conn->handshake_state->auth_cert == NULL) + ERR("We never got an authentication certificate"); + if (chan->conn->handshake_state->id_cert == NULL) + ERR("We never got an identity certificate"); + if (cell->payload_len < 4) + ERR("Cell was way too short"); + + auth = cell->payload; + { + uint16_t type = ntohs(get_uint16(auth)); + uint16_t len = ntohs(get_uint16(auth+2)); + if (4 + len > cell->payload_len) + ERR("Authenticator was truncated"); + + if (type != AUTHTYPE_RSA_SHA256_TLSSECRET) + ERR("Authenticator type was not recognized"); + + auth += 4; + authlen = len; + } + + if (authlen < V3_AUTH_BODY_LEN + 1) + ERR("Authenticator was too short"); + + if (connection_or_compute_authenticate_cell_body( + chan->conn, expected, sizeof(expected), NULL, 1) < 0) + ERR("Couldn't compute expected AUTHENTICATE cell body"); + + if (tor_memneq(expected, auth, sizeof(expected))) + ERR("Some field in the AUTHENTICATE cell body was not as expected"); + + { + crypto_pk_t *pk = tor_tls_cert_get_key( + chan->conn->handshake_state->auth_cert); + char d[DIGEST256_LEN]; + char *signed_data; + size_t keysize; + int signed_len; + + if (!pk) + ERR("Internal error: couldn't get RSA key from AUTH cert."); + crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256); + + keysize = crypto_pk_keysize(pk); + signed_data = tor_malloc(keysize); + signed_len = crypto_pk_public_checksig(pk, signed_data, keysize, + (char*)auth + V3_AUTH_BODY_LEN, + authlen - V3_AUTH_BODY_LEN); + crypto_pk_free(pk); + if (signed_len < 0) { + tor_free(signed_data); + ERR("Signature wasn't valid"); + } + if (signed_len < DIGEST256_LEN) { + tor_free(signed_data); + ERR("Not enough data was signed"); + } + /* Note that we deliberately allow *more* than DIGEST256_LEN bytes here, + * in case they're later used to hold a SHA3 digest or something. */ + if (tor_memneq(signed_data, d, DIGEST256_LEN)) { + tor_free(signed_data); + ERR("Signature did not match data to be signed."); + } + tor_free(signed_data); + } + + /* Okay, we are authenticated. */ + chan->conn->handshake_state->received_authenticate = 1; + chan->conn->handshake_state->authenticated = 1; + chan->conn->handshake_state->digest_received_data = 0; + { + crypto_pk_t *identity_rcvd = + tor_tls_cert_get_key(chan->conn->handshake_state->id_cert); + const digests_t *id_digests = + tor_cert_get_id_digests(chan->conn->handshake_state->id_cert); + + /* This must exist; we checked key type when reading the cert. */ + tor_assert(id_digests); + + memcpy(chan->conn->handshake_state->authenticated_peer_id, + id_digests->d[DIGEST_SHA1], DIGEST_LEN); + + channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd, + chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); + crypto_pk_free(identity_rcvd); + + connection_or_init_conn_from_address(chan->conn, + &(chan->conn->base_.addr), + chan->conn->base_.port, + (const char*)(chan->conn->handshake_state-> + authenticated_peer_id), + 0); + + log_info(LD_OR, + "Got an AUTHENTICATE cell from %s:%d: Looks good.", + safe_str(chan->conn->base_.address), + chan->conn->base_.port); + } + +#undef ERR +} + diff --git a/src/or/channeltls.h b/src/or/channeltls.h new file mode 100644 index 0000000000..b4a7e2beac --- /dev/null +++ b/src/or/channeltls.h @@ -0,0 +1,57 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file channeltls.h + * \brief Header file for channeltls.c + **/ + +#ifndef TOR_CHANNELTLS_H +#define TOR_CHANNELTLS_H + +#include "or.h" +#include "channel.h" + +#define BASE_CHAN_TO_TLS(c) (channel_tls_from_base((c))) +#define TLS_CHAN_TO_BASE(c) (channel_tls_to_base((c))) + +#define TLS_CHAN_MAGIC 0x8a192427U + +#ifdef TOR_CHANNEL_INTERNAL_ + +struct channel_tls_s { + /* Base channel_t struct */ + channel_t base_; + /* or_connection_t pointer */ + or_connection_t *conn; +}; + +#endif /* TOR_CHANNEL_INTERNAL_ */ + +channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port, + const char *id_digest); +channel_listener_t * channel_tls_get_listener(void); +channel_listener_t * channel_tls_start_listener(void); +channel_t * channel_tls_handle_incoming(or_connection_t *orconn); + +/* Casts */ + +channel_t * channel_tls_to_base(channel_tls_t *tlschan); +channel_tls_t * channel_tls_from_base(channel_t *chan); + +/* Things for connection_or.c to call back into */ +ssize_t channel_tls_flush_some_cells(channel_tls_t *chan, ssize_t num_cells); +int channel_tls_more_to_flush(channel_tls_t *chan); +void channel_tls_handle_cell(cell_t *cell, or_connection_t *conn); +void channel_tls_handle_state_change_on_orconn(channel_tls_t *chan, + or_connection_t *conn, + uint8_t old_state, + uint8_t state); +void channel_tls_handle_var_cell(var_cell_t *var_cell, + or_connection_t *conn); + +/* Cleanup at shutdown */ +void channel_tls_free_all(void); + +#endif + diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 1c692ab87b..2b4d3c3118 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,22 +9,28 @@ * \brief The actual details of building circuits. **/ -#define CIRCUIT_PRIVATE - #include "or.h" +#include "channel.h" #include "circuitbuild.h" #include "circuitlist.h" +#include "circuitstats.h" #include "circuituse.h" +#include "command.h" #include "config.h" +#include "confparse.h" #include "connection.h" #include "connection_edge.h" #include "connection_or.h" #include "control.h" #include "directory.h" +#include "entrynodes.h" #include "main.h" +#include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" #include "onion.h" +#include "onion_tap.h" +#include "onion_fast.h" #include "policies.h" #include "transports.h" #include "relay.h" @@ -32,1645 +38,58 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "routerset.h" #include "crypto.h" -#undef log -#include <math.h> +#include "connection_edge.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 */ -// XXXX: 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. -/* XXXX024 Make this static; add accessor functions. */ -circuit_build_times_t circ_times; /** A global list of all circuits at this hop. */ extern circuit_t *global_circuitlist; -/** An entry_guard_t represents our information about a chosen long-term - * first hop, known as a "helper" node in the literature. We can't just - * use a node_t, since we want to remember these even when we - * don't have any directory info. */ -typedef struct { - char nickname[MAX_NICKNAME_LEN+1]; - char identity[DIGEST_LEN]; - time_t chosen_on_date; /**< Approximately when was this guard added? - * "0" if we don't know. */ - char *chosen_by_version; /**< What tor version added this guard? NULL - * if we don't know. */ - unsigned int made_contact : 1; /**< 0 if we have never connected to this - * router, 1 if we have. */ - unsigned int can_retry : 1; /**< Should we retry connecting to this entry, - * in spite of having it marked as unreachable?*/ - unsigned int path_bias_notice : 1; /**< Did we alert the user about path bias - * for this node already? */ - unsigned int path_bias_disabled : 1; /**< Have we disabled this node because - * of path bias issues? */ - time_t bad_since; /**< 0 if this guard is currently usable, or the time at - * which it was observed to become (according to the - * directory or the user configuration) unusable. */ - time_t unreachable_since; /**< 0 if we can connect to this guard, or the - * time at which we first noticed we couldn't - * connect to it. */ - time_t last_attempted; /**< 0 if we can connect to this guard, or the time - * at which we last failed to connect to it. */ - - unsigned first_hops; /**< Number of first hops this guard has completed */ - unsigned circuit_successes; /**< Number of successfully built circuits using - * this guard as first hop. */ -} entry_guard_t; - -/** Information about a configured bridge. Currently this just matches the - * ones in the torrc file, but one day we may be able to learn about new - * bridges on our own, and remember them in the state file. */ -typedef struct { - /** Address of the bridge. */ - tor_addr_t addr; - /** TLS port for the bridge. */ - uint16_t port; - /** Boolean: We are re-parsing our bridge list, and we are going to remove - * this one if we don't find it in the list of configured bridges. */ - unsigned marked_for_removal : 1; - /** Expected identity digest, or all zero bytes if we don't know what the - * digest should be. */ - char identity[DIGEST_LEN]; - - /** Name of pluggable transport protocol taken from its config line. */ - char *transport_name; - - /** When should we next try to fetch a descriptor for this bridge? */ - download_status_t fetch_status; -} bridge_info_t; - -/** A list of our chosen entry guards. */ -static smartlist_t *entry_guards = NULL; -/** A value of 1 means that the entry_guards list has changed - * 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 channel_t * channel_connect_for_circuit(const tor_addr_t *addr, + uint16_t port, + const char *id_digest); static int circuit_deliver_create_cell(circuit_t *circ, - uint8_t cell_type, const char *payload); + const create_cell_t *create_cell, + int relayed); static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit); static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath); static int onion_extend_cpath(origin_circuit_t *circ); static int count_acceptable_nodes(smartlist_t *routers); static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice); - -static void entry_guards_changed(void); -static entry_guard_t *entry_guard_get_by_id_digest(const char *digest); - -static void bridge_free(bridge_info_t *bridge); - -static int entry_guard_inc_first_hop_count(entry_guard_t *guard); -static void pathbias_count_success(origin_circuit_t *circ); - -/** - * This function decides if CBT learning should be disabled. It returns - * true if one or more of the following four conditions are met: - * - * 1. If the cbtdisabled consensus parameter is set. - * 2. If the torrc option LearnCircuitBuildTimeout is false. - * 3. If we are a directory authority - * 4. If we fail to write circuit build time history to our state file. - */ -int -circuit_build_times_disabled(void) -{ - if (unit_tests) { - return 0; - } else { - int consensus_disabled = networkstatus_get_param(NULL, "cbtdisabled", - 0, 0, 1); - int config_disabled = !get_options()->LearnCircuitBuildTimeout; - int dirauth_disabled = get_options()->AuthoritativeDir; - int state_disabled = did_last_state_file_write_fail() ? 1 : 0; - - if (consensus_disabled || config_disabled || dirauth_disabled || - state_disabled) { - log_debug(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 { - log_debug(LD_CIRC, - "CircuitBuildTime learning is not disabled. " - "Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d", - consensus_disabled, config_disabled, dirauth_disabled, - state_disabled); - return 0; - } - } -} - -/** - * Retrieve and bounds-check the cbtmaxtimeouts consensus paramter. - * - * Effect: When this many timeouts happen in the last 'cbtrecentcount' - * circuit attempts, the client should discard all of its history and - * begin learning a fresh timeout value. - */ -static int32_t -circuit_build_times_max_timeouts(void) -{ - int32_t cbt_maxtimeouts; - - cbt_maxtimeouts = networkstatus_get_param(NULL, "cbtmaxtimeouts", - CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT, - CBT_MIN_MAX_RECENT_TIMEOUT_COUNT, - CBT_MAX_MAX_RECENT_TIMEOUT_COUNT); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_max_timeouts() called, cbtmaxtimeouts is" - " %d", - cbt_maxtimeouts); - } - - return cbt_maxtimeouts; -} - -/** - * Retrieve and bounds-check the cbtnummodes consensus paramter. - * - * Effect: This value governs how many modes to use in the weighted - * average calculation of Pareto parameter Xm. A value of 3 introduces - * some bias (2-5% of CDF) under ideal conditions, but allows for better - * performance in the event that a client chooses guard nodes of radically - * different performance characteristics. - */ -static int32_t -circuit_build_times_default_num_xm_modes(void) -{ - int32_t num = networkstatus_get_param(NULL, "cbtnummodes", - CBT_DEFAULT_NUM_XM_MODES, - CBT_MIN_NUM_XM_MODES, - CBT_MAX_NUM_XM_MODES); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_default_num_xm_modes() called, cbtnummodes" - " is %d", - num); - } - - return num; -} - -/** - * Retrieve and bounds-check the cbtmincircs consensus paramter. - * - * Effect: This is the minimum number of circuits to build before - * computing a timeout. - */ -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, - CBT_MIN_MIN_CIRCUITS_TO_OBSERVE, - CBT_MAX_MIN_CIRCUITS_TO_OBSERVE); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_min_circs_to_observe() called, cbtmincircs" - " is %d", - num); - } - - 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(); -} - -/** - * Retrieve and bounds-check the cbtquantile consensus paramter. - * - * Effect: This is the position on the quantile curve to use to set the - * timeout value. It is a percent (10-99). - */ -double -circuit_build_times_quantile_cutoff(void) -{ - int32_t num = networkstatus_get_param(NULL, "cbtquantile", - CBT_DEFAULT_QUANTILE_CUTOFF, - CBT_MIN_QUANTILE_CUTOFF, - CBT_MAX_QUANTILE_CUTOFF); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_quantile_cutoff() called, cbtquantile" - " is %d", - num); - } - - return num/100.0; -} - -/* DOCDOC circuit_build_times_get_bw_scale */ -int -circuit_build_times_get_bw_scale(networkstatus_t *ns) -{ - return networkstatus_get_param(ns, "bwweightscale", - BW_WEIGHT_SCALE, - BW_MIN_WEIGHT_SCALE, - BW_MAX_WEIGHT_SCALE); -} - -/** - * Retrieve and bounds-check the cbtclosequantile consensus paramter. - * - * Effect: This is the position on the quantile curve to use to set the - * timeout value to use to actually close circuits. It is a percent - * (0-99). - */ -static double -circuit_build_times_close_quantile(void) -{ - int32_t param; - /* Cast is safe - circuit_build_times_quantile_cutoff() is capped */ - int32_t min = (int)tor_lround(100*circuit_build_times_quantile_cutoff()); - param = networkstatus_get_param(NULL, "cbtclosequantile", - CBT_DEFAULT_CLOSE_QUANTILE, - CBT_MIN_CLOSE_QUANTILE, - CBT_MAX_CLOSE_QUANTILE); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_close_quantile() called, cbtclosequantile" - " is %d", param); - } - - if (param < min) { - log_warn(LD_DIR, "Consensus parameter cbtclosequantile is " - "too small, raising to %d", min); - param = min; - } - return param / 100.0; -} - -/** - * Retrieve and bounds-check the cbttestfreq consensus paramter. - * - * Effect: Describes how often in seconds to build a test circuit to - * gather timeout values. Only applies if less than 'cbtmincircs' - * have been recorded. - */ -static int32_t -circuit_build_times_test_frequency(void) -{ - int32_t num = networkstatus_get_param(NULL, "cbttestfreq", - CBT_DEFAULT_TEST_FREQUENCY, - CBT_MIN_TEST_FREQUENCY, - CBT_MAX_TEST_FREQUENCY); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_test_frequency() called, cbttestfreq is %d", - num); - } - - return num; -} - -/** - * Retrieve and bounds-check the cbtmintimeout consensus parameter. - * - * Effect: This is the minimum allowed timeout value in milliseconds. - * The minimum is to prevent rounding to 0 (we only check once - * per second). - */ -static int32_t -circuit_build_times_min_timeout(void) -{ - int32_t num = networkstatus_get_param(NULL, "cbtmintimeout", - CBT_DEFAULT_TIMEOUT_MIN_VALUE, - CBT_MIN_TIMEOUT_MIN_VALUE, - CBT_MAX_TIMEOUT_MIN_VALUE); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_min_timeout() called, cbtmintimeout is %d", - num); - } - - return num; -} - -/** - * Retrieve and bounds-check the cbtinitialtimeout consensus paramter. - * - * Effect: This is the timeout value to use before computing a timeout, - * in milliseconds. - */ -int32_t -circuit_build_times_initial_timeout(void) -{ - int32_t min = circuit_build_times_min_timeout(); - int32_t param = networkstatus_get_param(NULL, "cbtinitialtimeout", - CBT_DEFAULT_TIMEOUT_INITIAL_VALUE, - CBT_MIN_TIMEOUT_INITIAL_VALUE, - CBT_MAX_TIMEOUT_INITIAL_VALUE); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_initial_timeout() called, " - "cbtinitialtimeout is %d", - param); - } - - if (param < min) { - log_warn(LD_DIR, "Consensus parameter cbtinitialtimeout is too small, " - "raising to %d", min); - param = min; - } - return param; -} - -/** - * Retrieve and bounds-check the cbtrecentcount consensus paramter. - * - * Effect: This is the number of circuit build times to keep track of - * for deciding if we hit cbtmaxtimeouts and need to reset our state - * and learn a new timeout. - */ -static int32_t -circuit_build_times_recent_circuit_count(networkstatus_t *ns) -{ - int32_t num; - num = networkstatus_get_param(ns, "cbtrecentcount", - CBT_DEFAULT_RECENT_CIRCUITS, - CBT_MIN_RECENT_CIRCUITS, - CBT_MAX_RECENT_CIRCUITS); - - if (!(get_options()->LearnCircuitBuildTimeout)) { - log_debug(LD_BUG, - "circuit_build_times_recent_circuit_count() called, " - "cbtrecentcount is %d", - num); - } - - 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; - - /* - * First check if we're doing adaptive timeouts at all; nothing to - * update if we aren't. - */ - - if (!circuit_build_times_disabled()) { - num = circuit_build_times_recent_circuit_count(ns); - - if (num > 0) { - if (num != cbt->liveness.num_recent_circs) { - int8_t *recent_circs; - log_notice(LD_CIRC, "The Tor Directory Consensus has changed how many " - "circuits we must track to detect network failures from %d " - "to %d.", cbt->liveness.num_recent_circs, num); - - tor_assert(cbt->liveness.timeouts_after_firsthop || - cbt->liveness.num_recent_circs == 0); - - /* - * 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); - if (cbt->liveness.timeouts_after_firsthop && - cbt->liveness.num_recent_circs > 0) { - 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; - } - /* else no change, nothing to do */ - } else { /* num == 0 */ - /* - * Weird. This probably shouldn't happen, so log a warning, but try - * to do something sensible anyway. - */ - - log_warn(LD_CIRC, - "The cbtrecentcircs consensus parameter came back zero! " - "This disables adaptive timeouts since we can't keep track of " - "any recent circuits."); - - circuit_build_times_free_timeouts(cbt); - } - } else { - /* - * Adaptive timeouts are disabled; this might be because of the - * LearnCircuitBuildTimes config parameter, and hence permanent, or - * the cbtdisabled consensus parameter, so it may be a new condition. - * Treat it like getting num == 0 above and free the circuit history - * if we have any. - */ - - circuit_build_times_free_timeouts(cbt); - } -} - -/** 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; - - /* - * Check if we have LearnCircuitBuildTimeout, and if we don't, - * always use CircuitBuildTimeout, no questions asked. - */ - if (get_options()->LearnCircuitBuildTimeout) { - 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(); - } - } else { - timeout = get_options()->CircuitBuildTimeout*1000; - } - - 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)); - /* - * Check if we really are using adaptive timeouts, and don't keep - * track of this stuff if not. - */ - if (!circuit_build_times_disabled()) { - cbt->liveness.num_recent_circs = - circuit_build_times_recent_circuit_count(NULL); - cbt->liveness.timeouts_after_firsthop = - tor_malloc_zero(sizeof(int8_t)*cbt->liveness.num_recent_circs); - } else { - cbt->liveness.num_recent_circs = 0; - cbt->liveness.timeouts_after_firsthop = NULL; - } - cbt->close_ms = cbt->timeout_ms = circuit_build_times_get_initial_timeout(); - control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET); -} - -/** - * Free the saved timeouts, if the cbtdisabled consensus parameter got turned - * on or something. - */ - -void -circuit_build_times_free_timeouts(circuit_build_times_t *cbt) -{ - if (!cbt) return; - - if (cbt->liveness.timeouts_after_firsthop) { - tor_free(cbt->liveness.timeouts_after_firsthop); - } - - cbt->liveness.num_recent_circs = 0; -} - -#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</b> 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; -} +static int entry_guard_inc_circ_attempt_count(entry_guard_t *guard); +static void pathbias_count_build_success(origin_circuit_t *circ); +static void pathbias_count_successful_close(origin_circuit_t *circ); +static void pathbias_count_collapse(origin_circuit_t *circ); +static void pathbias_count_use_failed(origin_circuit_t *circ); +static void pathbias_measure_use_rate(entry_guard_t *guard); +static void pathbias_measure_close_rate(entry_guard_t *guard); +static void pathbias_scale_use_rates(entry_guard_t *guard); +#ifdef CURVE25519_ENABLED +static int circuits_can_use_ntor(void); #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 most frequent build time bins. N is either - * 1 if we don't have enough circuit build time data collected, or - * determined by the consensus parameter cbtnummodes (default 3). - */ -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(); - - tor_assert(nbins > 0); - tor_assert(num_modes > 0); - - // 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)); - - /* Determine the N most common build times */ - 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]]); - } - - /* The following assert is safe, because we don't get called when we - * haven't observed at least CBT_MIN_MIN_CIRCUITS_TO_OBSERVE circuits. */ - tor_assert(bin_counts > 0); - - 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"); - tor_asprintf(&line->value, "%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. - * - * Adapted from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle - */ -static void -circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, - build_time_t *raw_times, - uint32_t num_times) -{ - uint32_t n = num_times; - if (num_times > CBT_NCIRCUITS_TO_OBSERVE) { - log_notice(LD_CIRC, "The number of circuit times that this Tor version " - "uses to calculate build times is less than the number stored " - "in your state file. Decreasing the circuit time history from " - "%lu to %d.", (unsigned long)num_times, - CBT_NCIRCUITS_TO_OBSERVE); - } - - if (n > INT_MAX-1) { - log_warn(LD_CIRC, "For some insane reasons, you had %lu circuit build " - "observations in your state file. That's far too many; probably " - "there's a bug here.", (unsigned long)n); - n = INT_MAX-1; - } - - /* This code can only be run on a compact array */ - 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_new(); - 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) -{ - /* Check for NULLness because we might not be using adaptive timeouts */ - if (cbt->liveness.timeouts_after_firsthop && - cbt->liveness.num_recent_circs > 0) { - 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) -{ - /* Check for NULLness because we might not be using adaptive timeouts */ - if (cbt->liveness.timeouts_after_firsthop && - cbt->liveness.num_recent_circs > 0) { - 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 recording.", - (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; - - if (cbt->liveness.timeouts_after_firsthop && - cbt->liveness.num_recent_circs > 0) { - /* 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); - if (cbt->liveness.timeouts_after_firsthop && - cbt->liveness.num_recent_circs > 0) { - 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 = %fmsec, close = %fmsec)", - 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, - "Your 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_info(LD_CIRC, - "Circuit build timeout of %dms is beyond the maximum build " - "time we have ever observed. Capping it to %dms.", - (int)cbt->timeout_ms, max_time); - cbt->timeout_ms = max_time; - } - - if (max_time < INT32_MAX/2 && cbt->close_ms > 2*max_time) { - log_info(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. +/** This function tries to get a channel to the specified endpoint, + * and then calls command_setup_channel() to give it the right + * callbacks. */ -void -circuit_build_times_set_timeout(circuit_build_times_t *cbt) +static channel_t * +channel_connect_for_circuit(const tor_addr_t *addr, uint16_t port, + const char *id_digest) { - long prev_timeout = tor_lround(cbt->timeout_ms/1000); - double timeout_rate; - - /* - * Just return if we aren't using adaptive timeouts - */ - if (circuit_build_times_disabled()) - return; - - if (!circuit_build_times_set_timeout_worker(cbt)) - return; - - if (cbt->timeout_ms < circuit_build_times_min_timeout()) { - log_info(LD_CIRC, "Set buildtimeout to low value %fms. Setting to %dms", - cbt->timeout_ms, circuit_build_times_min_timeout()); - cbt->timeout_ms = circuit_build_times_min_timeout(); - if (cbt->close_ms < cbt->timeout_ms) { - /* 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); + channel_t *chan; - timeout_rate = circuit_build_times_timeout_rate(cbt); + chan = channel_connect(addr, port, id_digest); + if (chan) command_setup_channel(chan); - if (prev_timeout > tor_lround(cbt->timeout_ms/1000)) { - log_info(LD_CIRC, - "Based on %d circuit times, it looks like we don't need to " - "wait so long for circuits to finish. We will now assume a " - "circuit is too slow to use after waiting %ld seconds.", - cbt->total_build_times, - tor_lround(cbt->timeout_ms/1000)); - log_info(LD_CIRC, - "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f", - cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, - timeout_rate); - } else if (prev_timeout < tor_lround(cbt->timeout_ms/1000)) { - log_info(LD_CIRC, - "Based on %d circuit times, it looks like we need to wait " - "longer for circuits to finish. We will now assume a " - "circuit is too slow to use after waiting %ld seconds.", - cbt->total_build_times, - tor_lround(cbt->timeout_ms/1000)); - log_info(LD_CIRC, - "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f", - cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, - timeout_rate); - } else { - log_info(LD_CIRC, - "Set circuit build timeout to %lds (%fms, %fms, Xm: %d, a: %f," - " r: %f) based on %d circuit times", - tor_lround(cbt->timeout_ms/1000), - cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, timeout_rate, - cbt->total_build_times); - } + return chan; } /** Iterate over values of circ_id, starting from conn-\>next_circ_id, @@ -1680,36 +99,46 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt) * Return it, or 0 if can't get a unique circ_id. */ static circid_t -get_unique_circ_id_by_conn(or_connection_t *conn) +get_unique_circ_id_by_chan(channel_t *chan) { circid_t test_circ_id; circid_t attempts=0; - circid_t high_bit; + circid_t high_bit, max_range; - tor_assert(conn); - if (conn->circ_id_type == CIRC_ID_TYPE_NEITHER) { - log_warn(LD_BUG, "Trying to pick a circuit ID for a connection from " + tor_assert(chan); + + if (chan->circ_id_type == CIRC_ID_TYPE_NEITHER) { + log_warn(LD_BUG, + "Trying to pick a circuit ID for a connection from " "a client with no identity."); return 0; } - high_bit = (conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0; + max_range = (chan->wide_circ_ids) ? (1u<<31) : (1u<<15); + high_bit = (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? max_range : 0; do { - /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a + /* Sequentially iterate over test_circ_id=1...max_range until we find a * circID such that (high_bit|test_circ_id) is not already used. */ - test_circ_id = conn->next_circ_id++; - if (test_circ_id == 0 || test_circ_id >= 1<<15) { + test_circ_id = chan->next_circ_id++; + if (test_circ_id == 0 || test_circ_id >= max_range) { test_circ_id = 1; - conn->next_circ_id = 2; + chan->next_circ_id = 2; } - if (++attempts > 1<<15) { + if (++attempts > max_range) { /* Make sure we don't loop forever if all circ_id's are used. This * matters because it's an external DoS opportunity. */ - log_warn(LD_CIRC,"No unused circ IDs. Failing."); + if (! chan->warned_circ_ids_exhausted) { + chan->warned_circ_ids_exhausted = 1; + log_warn(LD_CIRC,"No unused circIDs found on channel %s wide " + "circID support, with %u inbound and %u outbound circuits. " + "Failing a circuit.", + chan->wide_circ_ids ? "with" : "without", + chan->num_p_circuits, chan->num_n_circuits); + } return 0; } test_circ_id |= high_bit; - } while (circuit_id_in_use_on_orconn(test_circ_id, conn)); + } while (circuit_id_in_use_on_channel(test_circ_id, chan)); return test_circ_id; } @@ -1736,8 +165,8 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) 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 ? "" : ", last hop ", - circ->_base.state == CIRCUIT_STATE_OPEN ? "" : + circ->base_.state == CIRCUIT_STATE_OPEN ? "" : ", last hop ", + circ->base_.state == CIRCUIT_STATE_OPEN ? "" : (nickname?nickname:"*unnamed*")); } @@ -1865,21 +294,74 @@ circuit_rep_hist_note_result(origin_circuit_t *circ) } while (hop!=circ->cpath); } +#ifdef CURVE25519_ENABLED +/** Return 1 iff at least one node in circ's cpath supports ntor. */ +static int +circuit_cpath_supports_ntor(const origin_circuit_t *circ) +{ + crypt_path_t *head = circ->cpath, *cpath = circ->cpath; + + cpath = head; + do { + if (cpath->extend_info && + !tor_mem_is_zero( + (const char*)cpath->extend_info->curve25519_onion_key.public_key, + CURVE25519_PUBKEY_LEN)) + return 1; + + cpath = cpath->next; + } while (cpath != head); + + return 0; +} +#else +#define circuit_cpath_supports_ntor(circ) 0 +#endif + /** Pick all the entries in our cpath. Stop and return 0 when we're * happy, or return -1 if an error occurs. */ static int onion_populate_cpath(origin_circuit_t *circ) { - int r; - again: - r = onion_extend_cpath(circ); - if (r < 0) { - log_info(LD_CIRC,"Generating cpath hop failed."); - return -1; + int n_tries = 0; +#ifdef CURVE25519_ENABLED + const int using_ntor = circuits_can_use_ntor(); +#else + const int using_ntor = 0; +#endif + +#define MAX_POPULATE_ATTEMPTS 32 + + while (1) { + int r = onion_extend_cpath(circ); + if (r < 0) { + log_info(LD_CIRC,"Generating cpath hop failed."); + return -1; + } + if (r == 1) { + /* This circuit doesn't need/shouldn't be forced to have an ntor hop */ + if (circ->build_state->desired_path_len <= 1 || ! using_ntor) + return 0; + + /* This circuit has an ntor hop. great! */ + if (circuit_cpath_supports_ntor(circ)) + return 0; + + /* No node in the circuit supports ntor. Have we already tried too many + * times? */ + if (++n_tries >= MAX_POPULATE_ATTEMPTS) + break; + + /* Clear the path and retry */ + circuit_clear_cpath(circ); + } } - if (r == 0) - goto again; - return 0; /* if r == 1 */ + log_warn(LD_CIRC, "I tried for %d times, but I couldn't build a %d-hop " + "circuit with at least one node that supports ntor.", + MAX_POPULATE_ATTEMPTS, + circ->build_state->desired_path_len); + + return -1; } /** Create and return a new origin circuit. Initialize its purpose and @@ -1888,9 +370,9 @@ onion_populate_cpath(origin_circuit_t *circ) origin_circuit_t * origin_circuit_init(uint8_t purpose, int flags) { - /* sets circ->p_circ_id and circ->p_conn */ + /* sets circ->p_circ_id and circ->p_chan */ origin_circuit_t *circ = origin_circuit_new(); - circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT); + circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_CHAN_WAIT); circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); circ->build_state->onehop_tunnel = ((flags & CIRCLAUNCH_ONEHOP_TUNNEL) ? 1 : 0); @@ -1900,7 +382,7 @@ origin_circuit_init(uint8_t purpose, int flags) ((flags & CIRCLAUNCH_NEED_CAPACITY) ? 1 : 0); circ->build_state->is_internal = ((flags & CIRCLAUNCH_IS_INTERNAL) ? 1 : 0); - circ->_base.purpose = purpose; + circ->base_.purpose = purpose; return circ; } @@ -1942,7 +424,7 @@ int circuit_handle_first_hop(origin_circuit_t *circ) { crypt_path_t *firsthop; - or_connection_t *n_conn; + channel_t *n_chan; int err_reason = 0; const char *msg = NULL; int should_launch = 0; @@ -1952,29 +434,30 @@ circuit_handle_first_hop(origin_circuit_t *circ) tor_assert(firsthop->extend_info); /* now see if we're already connected to the first OR in 'route' */ - log_debug(LD_CIRC,"Looking for firsthop '%s:%u'", - fmt_addr(&firsthop->extend_info->addr), - firsthop->extend_info->port); + log_debug(LD_CIRC,"Looking for firsthop '%s'", + fmt_addrport(&firsthop->extend_info->addr, + firsthop->extend_info->port)); - n_conn = connection_or_get_for_extend(firsthop->extend_info->identity_digest, - &firsthop->extend_info->addr, - &msg, - &should_launch); + n_chan = channel_get_for_extend(firsthop->extend_info->identity_digest, + &firsthop->extend_info->addr, + &msg, + &should_launch); - if (!n_conn) { + if (!n_chan) { /* not currently connected in a useful way. */ log_info(LD_CIRC, "Next router is %s: %s", safe_str_client(extend_info_describe(firsthop->extend_info)), msg?msg:"???"); - circ->_base.n_hop = extend_info_dup(firsthop->extend_info); + circ->base_.n_hop = extend_info_dup(firsthop->extend_info); if (should_launch) { if (circ->build_state->onehop_tunnel) control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0); - n_conn = connection_or_connect(&firsthop->extend_info->addr, - firsthop->extend_info->port, - firsthop->extend_info->identity_digest); - if (!n_conn) { /* connect failed, forget the whole thing */ + n_chan = channel_connect_for_circuit( + &firsthop->extend_info->addr, + firsthop->extend_info->port, + firsthop->extend_info->identity_digest); + if (!n_chan) { /* connect failed, forget the whole thing */ log_info(LD_CIRC,"connect to firsthop failed. Closing."); return -END_CIRC_REASON_CONNECTFAILED; } @@ -1982,13 +465,13 @@ circuit_handle_first_hop(origin_circuit_t *circ) log_debug(LD_CIRC,"connecting in progress (or finished). Good."); /* return success. The onion/circuit/etc will be taken care of - * automatically (may already have been) whenever n_conn reaches + * automatically (may already have been) whenever n_chan reaches * OR_CONN_STATE_OPEN. */ return 0; } else { /* it's already open. use it. */ - tor_assert(!circ->_base.n_hop); - circ->_base.n_conn = n_conn; + tor_assert(!circ->base_.n_hop); + circ->base_.n_chan = n_chan; log_debug(LD_CIRC,"Conn open. Delivering first onion skin."); if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) { log_info(LD_CIRC,"circuit_send_next_onion_skin failed."); @@ -2004,48 +487,49 @@ circuit_handle_first_hop(origin_circuit_t *circ) * Status is 1 if connect succeeded, or 0 if connect failed. */ void -circuit_n_conn_done(or_connection_t *or_conn, int status) +circuit_n_chan_done(channel_t *chan, int status) { smartlist_t *pending_circs; int err_reason = 0; - log_debug(LD_CIRC,"or_conn to %s/%s, status=%d", - or_conn->nickname ? or_conn->nickname : "NULL", - or_conn->_base.address, status); + tor_assert(chan); + + log_debug(LD_CIRC,"chan to %s/%s, status=%d", + chan->nickname ? chan->nickname : "NULL", + channel_get_canonical_remote_descr(chan), status); pending_circs = smartlist_new(); - circuit_get_all_pending_on_or_conn(pending_circs, or_conn); + circuit_get_all_pending_on_channel(pending_circs, chan); SMARTLIST_FOREACH_BEGIN(pending_circs, circuit_t *, circ) { /* These checks are redundant wrt get_all_pending_on_or_conn, but I'm * leaving them in in case it's possible for the status of a circuit to * change as we're going down the list. */ - if (circ->marked_for_close || circ->n_conn || !circ->n_hop || - circ->state != CIRCUIT_STATE_OR_WAIT) + if (circ->marked_for_close || circ->n_chan || !circ->n_hop || + circ->state != CIRCUIT_STATE_CHAN_WAIT) continue; if (tor_digest_is_zero(circ->n_hop->identity_digest)) { /* Look at addr/port. This is an unkeyed connection. */ - if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) || - circ->n_hop->port != or_conn->_base.port) + if (!channel_matches_extend_info(chan, circ->n_hop)) continue; } else { /* We expected a key. See if it's the right one. */ - if (tor_memneq(or_conn->identity_digest, + if (tor_memneq(chan->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) continue; } - if (!status) { /* or_conn failed; close circ */ - log_info(LD_CIRC,"or_conn failed. Closing circ."); - circuit_mark_for_close(circ, END_CIRC_REASON_OR_CONN_CLOSED); + if (!status) { /* chan failed; close circ */ + log_info(LD_CIRC,"Channel failed; closing circ."); + circuit_mark_for_close(circ, END_CIRC_REASON_CHANNEL_CLOSED); continue; } log_debug(LD_CIRC, "Found circ, sending create cell."); /* circuit_deliver_create_cell will set n_circ_id and add us to - * orconn_circuid_circuit_map, so we don't need to call - * set_circid_orconn here. */ - circ->n_conn = or_conn; + * chan_circuid_circuit_map, so we don't need to call + * set_circid_chan here. */ + circ->n_chan = chan; extend_info_free(circ->n_hop); circ->n_hop = NULL; @@ -2060,14 +544,13 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) * died? */ } } else { - /* pull the create cell out of circ->onionskin, and send it */ - tor_assert(circ->n_conn_onionskin); - if (circuit_deliver_create_cell(circ,CELL_CREATE, - circ->n_conn_onionskin)<0) { + /* pull the create cell out of circ->n_chan_create_cell, and send it */ + tor_assert(circ->n_chan_create_cell); + if (circuit_deliver_create_cell(circ, circ->n_chan_create_cell, 1)<0) { circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); continue; } - tor_free(circ->n_conn_onionskin); + tor_free(circ->n_chan_create_cell); circuit_set_state(circ, CIRCUIT_STATE_OPEN); } } @@ -2076,44 +559,63 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) smartlist_free(pending_circs); } -/** Find a new circid that isn't currently in use on the circ->n_conn +/** Find a new circid that isn't currently in use on the circ->n_chan * for the outgoing - * circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b> - * (either CELL_CREATE or CELL_CREATE_FAST) with payload <b>payload</b> - * to this circuit. - * Return -1 if we failed to find a suitable circid, else return 0. + * circuit <b>circ</b>, and deliver the cell <b>create_cell</b> to this + * circuit. If <b>relayed</b> is true, this is a create cell somebody + * gave us via an EXTEND cell, so we shouldn't worry if we don't understand + * it. Return -1 if we failed to find a suitable circid, else return 0. */ static int -circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, - const char *payload) +circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell, + int relayed) { cell_t cell; circid_t id; + int r; tor_assert(circ); - tor_assert(circ->n_conn); - tor_assert(payload); - tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST); + tor_assert(circ->n_chan); + tor_assert(create_cell); + tor_assert(create_cell->cell_type == CELL_CREATE || + create_cell->cell_type == CELL_CREATE_FAST || + create_cell->cell_type == CELL_CREATE2); - id = get_unique_circ_id_by_conn(circ->n_conn); + id = get_unique_circ_id_by_chan(circ->n_chan); if (!id) { log_warn(LD_CIRC,"failed to get unique circID."); return -1; } - log_debug(LD_CIRC,"Chosen circID %u.", id); - circuit_set_n_circid_orconn(circ, id, circ->n_conn); + log_debug(LD_CIRC,"Chosen circID %u.", (unsigned)id); + circuit_set_n_circid_chan(circ, id, circ->n_chan); memset(&cell, 0, sizeof(cell_t)); - cell.command = cell_type; + r = relayed ? create_cell_format_relayed(&cell, create_cell) + : create_cell_format(&cell, create_cell); + if (r < 0) { + log_warn(LD_CIRC,"Couldn't format create cell"); + return -1; + } cell.circ_id = circ->n_circ_id; - memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN); - append_cell_to_circuit_queue(circ, circ->n_conn, &cell, + append_cell_to_circuit_queue(circ, circ->n_chan, &cell, CELL_DIRECTION_OUT, 0); if (CIRCUIT_IS_ORIGIN(circ)) { + /* Update began timestamp for circuits starting their first hop */ + if (TO_ORIGIN_CIRCUIT(circ)->cpath->state == CPATH_STATE_CLOSED) { + if (circ->n_chan->state != CHANNEL_STATE_OPEN) { + log_warn(LD_CIRC, + "Got first hop for a circuit without an opened channel. " + "State: %s.", channel_state_to_string(circ->n_chan->state)); + tor_fragile_assert(); + } + + tor_gettimeofday(&circ->timestamp_began); + } + /* mark it so it gets better rate limiting treatment. */ - circ->n_conn->client_used = time(NULL); + channel_timestamp_client(circ->n_chan); } return 0; @@ -2185,6 +687,73 @@ circuit_timeout_want_to_count_circ(origin_circuit_t *circ) && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN; } +#ifdef CURVE25519_ENABLED +/** Return true if the ntor handshake is enabled in the configuration, or if + * it's been set to "auto" in the configuration and it's enabled in the + * consensus. */ +static int +circuits_can_use_ntor(void) +{ + const or_options_t *options = get_options(); + if (options->UseNTorHandshake != -1) + return options->UseNTorHandshake; + return networkstatus_get_param(NULL, "UseNTorHandshake", 0, 0, 1); +} +#endif + +/** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b> + * directly, and set *<b>cell_type_out</b> and *<b>handshake_type_out</b> + * accordingly. */ +static void +circuit_pick_create_handshake(uint8_t *cell_type_out, + uint16_t *handshake_type_out, + const extend_info_t *ei) +{ +#ifdef CURVE25519_ENABLED + if (!tor_mem_is_zero((const char*)ei->curve25519_onion_key.public_key, + CURVE25519_PUBKEY_LEN) && + circuits_can_use_ntor()) { + *cell_type_out = CELL_CREATE2; + *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR; + return; + } +#else + (void) ei; +#endif + + *cell_type_out = CELL_CREATE; + *handshake_type_out = ONION_HANDSHAKE_TYPE_TAP; +} + +/** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b> + * directly, and set *<b>handshake_type_out</b> accordingly. Decide whether, + * in extending through <b>node</b> to do so, we should use an EXTEND2 or an + * EXTEND cell to do so, and set *<b>cell_type_out</b> and + * *<b>create_cell_type_out</b> accordingly. */ +static void +circuit_pick_extend_handshake(uint8_t *cell_type_out, + uint8_t *create_cell_type_out, + uint16_t *handshake_type_out, + const node_t *node_prev, + const extend_info_t *ei) +{ + uint8_t t; + circuit_pick_create_handshake(&t, handshake_type_out, ei); + /* XXXX024 The check for whether the node has a curve25519 key is a bad + * proxy for whether it can do extend2 cells; once a version that + * handles extend2 cells is out, remove it. */ + if (node_prev && + *handshake_type_out != ONION_HANDSHAKE_TYPE_TAP && + (node_has_curve25519_onion_key(node_prev) || + (node_prev->rs && node_prev->rs->version_supports_extend2_cells))) { + *cell_type_out = RELAY_COMMAND_EXTEND2; + *create_cell_type_out = CELL_CREATE2; + } else { + *cell_type_out = RELAY_COMMAND_EXTEND; + *create_cell_type_out = CELL_CREATE; + } +} + /** This is the backbone function for building circuits. * * If circ's first hop is closed, then we need to build a create @@ -2200,49 +769,50 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) { crypt_path_t *hop; const node_t *node; - char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN]; - char *onionskin; - size_t payload_len; tor_assert(circ); if (circ->cpath->state == CPATH_STATE_CLOSED) { + /* This is the first hop. */ + create_cell_t cc; int fast; - uint8_t cell_type; + int len; log_debug(LD_CIRC,"First skin; sending create cell."); + memset(&cc, 0, sizeof(cc)); if (circ->build_state->onehop_tunnel) control_event_bootstrap(BOOTSTRAP_STATUS_ONEHOP_CREATE, 0); else control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0); - node = node_get_by_id(circ->_base.n_conn->identity_digest); + node = node_get_by_id(circ->base_.n_chan->identity_digest); fast = should_use_create_fast_for_circuit(circ); if (!fast) { /* We are an OR and we know the right onion key: we should - * send an old slow create cell. + * send a create cell. */ - cell_type = CELL_CREATE; - if (onion_skin_create(circ->cpath->extend_info->onion_key, - &(circ->cpath->dh_handshake_state), - payload) < 0) { - log_warn(LD_CIRC,"onion_skin_create (first hop) failed."); - return - END_CIRC_REASON_INTERNAL; - } + circuit_pick_create_handshake(&cc.cell_type, &cc.handshake_type, + circ->cpath->extend_info); note_request("cell: create", 1); } else { /* We are not an OR, and we're building the first hop of a circuit to a * new OR: we can be speedy and use CREATE_FAST to save an RSA operation * and a DH operation. */ - cell_type = CELL_CREATE_FAST; - memset(payload, 0, sizeof(payload)); - crypto_rand((char*) circ->cpath->fast_handshake_state, - sizeof(circ->cpath->fast_handshake_state)); - memcpy(payload, circ->cpath->fast_handshake_state, - sizeof(circ->cpath->fast_handshake_state)); + cc.cell_type = CELL_CREATE_FAST; + cc.handshake_type = ONION_HANDSHAKE_TYPE_FAST; note_request("cell: create fast", 1); } - if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload) < 0) + len = onion_skin_create(cc.handshake_type, + circ->cpath->extend_info, + &circ->cpath->handshake_state, + cc.onionskin); + if (len < 0) { + log_warn(LD_CIRC,"onion_skin_create (first hop) failed."); + return - END_CIRC_REASON_INTERNAL; + } + cc.handshake_len = len; + + if (circuit_deliver_create_cell(TO_CIRCUIT(circ), &cc, 0) < 0) return - END_CIRC_REASON_RESOURCELIMIT; circ->cpath->state = CPATH_STATE_AWAITING_KEYS; @@ -2251,10 +821,13 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) fast ? "CREATE_FAST" : "CREATE", node ? node_describe(node) : "<unnamed>"); } else { + extend_cell_t ec; + int len; tor_assert(circ->cpath->state == CPATH_STATE_OPEN); - tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING); + tor_assert(circ->base_.state == CIRCUIT_STATE_BUILDING); log_debug(LD_CIRC,"starting to send subsequent skin."); hop = onion_next_hop_in_cpath(circ->cpath); + memset(&ec, 0, sizeof(ec)); if (!hop) { /* done building the circuit. whew. */ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); @@ -2262,7 +835,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) struct timeval end; long timediff; tor_gettimeofday(&end); - timediff = tv_mdiff(&circ->_base.timestamp_created, &end); + timediff = tv_mdiff(&circ->base_.timestamp_began, &end); /* * If the circuit build time is much greater than we would have cut @@ -2272,8 +845,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) 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 (%s)", timediff, - circ->_base.purpose, - circuit_purpose_to_string(circ->_base.purpose)); + circ->base_.purpose, + circuit_purpose_to_string(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)) { @@ -2281,7 +854,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) circuit_build_times_set_timeout(&circ_times); } - if (circ->_base.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { circuit_build_times_network_circ_success(&circ_times); } } @@ -2293,6 +866,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0); } + pathbias_count_build_success(circ); + circuit_rep_hist_note_result(circ); + circuit_has_opened(circ); /* do other actions as necessary */ + if (!can_complete_circuit && !circ->build_state->onehop_tunnel) { const or_options_t *options = get_options(); can_complete_circuit=1; @@ -2309,13 +886,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) } } - pathbias_count_success(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) + if (circ->base_.purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); + } return 0; } @@ -2324,29 +898,50 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) return - END_CIRC_REASON_INTERNAL; } - set_uint32(payload, tor_addr_to_ipv4n(&hop->extend_info->addr)); - set_uint16(payload+4, htons(hop->extend_info->port)); - - onionskin = payload+2+4; - memcpy(payload+2+4+ONIONSKIN_CHALLENGE_LEN, - hop->extend_info->identity_digest, DIGEST_LEN); - payload_len = 2+4+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN; - - if (onion_skin_create(hop->extend_info->onion_key, - &(hop->dh_handshake_state), onionskin) < 0) { + { + const node_t *prev_node; + prev_node = node_get_by_id(hop->prev->extend_info->identity_digest); + circuit_pick_extend_handshake(&ec.cell_type, + &ec.create_cell.cell_type, + &ec.create_cell.handshake_type, + prev_node, + hop->extend_info); + } + + tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr); + ec.orport_ipv4.port = hop->extend_info->port; + tor_addr_make_unspec(&ec.orport_ipv6.addr); + memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN); + + len = onion_skin_create(ec.create_cell.handshake_type, + hop->extend_info, + &hop->handshake_state, + ec.create_cell.onionskin); + if (len < 0) { log_warn(LD_CIRC,"onion_skin_create failed."); return - END_CIRC_REASON_INTERNAL; } + ec.create_cell.handshake_len = len; log_info(LD_CIRC,"Sending extend relay cell."); note_request("cell: extend", 1); - /* send it to hop->prev, because it will transfer - * it to a create cell and then send to hop */ - if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), - RELAY_COMMAND_EXTEND, - payload, payload_len, hop->prev) < 0) - return 0; /* circuit is closed */ + { + uint8_t command = 0; + uint16_t payload_len=0; + uint8_t payload[RELAY_PAYLOAD_SIZE]; + if (extend_cell_format(&command, &payload_len, payload, &ec)<0) { + log_warn(LD_CIRC,"Couldn't format extend cell"); + return -END_CIRC_REASON_INTERNAL; + } + /* send it to hop->prev, because it will transfer + * it to a create cell and then send to hop */ + if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), + command, + (char*)payload, payload_len, + hop->prev) < 0) + return 0; /* circuit is closed */ + } hop->state = CPATH_STATE_AWAITING_KEYS; } return 0; @@ -2369,7 +964,7 @@ circuit_note_clock_jumped(int seconds_elapsed) control_event_client_status(severity, "CIRCUIT_NOT_ESTABLISHED REASON=%s", "CLOCK_JUMPED"); circuit_mark_all_unused_circs(); - circuit_expire_all_dirty_circs(); + circuit_mark_all_dirty_circs_as_unusable(); } /** Take the 'extend' <b>cell</b>, pull out addr/port plus the onion @@ -2383,19 +978,15 @@ circuit_note_clock_jumped(int seconds_elapsed) int circuit_extend(cell_t *cell, circuit_t *circ) { - or_connection_t *n_conn; + channel_t *n_chan; relay_header_t rh; - char *onionskin; - char *id_digest=NULL; - uint32_t n_addr32; - uint16_t n_port; - tor_addr_t n_addr; + extend_cell_t ec; const char *msg = NULL; int should_launch = 0; - if (circ->n_conn) { + if (circ->n_chan) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "n_conn already set. Bug/attack. Closing."); + "n_chan already set. Bug/attack. Closing."); return -1; } if (circ->n_hop) { @@ -2412,27 +1003,21 @@ circuit_extend(cell_t *cell, circuit_t *circ) relay_header_unpack(&rh, cell->payload); - if (rh.length < 4+2+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN) { + if (extend_cell_parse(&ec, rh.command, + cell->payload+RELAY_HEADER_SIZE, + rh.length) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Wrong length %d on extend cell. Closing circuit.", - rh.length); + "Can't parse extend cell. Closing circuit."); return -1; } - n_addr32 = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE)); - n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4)); - onionskin = (char*) cell->payload+RELAY_HEADER_SIZE+4+2; - id_digest = (char*) cell->payload+RELAY_HEADER_SIZE+4+2+ - ONIONSKIN_CHALLENGE_LEN; - tor_addr_from_ipv4h(&n_addr, n_addr32); - - if (!n_port || !n_addr32) { + if (!ec.orport_ipv4.port || tor_addr_is_null(&ec.orport_ipv4.addr)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Client asked me to extend to zero destination port or addr."); return -1; } - if (tor_addr_is_internal(&n_addr, 0) && + if (tor_addr_is_internal(&ec.orport_ipv4.addr, 0) && !get_options()->ExtendAllowPrivateAddresses) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Client asked me to extend to a private address"); @@ -2445,7 +1030,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) * fingerprints -- a) because it opens the user up to a mitm attack, * and b) because it lets an attacker force the relay to hold open a * new TLS connection for each extend request. */ - if (tor_digest_is_zero(id_digest)) { + if (tor_digest_is_zero((const char*)ec.node_id)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Client asked me to extend without specifying an id_digest."); return -1; @@ -2454,55 +1039,64 @@ circuit_extend(cell_t *cell, circuit_t *circ) /* Next, check if we're being asked to connect to the hop that the * extend cell came from. There isn't any reason for that, and it can * assist circular-path attacks. */ - if (tor_memeq(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest, - DIGEST_LEN)) { + if (tor_memeq(ec.node_id, + TO_OR_CIRCUIT(circ)->p_chan->identity_digest, + DIGEST_LEN)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Client asked me to extend back to the previous hop."); return -1; } - n_conn = connection_or_get_for_extend(id_digest, - &n_addr, - &msg, - &should_launch); + n_chan = channel_get_for_extend((const char*)ec.node_id, + &ec.orport_ipv4.addr, + &msg, + &should_launch); - if (!n_conn) { - log_debug(LD_CIRC|LD_OR,"Next router (%s:%d): %s", - fmt_addr(&n_addr), (int)n_port, msg?msg:"????"); + if (!n_chan) { + log_debug(LD_CIRC|LD_OR,"Next router (%s): %s", + fmt_addrport(&ec.orport_ipv4.addr,ec.orport_ipv4.port), + msg?msg:"????"); - circ->n_hop = extend_info_alloc(NULL /*nickname*/, - id_digest, - NULL /*onion_key*/, - &n_addr, n_port); + circ->n_hop = extend_info_new(NULL /*nickname*/, + (const char*)ec.node_id, + NULL /*onion_key*/, + NULL /*curve25519_key*/, + &ec.orport_ipv4.addr, + ec.orport_ipv4.port); - circ->n_conn_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN); - memcpy(circ->n_conn_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN); - circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT); + circ->n_chan_create_cell = tor_memdup(&ec.create_cell, + sizeof(ec.create_cell)); + + circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT); if (should_launch) { /* we should try to open a connection */ - n_conn = connection_or_connect(&n_addr, n_port, id_digest); - if (!n_conn) { - log_info(LD_CIRC,"Launching n_conn failed. Closing circuit."); + n_chan = channel_connect_for_circuit(&ec.orport_ipv4.addr, + ec.orport_ipv4.port, + (const char*)ec.node_id); + if (!n_chan) { + log_info(LD_CIRC,"Launching n_chan failed. Closing circuit."); circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); return 0; } log_debug(LD_CIRC,"connecting in progress (or finished). Good."); } /* return success. The onion/circuit/etc will be taken care of - * automatically (may already have been) whenever n_conn reaches + * automatically (may already have been) whenever n_chan reaches * OR_CONN_STATE_OPEN. */ return 0; } tor_assert(!circ->n_hop); /* Connection is already established. */ - circ->n_conn = n_conn; - log_debug(LD_CIRC,"n_conn is %s:%u", - n_conn->_base.address,n_conn->_base.port); + circ->n_chan = n_chan; + log_debug(LD_CIRC, + "n_chan is %s", + channel_get_canonical_remote_descr(n_chan)); - if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0) + if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0) return -1; + return 0; } @@ -2556,12 +1150,12 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data, return 0; } -/** The minimum number of first hop completions before we start +/** The minimum number of circuit attempts before we start * thinking about warning about path bias and dropping guards */ static int pathbias_get_min_circs(const or_options_t *options) { -#define DFLT_PATH_BIAS_MIN_CIRC 20 +#define DFLT_PATH_BIAS_MIN_CIRC 150 if (options->PathBiasCircThreshold >= 5) return options->PathBiasCircThreshold; else @@ -2570,10 +1164,11 @@ pathbias_get_min_circs(const or_options_t *options) 5, INT32_MAX); } +/** The circuit success rate below which we issue a notice */ static double pathbias_get_notice_rate(const or_options_t *options) { -#define DFLT_PATH_BIAS_NOTICE_PCT 40 +#define DFLT_PATH_BIAS_NOTICE_PCT 70 if (options->PathBiasNoticeRate >= 0.0) return options->PathBiasNoticeRate; else @@ -2581,23 +1176,62 @@ pathbias_get_notice_rate(const or_options_t *options) DFLT_PATH_BIAS_NOTICE_PCT, 0, 100)/100.0; } +/* XXXX024 I'd like to have this be static again, but entrynodes.c needs it. */ +/** The circuit success rate below which we issue a warn */ static double -pathbias_get_disable_rate(const or_options_t *options) +pathbias_get_warn_rate(const or_options_t *options) +{ +#define DFLT_PATH_BIAS_WARN_PCT 50 + if (options->PathBiasWarnRate >= 0.0) + return options->PathBiasWarnRate; + else + return networkstatus_get_param(NULL, "pb_warnpct", + DFLT_PATH_BIAS_WARN_PCT, 0, 100)/100.0; +} + +/* XXXX024 I'd like to have this be static again, but entrynodes.c needs it. */ +/** + * The extreme rate is the rate at which we would drop the guard, + * if pb_dropguard is also set. Otherwise we just warn. + */ +double +pathbias_get_extreme_rate(const or_options_t *options) { -// XXX: This needs tuning based on use + experimentation before we set it -#define DFLT_PATH_BIAS_DISABLE_PCT 0 - if (options->PathBiasDisableRate >= 0.0) - return options->PathBiasDisableRate; +#define DFLT_PATH_BIAS_EXTREME_PCT 30 + if (options->PathBiasExtremeRate >= 0.0) + return options->PathBiasExtremeRate; else - return networkstatus_get_param(NULL, "pb_disablepct", - DFLT_PATH_BIAS_DISABLE_PCT, 0, 100)/100.0; + return networkstatus_get_param(NULL, "pb_extremepct", + DFLT_PATH_BIAS_EXTREME_PCT, 0, 100)/100.0; } +/* XXXX024 I'd like to have this be static again, but entrynodes.c needs it. */ +/** + * If 1, we actually disable use of guards that fall below + * the extreme_pct. + */ +int +pathbias_get_dropguards(const or_options_t *options) +{ +#define DFLT_PATH_BIAS_DROP_GUARDS 0 + if (options->PathBiasDropGuards >= 0) + return options->PathBiasDropGuards; + else + return networkstatus_get_param(NULL, "pb_dropguards", + DFLT_PATH_BIAS_DROP_GUARDS, 0, 1); +} + +/** + * This is the number of circuits at which we scale our + * counts by mult_factor/scale_factor. Note, this count is + * not exact, as we only perform the scaling in the event + * of no integer truncation. + */ static int pathbias_get_scale_threshold(const or_options_t *options) { -#define DFLT_PATH_BIAS_SCALE_THRESHOLD 200 - if (options->PathBiasScaleThreshold >= 2) +#define DFLT_PATH_BIAS_SCALE_THRESHOLD 300 + if (options->PathBiasScaleThreshold >= 10) return options->PathBiasScaleThreshold; else return networkstatus_get_param(NULL, "pb_scalecircs", @@ -2605,141 +1239,330 @@ pathbias_get_scale_threshold(const or_options_t *options) INT32_MAX); } +/** + * Compute the path bias scaling ratio from the consensus + * parameters pb_multfactor/pb_scalefactor. + * + * Returns a value in (0, 1.0] which we multiply our pathbias + * counts with to scale them down. + */ +static double +pathbias_get_scale_ratio(const or_options_t *options) +{ + /* + * The scale factor is the denominator for our scaling + * of circuit counts for our path bias window. + * + * Note that our use of doubles for the path bias state + * file means that powers of 2 work best here. + */ + int denominator = networkstatus_get_param(NULL, "pb_scalefactor", + 2, 2, INT32_MAX); + (void) options; + /** + * The mult factor is the numerator for our scaling + * of circuit counts for our path bias window. It + * allows us to scale by fractions. + */ + return networkstatus_get_param(NULL, "pb_multfactor", + 1, 1, denominator)/((double)denominator); +} + +/** The minimum number of circuit usage attempts before we start + * thinking about warning about path use bias and dropping guards */ static int -pathbias_get_scale_factor(const or_options_t *options) +pathbias_get_min_use(const or_options_t *options) +{ +#define DFLT_PATH_BIAS_MIN_USE 20 + if (options->PathBiasUseThreshold >= 3) + return options->PathBiasUseThreshold; + else + return networkstatus_get_param(NULL, "pb_minuse", + DFLT_PATH_BIAS_MIN_USE, + 3, INT32_MAX); +} + +/** The circuit use success rate below which we issue a notice */ +static double +pathbias_get_notice_use_rate(const or_options_t *options) { -#define DFLT_PATH_BIAS_SCALE_FACTOR 4 - if (options->PathBiasScaleFactor >= 1) - return options->PathBiasScaleFactor; +#define DFLT_PATH_BIAS_NOTICE_USE_PCT 80 + if (options->PathBiasNoticeUseRate >= 0.0) + return options->PathBiasNoticeUseRate; else - return networkstatus_get_param(NULL, "pb_scalefactor", - DFLT_PATH_BIAS_SCALE_THRESHOLD, 1, INT32_MAX); + return networkstatus_get_param(NULL, "pb_noticeusepct", + DFLT_PATH_BIAS_NOTICE_USE_PCT, + 0, 100)/100.0; } -static const char * +/** + * The extreme use rate is the rate at which we would drop the guard, + * if pb_dropguard is also set. Otherwise we just warn. + */ +double +pathbias_get_extreme_use_rate(const or_options_t *options) +{ +#define DFLT_PATH_BIAS_EXTREME_USE_PCT 60 + if (options->PathBiasExtremeUseRate >= 0.0) + return options->PathBiasExtremeUseRate; + else + return networkstatus_get_param(NULL, "pb_extremeusepct", + DFLT_PATH_BIAS_EXTREME_USE_PCT, + 0, 100)/100.0; +} + +/** + * This is the number of circuits at which we scale our + * use counts by mult_factor/scale_factor. Note, this count is + * not exact, as we only perform the scaling in the event + * of no integer truncation. + */ +static int +pathbias_get_scale_use_threshold(const or_options_t *options) +{ +#define DFLT_PATH_BIAS_SCALE_USE_THRESHOLD 100 + if (options->PathBiasScaleUseThreshold >= 10) + return options->PathBiasScaleUseThreshold; + else + return networkstatus_get_param(NULL, "pb_scaleuse", + DFLT_PATH_BIAS_SCALE_USE_THRESHOLD, + 10, INT32_MAX); +} + +/** + * Convert a Guard's path state to string. + */ +const char * pathbias_state_to_string(path_state_t state) { switch (state) { case PATH_STATE_NEW_CIRC: return "new"; - case PATH_STATE_DID_FIRST_HOP: - return "first hop"; - case PATH_STATE_SUCCEEDED: - return "succeeded"; + case PATH_STATE_BUILD_ATTEMPTED: + return "build attempted"; + case PATH_STATE_BUILD_SUCCEEDED: + return "build succeeded"; + case PATH_STATE_USE_ATTEMPTED: + return "use attempted"; + case PATH_STATE_USE_SUCCEEDED: + return "use succeeded"; + case PATH_STATE_USE_FAILED: + return "use failed"; + case PATH_STATE_ALREADY_COUNTED: + return "already counted"; } return "unknown"; } /** - * Check our circuit state to see if this is a successful first hop. - * If so, record it in the current guard's path bias first_hop count. + * This function decides if a circuit has progressed far enough to count + * as a circuit "attempt". As long as end-to-end tagging is possible, + * we assume the adversary will use it over hop-to-hop failure. Therefore, + * we only need to account bias for the last hop. This should make us + * much more resilient to ambient circuit failure, and also make that + * failure easier to measure (we only need to measure Exit failure rates). + */ +static int +pathbias_is_new_circ_attempt(origin_circuit_t *circ) +{ +#define N2N_TAGGING_IS_POSSIBLE +#ifdef N2N_TAGGING_IS_POSSIBLE + /* cpath is a circular list. We want circs with more than one hop, + * and the second hop must be waiting for keys still (it's just + * about to get them). */ + return circ->cpath && + circ->cpath->next != circ->cpath && + circ->cpath->next->state == CPATH_STATE_AWAITING_KEYS; +#else + /* If tagging attacks are no longer possible, we probably want to + * count bias from the first hop. However, one could argue that + * timing-based tagging is still more useful than per-hop failure. + * In which case, we'd never want to use this. + */ + return circ->cpath && + circ->cpath->state == CPATH_STATE_AWAITING_KEYS; +#endif +} + +/** + * Decide if the path bias code should count a circuit. * - * Also check for several potential error cases for bug #6475. + * @returns 1 if we should count it, 0 otherwise. */ static int -pathbias_count_first_hop(origin_circuit_t *circ) +pathbias_should_count(origin_circuit_t *circ) { -#define FIRST_HOP_NOTICE_INTERVAL (600) - static ratelim_t first_hop_notice_limit = - RATELIM_INIT(FIRST_HOP_NOTICE_INTERVAL); +#define PATHBIAS_COUNT_INTERVAL (600) + static ratelim_t count_limit = + RATELIM_INIT(PATHBIAS_COUNT_INTERVAL); char *rate_msg = NULL; + /* We can't do path bias accounting without entry guards. + * Testing and controller circuits also have no guards. + * + * We also don't count server-side rends, because their + * endpoint could be chosen maliciously. + * Similarly, we can't count client-side intro attempts, + * because clients can be manipulated into connecting to + * malicious intro points. */ + if (get_options()->UseEntryGuards == 0 || + circ->base_.purpose == CIRCUIT_PURPOSE_TESTING || + circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER || + circ->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND || + circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED || + (circ->base_.purpose >= CIRCUIT_PURPOSE_C_INTRODUCING && + circ->base_.purpose <= CIRCUIT_PURPOSE_C_INTRODUCE_ACKED)) { + + /* Check to see if the shouldcount result has changed due to a + * unexpected purpose change that would affect our results. + * + * The reason we check the path state too here is because for the + * cannibalized versions of these purposes, we count them as successful + * before their purpose change. + */ + if (circ->pathbias_shouldcount == PATHBIAS_SHOULDCOUNT_COUNTED + && circ->path_state != PATH_STATE_ALREADY_COUNTED) { + log_info(LD_BUG, + "Circuit %d is now being ignored despite being counted " + "in the past. Purpose is %s, path state is %s", + circ->global_identifier, + circuit_purpose_to_string(circ->base_.purpose), + pathbias_state_to_string(circ->path_state)); + } + circ->pathbias_shouldcount = PATHBIAS_SHOULDCOUNT_IGNORED; + return 0; + } + /* Completely ignore one hop circuits */ if (circ->build_state->onehop_tunnel || circ->build_state->desired_path_len == 1) { /* Check for inconsistency */ if (circ->build_state->desired_path_len != 1 || !circ->build_state->onehop_tunnel) { - if ((rate_msg = rate_limit_log(&first_hop_notice_limit, - approx_time()))) { + if ((rate_msg = rate_limit_log(&count_limit, approx_time()))) { log_info(LD_BUG, "One-hop circuit has length %d. Path state is %s. " "Circuit is a %s currently %s.%s", circ->build_state->desired_path_len, pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } tor_fragile_assert(); } + + /* Check to see if the shouldcount result has changed due to a + * unexpected change that would affect our results */ + if (circ->pathbias_shouldcount == PATHBIAS_SHOULDCOUNT_COUNTED) { + log_info(LD_BUG, + "One-hop circuit %d is now being ignored despite being counted " + "in the past. Purpose is %s, path state is %s", + circ->global_identifier, + circuit_purpose_to_string(circ->base_.purpose), + pathbias_state_to_string(circ->path_state)); + } + circ->pathbias_shouldcount = PATHBIAS_SHOULDCOUNT_IGNORED; return 0; } - if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS) { + /* Check to see if the shouldcount result has changed due to a + * unexpected purpose change that would affect our results */ + if (circ->pathbias_shouldcount == PATHBIAS_SHOULDCOUNT_IGNORED) { + log_info(LD_BUG, + "Circuit %d is now being counted despite being ignored " + "in the past. Purpose is %s, path state is %s", + circ->global_identifier, + circuit_purpose_to_string(circ->base_.purpose), + pathbias_state_to_string(circ->path_state)); + } + circ->pathbias_shouldcount = PATHBIAS_SHOULDCOUNT_COUNTED; + + return 1; +} + +/** + * Check our circuit state to see if this is a successful circuit attempt. + * If so, record it in the current guard's path bias circ_attempt count. + * + * Also check for several potential error cases for bug #6475. + */ +static int +pathbias_count_build_attempt(origin_circuit_t *circ) +{ +#define CIRC_ATTEMPT_NOTICE_INTERVAL (600) + static ratelim_t circ_attempt_notice_limit = + RATELIM_INIT(CIRC_ATTEMPT_NOTICE_INTERVAL); + char *rate_msg = NULL; + + if (!pathbias_should_count(circ)) { + return 0; + } + + if (pathbias_is_new_circ_attempt(circ)) { /* Help track down the real cause of bug #6475: */ - if (circ->has_opened && circ->path_state != PATH_STATE_DID_FIRST_HOP) { - if ((rate_msg = rate_limit_log(&first_hop_notice_limit, + if (circ->has_opened && circ->path_state != PATH_STATE_BUILD_ATTEMPTED) { + if ((rate_msg = rate_limit_log(&circ_attempt_notice_limit, approx_time()))) { log_info(LD_BUG, "Opened circuit is in strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } } - /* Don't count cannibalized circs for path bias */ + /* Don't re-count cannibalized circs.. */ if (!circ->has_opened) { - entry_guard_t *guard; + entry_guard_t *guard = NULL; + + if (circ->cpath && circ->cpath->extend_info) { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + } else if (circ->base_.n_chan) { + guard = + entry_guard_get_by_id_digest(circ->base_.n_chan->identity_digest); + } - guard = entry_guard_get_by_id_digest( - circ->_base.n_conn->identity_digest); if (guard) { if (circ->path_state == PATH_STATE_NEW_CIRC) { - circ->path_state = PATH_STATE_DID_FIRST_HOP; + circ->path_state = PATH_STATE_BUILD_ATTEMPTED; - if (entry_guard_inc_first_hop_count(guard) < 0) { + if (entry_guard_inc_circ_attempt_count(guard) < 0) { /* Bogus guard; we already warned. */ return -END_CIRC_REASON_TORPROTOCOL; } } else { - if ((rate_msg = rate_limit_log(&first_hop_notice_limit, + if ((rate_msg = rate_limit_log(&circ_attempt_notice_limit, approx_time()))) { log_info(LD_BUG, "Unopened circuit has strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } } } else { - if ((rate_msg = rate_limit_log(&first_hop_notice_limit, + if ((rate_msg = rate_limit_log(&circ_attempt_notice_limit, approx_time()))) { - log_info(LD_BUG, + log_info(LD_CIRC, "Unopened circuit has no known guard. " "Circuit is a %s currently %s.%s", - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } } } - } else { - /* Help track down the real cause of bug #6475: */ - if (circ->path_state == PATH_STATE_NEW_CIRC) { - if ((rate_msg = rate_limit_log(&first_hop_notice_limit, - approx_time()))) { - log_info(LD_BUG, - "A %s circuit is in cpath state %d (opened: %d). " - "Circuit is a %s currently %s.%s", - pathbias_state_to_string(circ->path_state), - circ->cpath->state, circ->has_opened, - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), - rate_msg); - tor_free(rate_msg); - } - } } return 0; @@ -2753,48 +1576,34 @@ pathbias_count_first_hop(origin_circuit_t *circ) * Also check for several potential error cases for bug #6475. */ static void -pathbias_count_success(origin_circuit_t *circ) +pathbias_count_build_success(origin_circuit_t *circ) { #define SUCCESS_NOTICE_INTERVAL (600) static ratelim_t success_notice_limit = RATELIM_INIT(SUCCESS_NOTICE_INTERVAL); char *rate_msg = NULL; + entry_guard_t *guard = NULL; - /* Ignore one hop circuits */ - if (circ->build_state->onehop_tunnel || - circ->build_state->desired_path_len == 1) { - /* Check for consistency */ - if (circ->build_state->desired_path_len != 1 || - !circ->build_state->onehop_tunnel) { - if ((rate_msg = rate_limit_log(&success_notice_limit, - approx_time()))) { - log_info(LD_BUG, - "One-hop circuit has length %d. Path state is %s. " - "Circuit is a %s currently %s.%s", - circ->build_state->desired_path_len, - pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), - rate_msg); - tor_free(rate_msg); - } - tor_fragile_assert(); - } + if (!pathbias_should_count(circ)) { return; } - /* Don't count cannibalized/reused circs for path bias */ + /* Don't count cannibalized/reused circs for path bias + * "build" success, since they get counted under "use" success. */ if (!circ->has_opened) { - entry_guard_t *guard = - entry_guard_get_by_id_digest(circ->_base.n_conn->identity_digest); + if (circ->cpath && circ->cpath->extend_info) { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + } if (guard) { - if (circ->path_state == PATH_STATE_DID_FIRST_HOP) { - circ->path_state = PATH_STATE_SUCCEEDED; - guard->circuit_successes++; + if (circ->path_state == PATH_STATE_BUILD_ATTEMPTED) { + circ->path_state = PATH_STATE_BUILD_SUCCEEDED; + guard->circ_successes++; + entry_guards_changed(); - log_info(LD_PROTOCOL, "Got success count %u/%u for guard %s=%s", - guard->circuit_successes, guard->first_hops, + log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)", + guard->circ_successes, guard->circ_attempts, guard->nickname, hex_str(guard->identity, DIGEST_LEN)); } else { if ((rate_msg = rate_limit_log(&success_notice_limit, @@ -2803,41 +1612,44 @@ pathbias_count_success(origin_circuit_t *circ) "Succeeded circuit is in strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } } - if (guard->first_hops < guard->circuit_successes) { - log_info(LD_BUG, "Unexpectedly high circuit_successes (%u/%u) " - "for guard %s=%s", - guard->circuit_successes, guard->first_hops, + if (guard->circ_attempts < guard->circ_successes) { + log_notice(LD_BUG, "Unexpectedly high successes counts (%f/%f) " + "for guard %s ($%s)", + guard->circ_successes, guard->circ_attempts, guard->nickname, hex_str(guard->identity, DIGEST_LEN)); } - } else { + /* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to + * CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT and have no guards here. + * No need to log that case. */ + } else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { if ((rate_msg = rate_limit_log(&success_notice_limit, approx_time()))) { - log_info(LD_BUG, + log_info(LD_CIRC, "Completed circuit has no known guard. " "Circuit is a %s currently %s.%s", - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } } } else { - if (circ->path_state != PATH_STATE_SUCCEEDED) { + if (circ->path_state < PATH_STATE_BUILD_SUCCEEDED) { if ((rate_msg = rate_limit_log(&success_notice_limit, approx_time()))) { log_info(LD_BUG, "Opened circuit is in strange path state %s. " "Circuit is a %s currently %s.%s", pathbias_state_to_string(circ->path_state), - circuit_purpose_to_string(circ->_base.purpose), - circuit_state_to_string(circ->_base.state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state), rate_msg); tor_free(rate_msg); } @@ -2845,61 +1657,1012 @@ pathbias_count_success(origin_circuit_t *circ) } } -/** Increment the number of times we successfully extended a circuit to - * 'guard', first checking if the failure rate is high enough that we should - * eliminate the guard. Return -1 if the guard looks no good; return 0 if the - * guard looks fine. */ +/** + * Record an attempt to use a circuit. Changes the circuit's + * path state and update its guard's usage counter. + * + * Used for path bias usage accounting. + */ +void +pathbias_count_use_attempt(origin_circuit_t *circ) +{ + entry_guard_t *guard; + + if (!pathbias_should_count(circ)) { + return; + } + + if (circ->path_state < PATH_STATE_BUILD_SUCCEEDED) { + log_notice(LD_BUG, + "Used circuit is in strange path state %s. " + "Circuit is a %s currently %s.", + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state)); + } else if (circ->path_state < PATH_STATE_USE_ATTEMPTED) { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + if (guard) { + pathbias_measure_use_rate(guard); + pathbias_scale_use_rates(guard); + guard->use_attempts++; + entry_guards_changed(); + + log_debug(LD_CIRC, + "Marked circuit %d (%f/%f) as used for guard %s ($%s).", + circ->global_identifier, + guard->use_successes, guard->use_attempts, + guard->nickname, hex_str(guard->identity, DIGEST_LEN)); + } + + circ->path_state = PATH_STATE_USE_ATTEMPTED; + } else { + /* Harmless but educational log message */ + log_info(LD_CIRC, + "Used circuit %d is already in path state %s. " + "Circuit is a %s currently %s.", + circ->global_identifier, + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state)); + } + + return; +} + +/** + * Check the circuit's path state is appropriate and mark it as + * successfully used. Used for path bias usage accounting. + * + * We don't actually increment the guard's counters until + * pathbias_check_close(), because the circuit can still transition + * back to PATH_STATE_USE_ATTEMPTED if a stream fails later (this + * is done so we can probe the circuit for liveness at close). + */ +void +pathbias_mark_use_success(origin_circuit_t *circ) +{ + if (!pathbias_should_count(circ)) { + return; + } + + if (circ->path_state < PATH_STATE_USE_ATTEMPTED) { + log_notice(LD_BUG, + "Used circuit %d is in strange path state %s. " + "Circuit is a %s currently %s.", + circ->global_identifier, + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state)); + + pathbias_count_use_attempt(circ); + } + + /* We don't do any accounting at the guard until actual circuit close */ + circ->path_state = PATH_STATE_USE_SUCCEEDED; + + return; +} + +/** + * If a stream ever detatches from a circuit in a retriable way, + * we need to mark this circuit as still needing either another + * successful stream, or in need of a probe. + * + * An adversary could let the first stream request succeed (ie the + * resolve), but then tag and timeout the remainder (via cell + * dropping), forcing them on new circuits. + * + * Rolling back the state will cause us to probe such circuits, which + * should lead to probe failures in the event of such tagging due to + * either unrecognized cells coming in while we wait for the probe, + * or the cipher state getting out of sync in the case of dropped cells. + */ +void +pathbias_mark_use_rollback(origin_circuit_t *circ) +{ + if (circ->path_state == PATH_STATE_USE_SUCCEEDED) { + log_info(LD_CIRC, + "Rolling back pathbias use state to 'attempted' for detached " + "circuit %d", circ->global_identifier); + circ->path_state = PATH_STATE_USE_ATTEMPTED; + } +} + +/** + * Actually count a circuit success towards a guard's usage counters + * if the path state is appropriate. + */ +static void +pathbias_count_use_success(origin_circuit_t *circ) +{ + entry_guard_t *guard; + + if (!pathbias_should_count(circ)) { + return; + } + + if (circ->path_state != PATH_STATE_USE_SUCCEEDED) { + log_notice(LD_BUG, + "Successfully used circuit %d is in strange path state %s. " + "Circuit is a %s currently %s.", + circ->global_identifier, + pathbias_state_to_string(circ->path_state), + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state)); + } else { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + if (guard) { + guard->use_successes++; + entry_guards_changed(); + + if (guard->use_attempts < guard->use_successes) { + log_notice(LD_BUG, "Unexpectedly high use successes counts (%f/%f) " + "for guard %s=%s", + guard->use_successes, guard->use_attempts, + guard->nickname, hex_str(guard->identity, DIGEST_LEN)); + } + + log_debug(LD_CIRC, + "Marked circuit %d (%f/%f) as used successfully for guard " + "%s ($%s).", + circ->global_identifier, guard->use_successes, + guard->use_attempts, guard->nickname, + hex_str(guard->identity, DIGEST_LEN)); + } + } + + return; +} + +/** + * Send a probe down a circuit that the client attempted to use, + * but for which the stream timed out/failed. The probe is a + * RELAY_BEGIN cell with a 0.a.b.c destination address, which + * the exit will reject and reply back, echoing that address. + * + * The reason for such probes is because it is possible to bias + * a user's paths simply by causing timeouts, and these timeouts + * are not possible to differentiate from unresponsive servers. + * + * The probe is sent at the end of the circuit lifetime for two + * reasons: to prevent cryptographic taggers from being able to + * drop cells to cause timeouts, and to prevent easy recognition + * of probes before any real client traffic happens. + * + * Returns -1 if we couldn't probe, 0 otherwise. + */ +static int +pathbias_send_usable_probe(circuit_t *circ) +{ + /* Based on connection_ap_handshake_send_begin() */ + char payload[CELL_PAYLOAD_SIZE]; + int payload_len; + origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); + crypt_path_t *cpath_layer = NULL; + char *probe_nonce = NULL; + + tor_assert(ocirc); + + cpath_layer = ocirc->cpath->prev; + + if (cpath_layer->state != CPATH_STATE_OPEN) { + /* This can happen for cannibalized circuits. Their + * last hop isn't yet open */ + log_info(LD_CIRC, + "Got pathbias probe request for unopened circuit %d. " + "Opened %d, len %d", ocirc->global_identifier, + ocirc->has_opened, ocirc->build_state->desired_path_len); + return -1; + } + + /* We already went down this road. */ + if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING && + ocirc->pathbias_probe_id) { + log_info(LD_CIRC, + "Got pathbias probe request for circuit %d with " + "outstanding probe", ocirc->global_identifier); + return -1; + } + + /* Can't probe if the channel isn't open */ + if (circ->n_chan == NULL || + (circ->n_chan->state != CHANNEL_STATE_OPEN + && circ->n_chan->state != CHANNEL_STATE_MAINT)) { + log_info(LD_CIRC, + "Skipping pathbias probe for circuit %d: Channel is not open.", + ocirc->global_identifier); + return -1; + } + + circuit_change_purpose(circ, CIRCUIT_PURPOSE_PATH_BIAS_TESTING); + + /* Update timestamp for when circuit_expire_building() should kill us */ + tor_gettimeofday(&circ->timestamp_began); + + /* Generate a random address for the nonce */ + crypto_rand((char*)ô->pathbias_probe_nonce, + sizeof(ocirc->pathbias_probe_nonce)); + ocirc->pathbias_probe_nonce &= 0x00ffffff; + probe_nonce = tor_dup_ip(ocirc->pathbias_probe_nonce); + + tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:25", probe_nonce); + payload_len = (int)strlen(payload)+1; + + // XXX: need this? Can we assume ipv4 will always be supported? + // If not, how do we tell? + //if (payload_len <= RELAY_PAYLOAD_SIZE - 4 && edge_conn->begincell_flags) { + // set_uint32(payload + payload_len, htonl(edge_conn->begincell_flags)); + // payload_len += 4; + //} + + /* Generate+Store stream id, make sure it's non-zero */ + ocirc->pathbias_probe_id = get_unique_stream_id_by_circ(ocirc); + + if (ocirc->pathbias_probe_id==0) { + log_warn(LD_CIRC, + "Ran out of stream IDs on circuit %u during " + "pathbias probe attempt.", ocirc->global_identifier); + tor_free(probe_nonce); + return -1; + } + + log_info(LD_CIRC, + "Sending pathbias testing cell to %s:25 on stream %d for circ %d.", + probe_nonce, ocirc->pathbias_probe_id, ocirc->global_identifier); + tor_free(probe_nonce); + + /* Send a test relay cell */ + if (relay_send_command_from_edge(ocirc->pathbias_probe_id, circ, + RELAY_COMMAND_BEGIN, payload, + payload_len, cpath_layer) < 0) { + log_notice(LD_CIRC, + "Failed to send pathbias probe cell on circuit %d.", + ocirc->global_identifier); + return -1; + } + + /* Mark it freshly dirty so it doesn't get expired in the meantime */ + circ->timestamp_dirty = time(NULL); + + return 0; +} + +/** + * Check the response to a pathbias probe, to ensure the + * cell is recognized and the nonce and other probe + * characteristics are as expected. + * + * If the response is valid, return 0. Otherwise return < 0. + */ +int +pathbias_check_probe_response(circuit_t *circ, const cell_t *cell) +{ + /* Based on connection_edge_process_relay_cell() */ + relay_header_t rh; + int reason; + uint32_t ipv4_host; + origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); + + tor_assert(cell); + tor_assert(ocirc); + tor_assert(circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING); + + relay_header_unpack(&rh, cell->payload); + + reason = rh.length > 0 ? + get_uint8(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC; + + if (rh.command == RELAY_COMMAND_END && + reason == END_STREAM_REASON_EXITPOLICY && + ocirc->pathbias_probe_id == rh.stream_id) { + + /* Check length+extract host: It is in network order after the reason code. + * See connection_edge_end(). */ + if (rh.length < 9) { /* reason+ipv4+dns_ttl */ + log_notice(LD_PROTOCOL, + "Short path bias probe response length field (%d).", rh.length); + return - END_CIRC_REASON_TORPROTOCOL; + } + + ipv4_host = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1)); + + /* Check nonce */ + if (ipv4_host == ocirc->pathbias_probe_nonce) { + pathbias_mark_use_success(ocirc); + circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); + log_info(LD_CIRC, + "Got valid path bias probe back for circ %d, stream %d.", + ocirc->global_identifier, ocirc->pathbias_probe_id); + return 0; + } else { + log_notice(LD_CIRC, + "Got strange probe value 0x%x vs 0x%x back for circ %d, " + "stream %d.", ipv4_host, ocirc->pathbias_probe_nonce, + ocirc->global_identifier, ocirc->pathbias_probe_id); + return -1; + } + } + log_info(LD_CIRC, + "Got another cell back back on pathbias probe circuit %d: " + "Command: %d, Reason: %d, Stream-id: %d", + ocirc->global_identifier, rh.command, reason, rh.stream_id); + return -1; +} + +/** + * Check if a circuit was used and/or closed successfully. + * + * If we attempted to use the circuit to carry a stream but failed + * for whatever reason, or if the circuit mysteriously died before + * we could attach any streams, record these two cases. + * + * If we *have* successfully used the circuit, or it appears to + * have been closed by us locally, count it as a success. + * + * Returns 0 if we're done making decisions with the circ, + * or -1 if we want to probe it first. + */ +int +pathbias_check_close(origin_circuit_t *ocirc, int reason) +{ + circuit_t *circ = ô->base_; + + if (!pathbias_should_count(ocirc)) { + return 0; + } + + switch (ocirc->path_state) { + /* If the circuit was closed after building, but before use, we need + * to ensure we were the ones who tried to close it (and not a remote + * actor). */ + case PATH_STATE_BUILD_SUCCEEDED: + if (reason & END_CIRC_REASON_FLAG_REMOTE) { + /* Remote circ close reasons on an unused circuit all could be bias */ + log_info(LD_CIRC, + "Circuit %d remote-closed without successful use for reason %d. " + "Circuit purpose %d currently %d,%s. Len %d.", + ocirc->global_identifier, + reason, circ->purpose, ocirc->has_opened, + circuit_state_to_string(circ->state), + ocirc->build_state->desired_path_len); + pathbias_count_collapse(ocirc); + } else if ((reason & ~END_CIRC_REASON_FLAG_REMOTE) + == END_CIRC_REASON_CHANNEL_CLOSED && + circ->n_chan && + circ->n_chan->reason_for_closing + != CHANNEL_CLOSE_REQUESTED) { + /* If we didn't close the channel ourselves, it could be bias */ + /* XXX: Only count bias if the network is live? + * What about clock jumps/suspends? */ + log_info(LD_CIRC, + "Circuit %d's channel closed without successful use for reason " + "%d, channel reason %d. Circuit purpose %d currently %d,%s. Len " + "%d.", ocirc->global_identifier, + reason, circ->n_chan->reason_for_closing, + circ->purpose, ocirc->has_opened, + circuit_state_to_string(circ->state), + ocirc->build_state->desired_path_len); + pathbias_count_collapse(ocirc); + } else { + pathbias_count_successful_close(ocirc); + } + break; + + /* If we tried to use a circuit but failed, we should probe it to ensure + * it has not been tampered with. */ + case PATH_STATE_USE_ATTEMPTED: + /* XXX: Only probe and/or count failure if the network is live? + * What about clock jumps/suspends? */ + if (pathbias_send_usable_probe(circ) == 0) + return -1; + else + pathbias_count_use_failed(ocirc); + + /* Any circuit where there were attempted streams but no successful + * streams could be bias */ + log_info(LD_CIRC, + "Circuit %d closed without successful use for reason %d. " + "Circuit purpose %d currently %d,%s. Len %d.", + ocirc->global_identifier, + reason, circ->purpose, ocirc->has_opened, + circuit_state_to_string(circ->state), + ocirc->build_state->desired_path_len); + break; + + case PATH_STATE_USE_SUCCEEDED: + pathbias_count_successful_close(ocirc); + pathbias_count_use_success(ocirc); + break; + + case PATH_STATE_USE_FAILED: + pathbias_count_use_failed(ocirc); + break; + + case PATH_STATE_NEW_CIRC: + case PATH_STATE_BUILD_ATTEMPTED: + case PATH_STATE_ALREADY_COUNTED: + default: + // Other states are uninteresting. No stats to count. + break; + } + + ocirc->path_state = PATH_STATE_ALREADY_COUNTED; + + return 0; +} + +/** + * Count a successfully closed circuit. + */ +static void +pathbias_count_successful_close(origin_circuit_t *circ) +{ + entry_guard_t *guard = NULL; + if (!pathbias_should_count(circ)) { + return; + } + + if (circ->cpath && circ->cpath->extend_info) { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + } + + if (guard) { + /* In the long run: circuit_success ~= successful_circuit_close + + * circ_failure + stream_failure */ + guard->successful_circuits_closed++; + entry_guards_changed(); + } else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + /* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to + * CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT and have no guards here. + * No need to log that case. */ + log_info(LD_CIRC, + "Successfully closed circuit has no known guard. " + "Circuit is a %s currently %s", + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state)); + } +} + +/** + * Count a circuit that fails after it is built, but before it can + * carry any traffic. + * + * This is needed because there are ways to destroy a + * circuit after it has successfully completed. Right now, this is + * used for purely informational/debugging purposes. + */ +static void +pathbias_count_collapse(origin_circuit_t *circ) +{ + entry_guard_t *guard = NULL; + + if (!pathbias_should_count(circ)) { + return; + } + + if (circ->cpath && circ->cpath->extend_info) { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + } + + if (guard) { + guard->collapsed_circuits++; + entry_guards_changed(); + } else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + /* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to + * CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT and have no guards here. + * No need to log that case. */ + log_info(LD_CIRC, + "Destroyed circuit has no known guard. " + "Circuit is a %s currently %s", + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state)); + } +} + +/** + * Count a known failed circuit (because we could not probe it). + * + * This counter is informational. + */ +static void +pathbias_count_use_failed(origin_circuit_t *circ) +{ + entry_guard_t *guard = NULL; + if (!pathbias_should_count(circ)) { + return; + } + + if (circ->cpath && circ->cpath->extend_info) { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + } + + if (guard) { + guard->unusable_circuits++; + entry_guards_changed(); + } else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + /* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to + * CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT and have no guards here. + * No need to log that case. */ + /* XXX note cut-and-paste code in this function compared to nearby + * functions. Would be nice to refactor. -RD */ + log_info(LD_CIRC, + "Stream-failing circuit has no known guard. " + "Circuit is a %s currently %s", + circuit_purpose_to_string(circ->base_.purpose), + circuit_state_to_string(circ->base_.state)); + } +} + +/** + * Count timeouts for path bias log messages. + * + * These counts are purely informational. + */ +void +pathbias_count_timeout(origin_circuit_t *circ) +{ + entry_guard_t *guard = NULL; + + if (!pathbias_should_count(circ)) { + return; + } + + /* For hidden service circs, they can actually be used + * successfully and then time out later (because + * the other side declines to use them). */ + if (circ->path_state == PATH_STATE_USE_SUCCEEDED) { + return; + } + + if (circ->cpath && circ->cpath->extend_info) { + guard = entry_guard_get_by_id_digest( + circ->cpath->extend_info->identity_digest); + } + + if (guard) { + guard->timeouts++; + entry_guards_changed(); + } +} + +/** + * Helper function to count all of the currently opened circuits + * for a guard that are in a given path state range. The state + * range is inclusive on both ends. + */ static int -entry_guard_inc_first_hop_count(entry_guard_t *guard) +pathbias_count_circs_in_states(entry_guard_t *guard, + path_state_t from, + path_state_t to) +{ + circuit_t *circ; + int open_circuits = 0; + + /* Count currently open circuits. Give them the benefit of the doubt. */ + for (circ = global_circuitlist; circ; circ = circ->next) { + origin_circuit_t *ocirc = NULL; + if (!CIRCUIT_IS_ORIGIN(circ) || /* didn't originate here */ + circ->marked_for_close) /* already counted */ + continue; + + ocirc = TO_ORIGIN_CIRCUIT(circ); + + if (!ocirc->cpath || !ocirc->cpath->extend_info) + continue; + + if (ocirc->path_state >= from && + ocirc->path_state <= to && + pathbias_should_count(ocirc) && + fast_memeq(guard->identity, + ocirc->cpath->extend_info->identity_digest, + DIGEST_LEN)) { + log_debug(LD_CIRC, "Found opened circuit %d in path_state %s", + ocirc->global_identifier, + pathbias_state_to_string(ocirc->path_state)); + open_circuits++; + } + } + + return open_circuits; +} + +/** + * Return the number of circuits counted as successfully closed for + * this guard. + * + * Also add in the currently open circuits to give them the benefit + * of the doubt. + */ +double +pathbias_get_close_success_count(entry_guard_t *guard) +{ + return guard->successful_circuits_closed + + pathbias_count_circs_in_states(guard, + PATH_STATE_BUILD_SUCCEEDED, + PATH_STATE_USE_SUCCEEDED); +} + +/** + * Return the number of circuits counted as successfully used + * this guard. + * + * Also add in the currently open circuits that we are attempting + * to use to give them the benefit of the doubt. + */ +double +pathbias_get_use_success_count(entry_guard_t *guard) +{ + return guard->use_successes + + pathbias_count_circs_in_states(guard, + PATH_STATE_USE_ATTEMPTED, + PATH_STATE_USE_SUCCEEDED); +} + +/** + * Check the path bias use rate against our consensus parameter limits. + * + * Emits a log message if the use success rates are too low. + * + * If pathbias_get_dropguards() is set, we also disable the use of + * very failure prone guards. + */ +static void +pathbias_measure_use_rate(entry_guard_t *guard) { const or_options_t *options = get_options(); - entry_guards_changed(); + if (guard->use_attempts > pathbias_get_min_use(options)) { + /* Note: We rely on the < comparison here to allow us to set a 0 + * rate and disable the feature entirely. If refactoring, don't + * change to <= */ + if (pathbias_get_use_success_count(guard)/guard->use_attempts + < pathbias_get_extreme_use_rate(options)) { + /* Dropping is currently disabled by default. */ + if (pathbias_get_dropguards(options)) { + if (!guard->path_bias_disabled) { + log_warn(LD_CIRC, + "Your Guard %s ($%s) is failing to carry an extremely large " + "amount of stream on its circuits. " + "To avoid potential route manipulation attacks, Tor has " + "disabled use of this guard. " + "Use counts are %ld/%ld. Success counts are %ld/%ld. " + "%ld circuits completed, %ld were unusable, %ld collapsed, " + "and %ld timed out. " + "For reference, your timeout cutoff is %ld seconds.", + guard->nickname, hex_str(guard->identity, DIGEST_LEN), + tor_lround(pathbias_get_use_success_count(guard)), + tor_lround(guard->use_attempts), + tor_lround(pathbias_get_close_success_count(guard)), + tor_lround(guard->circ_attempts), + tor_lround(guard->circ_successes), + tor_lround(guard->unusable_circuits), + tor_lround(guard->collapsed_circuits), + tor_lround(guard->timeouts), + tor_lround(circ_times.close_ms/1000)); + guard->path_bias_disabled = 1; + guard->bad_since = approx_time(); + entry_guards_changed(); + return; + } + } else if (!guard->path_bias_use_extreme) { + guard->path_bias_use_extreme = 1; + log_warn(LD_CIRC, + "Your Guard %s ($%s) is failing to carry an extremely large " + "amount of streams on its circuits. " + "This could indicate a route manipulation attack, network " + "overload, bad local network connectivity, or a bug. " + "Use counts are %ld/%ld. Success counts are %ld/%ld. " + "%ld circuits completed, %ld were unusable, %ld collapsed, " + "and %ld timed out. " + "For reference, your timeout cutoff is %ld seconds.", + guard->nickname, hex_str(guard->identity, DIGEST_LEN), + tor_lround(pathbias_get_use_success_count(guard)), + tor_lround(guard->use_attempts), + tor_lround(pathbias_get_close_success_count(guard)), + tor_lround(guard->circ_attempts), + tor_lround(guard->circ_successes), + tor_lround(guard->unusable_circuits), + tor_lround(guard->collapsed_circuits), + tor_lround(guard->timeouts), + tor_lround(circ_times.close_ms/1000)); + } + } else if (pathbias_get_use_success_count(guard)/guard->use_attempts + < pathbias_get_notice_use_rate(options)) { + if (!guard->path_bias_use_noticed) { + guard->path_bias_use_noticed = 1; + log_notice(LD_CIRC, + "Your Guard %s ($%s) is failing to carry more streams on its " + "circuits than usual. " + "Most likely this means the Tor network is overloaded " + "or your network connection is poor. " + "Use counts are %ld/%ld. Success counts are %ld/%ld. " + "%ld circuits completed, %ld were unusable, %ld collapsed, " + "and %ld timed out. " + "For reference, your timeout cutoff is %ld seconds.", + guard->nickname, hex_str(guard->identity, DIGEST_LEN), + tor_lround(pathbias_get_use_success_count(guard)), + tor_lround(guard->use_attempts), + tor_lround(pathbias_get_close_success_count(guard)), + tor_lround(guard->circ_attempts), + tor_lround(guard->circ_successes), + tor_lround(guard->unusable_circuits), + tor_lround(guard->collapsed_circuits), + tor_lround(guard->timeouts), + tor_lround(circ_times.close_ms/1000)); + } + } + } +} + +/** + * Check the path bias circuit close status rates against our consensus + * parameter limits. + * + * Emits a log message if the use success rates are too low. + * + * If pathbias_get_dropguards() is set, we also disable the use of + * very failure prone guards. + * + * XXX: This function shares similar log messages and checks to + * pathbias_measure_use_rate(). It may be possible to combine them + * eventually, especially if we can ever remove the need for 3 + * levels of closure warns (if the overall circuit failure rate + * goes down with ntor). One way to do so would be to multiply + * the build rate with the use rate to get an idea of the total + * fraction of the total network paths the user is able to use. + * See ticket #8159. + */ +static void +pathbias_measure_close_rate(entry_guard_t *guard) +{ + const or_options_t *options = get_options(); - if (guard->first_hops > (unsigned)pathbias_get_min_circs(options)) { + if (guard->circ_attempts > pathbias_get_min_circs(options)) { /* Note: We rely on the < comparison here to allow us to set a 0 * rate and disable the feature entirely. If refactoring, don't * change to <= */ - if (guard->circuit_successes/((double)guard->first_hops) - < pathbias_get_disable_rate(options)) { + if (pathbias_get_close_success_count(guard)/guard->circ_attempts + < pathbias_get_extreme_rate(options)) { + /* Dropping is currently disabled by default. */ + if (pathbias_get_dropguards(options)) { + if (!guard->path_bias_disabled) { + log_warn(LD_CIRC, + "Your Guard %s ($%s) is failing an extremely large " + "amount of circuits. " + "To avoid potential route manipulation attacks, Tor has " + "disabled use of this guard. " + "Success counts are %ld/%ld. Use counts are %ld/%ld. " + "%ld circuits completed, %ld were unusable, %ld collapsed, " + "and %ld timed out. " + "For reference, your timeout cutoff is %ld seconds.", + guard->nickname, hex_str(guard->identity, DIGEST_LEN), + tor_lround(pathbias_get_close_success_count(guard)), + tor_lround(guard->circ_attempts), + tor_lround(pathbias_get_use_success_count(guard)), + tor_lround(guard->use_attempts), + tor_lround(guard->circ_successes), + tor_lround(guard->unusable_circuits), + tor_lround(guard->collapsed_circuits), + tor_lround(guard->timeouts), + tor_lround(circ_times.close_ms/1000)); + guard->path_bias_disabled = 1; + guard->bad_since = approx_time(); + entry_guards_changed(); + return; + } + } else if (!guard->path_bias_extreme) { + guard->path_bias_extreme = 1; + log_warn(LD_CIRC, + "Your Guard %s ($%s) is failing an extremely large " + "amount of circuits. " + "This could indicate a route manipulation attack, " + "extreme network overload, or a bug. " + "Success counts are %ld/%ld. Use counts are %ld/%ld. " + "%ld circuits completed, %ld were unusable, %ld collapsed, " + "and %ld timed out. " + "For reference, your timeout cutoff is %ld seconds.", + guard->nickname, hex_str(guard->identity, DIGEST_LEN), + tor_lround(pathbias_get_close_success_count(guard)), + tor_lround(guard->circ_attempts), + tor_lround(pathbias_get_use_success_count(guard)), + tor_lround(guard->use_attempts), + tor_lround(guard->circ_successes), + tor_lround(guard->unusable_circuits), + tor_lround(guard->collapsed_circuits), + tor_lround(guard->timeouts), + tor_lround(circ_times.close_ms/1000)); + } + } else if (pathbias_get_close_success_count(guard)/guard->circ_attempts + < pathbias_get_warn_rate(options)) { + if (!guard->path_bias_warned) { + guard->path_bias_warned = 1; + log_warn(LD_CIRC, + "Your Guard %s ($%s) is failing a very large " + "amount of circuits. " + "Most likely this means the Tor network is " + "overloaded, but it could also mean an attack against " + "you or potentially the guard itself. " + "Success counts are %ld/%ld. Use counts are %ld/%ld. " + "%ld circuits completed, %ld were unusable, %ld collapsed, " + "and %ld timed out. " + "For reference, your timeout cutoff is %ld seconds.", + guard->nickname, hex_str(guard->identity, DIGEST_LEN), + tor_lround(pathbias_get_close_success_count(guard)), + tor_lround(guard->circ_attempts), + tor_lround(pathbias_get_use_success_count(guard)), + tor_lround(guard->use_attempts), + tor_lround(guard->circ_successes), + tor_lround(guard->unusable_circuits), + tor_lround(guard->collapsed_circuits), + tor_lround(guard->timeouts), + tor_lround(circ_times.close_ms/1000)); + } + } else if (pathbias_get_close_success_count(guard)/guard->circ_attempts + < pathbias_get_notice_rate(options)) { + if (!guard->path_bias_noticed) { + guard->path_bias_noticed = 1; + log_notice(LD_CIRC, + "Your Guard %s ($%s) is failing more circuits than " + "usual. " + "Most likely this means the Tor network is overloaded. " + "Success counts are %ld/%ld. Use counts are %ld/%ld. " + "%ld circuits completed, %ld were unusable, %ld collapsed, " + "and %ld timed out. " + "For reference, your timeout cutoff is %ld seconds.", + guard->nickname, hex_str(guard->identity, DIGEST_LEN), + tor_lround(pathbias_get_close_success_count(guard)), + tor_lround(guard->circ_attempts), + tor_lround(pathbias_get_use_success_count(guard)), + tor_lround(guard->use_attempts), + tor_lround(guard->circ_successes), + tor_lround(guard->unusable_circuits), + tor_lround(guard->collapsed_circuits), + tor_lround(guard->timeouts), + tor_lround(circ_times.close_ms/1000)); + } + } + } +} - log_info(LD_PROTOCOL, - "Extremely low circuit success rate %u/%u for guard %s=%s. " - "This might indicate an attack, or a bug.", - guard->circuit_successes, guard->first_hops, guard->nickname, - hex_str(guard->identity, DIGEST_LEN)); +/** + * This function scales the path bias use rates if we have + * more data than the scaling threshold. This allows us to + * be more sensitive to recent measurements. + * + * XXX: The attempt count transfer stuff here might be done + * better by keeping separate pending counters that get + * transfered at circuit close. See ticket #8160. + */ +static void +pathbias_scale_close_rates(entry_guard_t *guard) +{ + const or_options_t *options = get_options(); - guard->path_bias_disabled = 1; - guard->bad_since = approx_time(); - return -1; - } else if (guard->circuit_successes/((double)guard->first_hops) - < pathbias_get_notice_rate(options) - && !guard->path_bias_notice) { - guard->path_bias_notice = 1; - log_info(LD_PROTOCOL, - "Low circuit success rate %u/%u for guard %s=%s.", - guard->circuit_successes, guard->first_hops, guard->nickname, - hex_str(guard->identity, DIGEST_LEN)); + /* If we get a ton of circuits, just scale everything down */ + if (guard->circ_attempts > pathbias_get_scale_threshold(options)) { + double scale_ratio = pathbias_get_scale_ratio(options); + int opened_attempts = pathbias_count_circs_in_states(guard, + PATH_STATE_BUILD_ATTEMPTED, PATH_STATE_BUILD_ATTEMPTED); + int opened_built = pathbias_count_circs_in_states(guard, + PATH_STATE_BUILD_SUCCEEDED, + PATH_STATE_USE_FAILED); + /* Verify that the counts are sane before and after scaling */ + int counts_are_sane = (guard->circ_attempts >= guard->circ_successes); + + guard->circ_attempts -= (opened_attempts+opened_built); + guard->circ_successes -= opened_built; + + guard->circ_attempts *= scale_ratio; + guard->circ_successes *= scale_ratio; + guard->timeouts *= scale_ratio; + guard->successful_circuits_closed *= scale_ratio; + guard->collapsed_circuits *= scale_ratio; + guard->unusable_circuits *= scale_ratio; + + guard->circ_attempts += (opened_attempts+opened_built); + guard->circ_successes += opened_built; + + entry_guards_changed(); + + log_info(LD_CIRC, + "Scaled pathbias counts to (%f,%f)/%f (%d/%d open) for guard " + "%s ($%s)", + guard->circ_successes, guard->successful_circuits_closed, + guard->circ_attempts, opened_built, opened_attempts, + guard->nickname, hex_str(guard->identity, DIGEST_LEN)); + + /* Have the counts just become invalid by this scaling attempt? */ + if (counts_are_sane && guard->circ_attempts < guard->circ_successes) { + log_notice(LD_BUG, + "Scaling has mangled pathbias counts to %f/%f (%d/%d open) " + "for guard %s ($%s)", + guard->circ_successes, guard->circ_attempts, opened_built, + opened_attempts, guard->nickname, + hex_str(guard->identity, DIGEST_LEN)); } } +} + +/** + * This function scales the path bias circuit close rates if we have + * more data than the scaling threshold. This allows us to be more + * sensitive to recent measurements. + * + * XXX: The attempt count transfer stuff here might be done + * better by keeping separate pending counters that get + * transfered at circuit close. See ticket #8160. + */ +void +pathbias_scale_use_rates(entry_guard_t *guard) +{ + const or_options_t *options = get_options(); /* If we get a ton of circuits, just scale everything down */ - if (guard->first_hops > (unsigned)pathbias_get_scale_threshold(options)) { - const int scale_factor = pathbias_get_scale_factor(options); - guard->first_hops /= scale_factor; - guard->circuit_successes /= scale_factor; + if (guard->use_attempts > pathbias_get_scale_use_threshold(options)) { + double scale_ratio = pathbias_get_scale_ratio(options); + int opened_attempts = pathbias_count_circs_in_states(guard, + PATH_STATE_USE_ATTEMPTED, PATH_STATE_USE_SUCCEEDED); + /* Verify that the counts are sane before and after scaling */ + int counts_are_sane = (guard->use_attempts >= guard->use_successes); + + guard->use_attempts -= opened_attempts; + + guard->use_attempts *= scale_ratio; + guard->use_successes *= scale_ratio; + + guard->use_attempts += opened_attempts; + + log_info(LD_CIRC, + "Scaled pathbias use counts to %f/%f (%d open) for guard %s ($%s)", + guard->use_successes, guard->use_attempts, opened_attempts, + guard->nickname, hex_str(guard->identity, DIGEST_LEN)); + + /* Have the counts just become invalid by this scaling attempt? */ + if (counts_are_sane && guard->use_attempts < guard->use_successes) { + log_notice(LD_BUG, + "Scaling has mangled pathbias usage counts to %f/%f " + "(%d open) for guard %s ($%s)", + guard->circ_successes, guard->circ_attempts, + opened_attempts, guard->nickname, + hex_str(guard->identity, DIGEST_LEN)); + } + + entry_guards_changed(); } - guard->first_hops++; - log_info(LD_PROTOCOL, "Got success count %u/%u for guard %s=%s", - guard->circuit_successes, guard->first_hops, guard->nickname, +} + +/** Increment the number of times we successfully extended a circuit to + * <b>guard</b>, first checking if the failure rate is high enough that + * we should eliminate the guard. Return -1 if the guard looks no good; + * return 0 if the guard looks fine. + */ +static int +entry_guard_inc_circ_attempt_count(entry_guard_t *guard) +{ + entry_guards_changed(); + + pathbias_measure_close_rate(guard); + + if (guard->path_bias_disabled) + return -1; + + pathbias_scale_close_rates(guard); + guard->circ_attempts++; + + log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)", + guard->circ_successes, guard->circ_attempts, guard->nickname, hex_str(guard->identity, DIGEST_LEN)); return 0; } -/** A created or extended cell came back to us on the circuit, and it included - * <b>reply</b> as its body. (If <b>reply_type</b> is CELL_CREATED, the body - * contains (the second DH key, plus KH). If <b>reply_type</b> is - * CELL_CREATED_FAST, the body contains a secret y and a hash H(x|y).) +/** A "created" cell <b>reply</b> came back to us on circuit <b>circ</b>. + * (The body of <b>reply</b> varies depending on what sort of handshake + * this is.) * * Calculate the appropriate keys and digests, make sure KH is * correct, and initialize this hop of the cpath. @@ -2907,14 +2670,14 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) * Return - reason if we want to mark circ for close, else return 0. */ int -circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, - const uint8_t *reply) +circuit_finish_handshake(origin_circuit_t *circ, + const created_cell_t *reply) { char keys[CPATH_KEY_MATERIAL_LEN]; crypt_path_t *hop; int rv; - if ((rv = pathbias_count_first_hop(circ)) < 0) + if ((rv = pathbias_count_build_attempt(circ)) < 0) return rv; if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS) { @@ -2928,39 +2691,25 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, } tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS); - if (reply_type == CELL_CREATED && hop->dh_handshake_state) { - if (onion_skin_client_handshake(hop->dh_handshake_state, (char*)reply,keys, - DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) { + { + if (onion_skin_client_handshake(hop->handshake_state.tag, + &hop->handshake_state, + reply->reply, reply->handshake_len, + (uint8_t*)keys, sizeof(keys), + (uint8_t*)hop->rend_circ_nonce) < 0) { log_warn(LD_CIRC,"onion_skin_client_handshake failed."); return -END_CIRC_REASON_TORPROTOCOL; } - /* Remember hash of g^xy */ - memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN); - } else if (reply_type == CELL_CREATED_FAST && !hop->dh_handshake_state) { - if (fast_client_handshake(hop->fast_handshake_state, reply, - (uint8_t*)keys, - DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) { - log_warn(LD_CIRC,"fast_client_handshake failed."); - return -END_CIRC_REASON_TORPROTOCOL; - } - memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN); - } else { - log_warn(LD_PROTOCOL,"CREATED cell type did not match CREATE cell type."); - return -END_CIRC_REASON_TORPROTOCOL; } - 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)); + onion_handshake_state_release(&hop->handshake_state); if (circuit_init_cpath_crypto(hop, keys, 0)<0) { return -END_CIRC_REASON_TORPROTOCOL; } hop->state = CPATH_STATE_OPEN; - log_info(LD_CIRC,"Finished building %scircuit hop:", - (reply_type == CELL_CREATED_FAST) ? "fast " : ""); + log_info(LD_CIRC,"Finished building circuit hop:"); circuit_log_path(LOG_INFO,LD_CIRC,circ); control_event_circuit_status(circ, CIRC_EVENT_EXTENDED, 0); @@ -2969,12 +2718,12 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, /** We received a relay truncated cell on circ. * - * Since we don't ask for truncates currently, getting a truncated + * Since we don't send truncates currently, getting a truncated * means that a connection broke or an extend failed. For now, - * just give up: for circ to close, and return 0. + * just give up: force circ to close, and return 0. */ int -circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer) +circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason) { // crypt_path_t *victim; // connection_t *stream; @@ -2982,12 +2731,12 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer) tor_assert(circ); tor_assert(layer); - /* XXX Since we don't ask for truncates currently, getting a truncated + /* XXX Since we don't send truncates currently, getting a truncated * means that a connection broke or an extend failed. For now, * just give up. */ circuit_mark_for_close(TO_CIRCUIT(circ), - END_CIRC_REASON_FLAG_REMOTE|END_CIRC_REASON_OR_CONN_CLOSED); + END_CIRC_REASON_FLAG_REMOTE|reason); return 0; #if 0 @@ -3020,24 +2769,26 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer) * cell back. */ int -onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, - const char *keys) +onionskin_answer(or_circuit_t *circ, + const created_cell_t *created_cell, + const char *keys, + const uint8_t *rend_circ_nonce) { cell_t cell; crypt_path_t *tmp_cpath; + if (created_cell_format(&cell, created_cell) < 0) { + log_warn(LD_BUG,"couldn't format created cell (type=%d, len=%d)", + (int)created_cell->cell_type, (int)created_cell->handshake_len); + return -1; + } + cell.circ_id = circ->p_circ_id; + tmp_cpath = tor_malloc_zero(sizeof(crypt_path_t)); tmp_cpath->magic = CRYPT_PATH_MAGIC; - memset(&cell, 0, sizeof(cell_t)); - cell.command = cell_type; - cell.circ_id = circ->p_circ_id; - circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); - memcpy(cell.payload, 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)get_uint32(keys), (unsigned int)get_uint32(keys+20)); @@ -3053,20 +2804,17 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, tmp_cpath->magic = 0; tor_free(tmp_cpath); - if (cell_type == CELL_CREATED) - memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN); - else - memcpy(circ->handshake_digest, cell.payload+DIGEST_LEN, DIGEST_LEN); + memcpy(circ->rend_circ_nonce, rend_circ_nonce, DIGEST_LEN); - circ->is_first_hop = (cell_type == CELL_CREATED_FAST); + circ->is_first_hop = (created_cell->cell_type == CELL_CREATED_FAST); append_cell_to_circuit_queue(TO_CIRCUIT(circ), - circ->p_conn, &cell, CELL_DIRECTION_IN, 0); + circ->p_chan, &cell, CELL_DIRECTION_IN, 0); log_debug(LD_CIRC,"Finished sending '%s' cell.", circ->is_first_hop ? "created_fast" : "created"); - if (!is_local_addr(&circ->p_conn->_base.addr) && - !connection_or_nonopen_was_started_here(circ->p_conn)) { + if (!channel_is_local(circ->p_chan) && + !channel_is_outgoing(circ->p_chan)) { /* record that we could process create cells from a non-local conn * that we didn't initiate; presumably this means that create cells * can reach us too. */ @@ -3076,15 +2824,18 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, return 0; } -/** Choose a length for a circuit of purpose <b>purpose</b>. - * Default length is 3 + the number of endpoints that would give something - * away. If the routerlist <b>routers</b> doesn't have enough routers +/** Choose a length for a circuit of purpose <b>purpose</b>: three + the + * number of endpoints that would give something away about our destination. + * + * If the routerlist <b>nodes</b> doesn't have enough routers * to handle the desired path length, return as large a path length as * is feasible, except if it's less than 2, in which case return -1. + * XXX ^^ I think this behavior is a hold-over from back when we had only a + * few relays in the network, and certainly back before guards existed. + * We should very likely get rid of it. -RD */ static int -new_route_len(uint8_t purpose, extend_info_t *exit, - smartlist_t *nodes) +new_route_len(uint8_t purpose, extend_info_t *exit, smartlist_t *nodes) { int num_acceptable_routers; int routelen; @@ -3149,7 +2900,7 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime, enough = (smartlist_len(sl) == 0); for (i = 0; i < smartlist_len(sl); ++i) { port = smartlist_get(sl, i); - if (smartlist_string_num_isin(LongLivedServices, *port)) + if (smartlist_contains_int_as_string(LongLivedServices, *port)) *need_uptime = 1; tor_free(port); } @@ -3268,7 +3019,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) n_supported[i] = -1; continue; } - if (routerset_contains_node(options->_ExcludeExitNodesUnion, node)) { + if (routerset_contains_node(options->ExcludeExitNodesUnion_, node)) { n_supported[i] = -1; continue; /* user asked us not to use it, no matter what */ } @@ -3285,7 +3036,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) * we'll retry later in this function with need_update and * need_capacity set to 0. */ } - if (!(node->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) { + if (!(node->is_valid || options->AllowInvalid_ & ALLOW_INVALID_EXIT)) { /* if it's invalid and we don't want it */ n_supported[i] = -1; // log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.", @@ -3371,7 +3122,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) } log_notice(LD_CIRC, "All routers are down or won't exit%s -- " "choosing a doomed exit at random.", - options->_ExcludeExitNodesUnion ? " or are Excluded" : ""); + options->ExcludeExitNodesUnion_ ? " or are Excluded" : ""); } supporting = smartlist_new(); needed_ports = circuit_get_unhandled_ports(time(NULL)); @@ -3410,7 +3161,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) log_warn(LD_CIRC, "No specified %sexit routers seem to be running: " "can't choose an exit.", - options->_ExcludeExitNodesUnion ? "non-excluded " : ""); + options->ExcludeExitNodesUnion_ ? "non-excluded " : ""); } return NULL; } @@ -3438,14 +3189,14 @@ choose_good_exit_server(uint8_t purpose, switch (purpose) { case CIRCUIT_PURPOSE_C_GENERAL: - if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE) + 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, options->ExcludeNodes, flags); else return choose_good_exit_server_general(need_uptime,need_capacity); case CIRCUIT_PURPOSE_C_ESTABLISH_REND: - if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS) + if (options->AllowInvalid_ & ALLOW_INVALID_RENDEZVOUS) flags |= CRN_ALLOW_INVALID; return router_choose_random_node(NULL, options->ExcludeNodes, flags); } @@ -3462,7 +3213,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) const or_options_t *options = get_options(); routerset_t *rs = options->ExcludeNodes; const char *description; - uint8_t purpose = circ->_base.purpose; + uint8_t purpose = circ->base_.purpose; if (circ->build_state->onehop_tunnel) return; @@ -3482,7 +3233,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) if (circ->build_state->is_internal) return; description = "requested exit node"; - rs = options->_ExcludeExitNodesUnion; + rs = options->ExcludeExitNodesUnion_; break; case CIRCUIT_PURPOSE_C_INTRODUCING: case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: @@ -3499,7 +3250,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) description = "chosen rendezvous point"; break; case CIRCUIT_PURPOSE_CONTROLLER: - rs = options->_ExcludeExitNodesUnion; + rs = options->ExcludeExitNodesUnion_; description = "controller-selected circuit target"; break; } @@ -3541,7 +3292,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) log_debug(LD_CIRC, "Launching a one-hop circuit for dir tunnel."); state->desired_path_len = 1; } else { - int r = new_route_len(circ->_base.purpose, exit, nodelist_get_list()); + int r = new_route_len(circ->base_.purpose, exit, nodelist_get_list()); if (r < 1) /* must be at least 1 */ return -1; state->desired_path_len = r; @@ -3554,7 +3305,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) exit = extend_info_dup(exit); } else { /* we have to decide one */ const node_t *node = - choose_good_exit_server(circ->_base.purpose, state->need_uptime, + choose_good_exit_server(circ->base_.purpose, state->need_uptime, state->need_capacity, state->is_internal); if (!node) { log_warn(LD_CIRC,"failed to choose an exit server"); @@ -3597,6 +3348,9 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit) { int err_reason = 0; warn_if_last_router_excluded(circ, exit); + + tor_gettimeofday(&circ->base_.timestamp_began); + circuit_append_new_exit(circ, exit); circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING); if ((err_reason = circuit_send_next_onion_skin(circ))<0) { @@ -3605,6 +3359,9 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit) circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason); return -1; } + + // XXX: Should cannibalized circuits be dirty or not? Not easy to say.. + return 0; } @@ -3675,8 +3432,8 @@ choose_good_middle_server(uint8_t purpose, smartlist_t *excluded; const or_options_t *options = get_options(); router_crn_flags_t flags = CRN_NEED_DESC; - tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose && - purpose <= _CIRCUIT_PURPOSE_MAX); + tor_assert(CIRCUIT_PURPOSE_MIN_ <= purpose && + purpose <= CIRCUIT_PURPOSE_MAX_); log_debug(LD_CIRC, "Contemplating intermediate hop: random choice."); excluded = smartlist_new(); @@ -3693,7 +3450,7 @@ choose_good_middle_server(uint8_t purpose, flags |= CRN_NEED_UPTIME; if (state->need_capacity) flags |= CRN_NEED_CAPACITY; - if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE) + if (options->AllowInvalid_ & ALLOW_INVALID_MIDDLE) flags |= CRN_ALLOW_INVALID; choice = router_choose_random_node(excluded, options->ExcludeNodes, flags); smartlist_free(excluded); @@ -3708,7 +3465,8 @@ choose_good_middle_server(uint8_t purpose, * If <b>state</b> is NULL, we're choosing a router to serve as an entry * guard, not for any particular circuit. */ -static const node_t * +/* XXXX024 I'd like to have this be static again, but entrynodes.c needs it. */ +const node_t * choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) { const node_t *choice; @@ -3740,8 +3498,9 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) }); } /* and exclude current entry guards and their families, if applicable */ - if (options->UseEntryGuards && entry_guards) { - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, + /*XXXX025 use the using_as_guard flag to accomplish this.*/ + if (options->UseEntryGuards) { + SMARTLIST_FOREACH(get_entry_guards(), const entry_guard_t *, entry, { if ((node = node_get_by_id(entry->identity))) { nodelist_add_node_and_family(excluded, node); @@ -3755,7 +3514,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) if (state->need_capacity) flags |= CRN_NEED_CAPACITY; } - if (options->_AllowInvalid & ALLOW_INVALID_ENTRY) + if (options->AllowInvalid_ & ALLOW_INVALID_ENTRY) flags |= CRN_ALLOW_INVALID; choice = router_choose_random_node(excluded, options->ExcludeNodes, flags); @@ -3779,11 +3538,14 @@ onion_next_hop_in_cpath(crypt_path_t *cpath) /** Choose a suitable next hop in the cpath <b>head_ptr</b>, * based on <b>state</b>. Append the hop info to head_ptr. + * + * Return 1 if the path is complete, 0 if we successfully added a hop, + * and -1 on error. */ static int onion_extend_cpath(origin_circuit_t *circ) { - uint8_t purpose = circ->_base.purpose; + uint8_t purpose = circ->base_.purpose; cpath_build_state_t *state = circ->build_state; int cur_len = circuit_get_cpath_len(circ); extend_info_t *info = NULL; @@ -3802,12 +3564,10 @@ onion_extend_cpath(origin_circuit_t *circ) } else if (cur_len == 0) { /* picking first node */ const node_t *r = choose_good_entry_server(purpose, state); if (r) { - /* If we're extending to a bridge, use the preferred address - rather than the primary, for potentially extending to an IPv6 - bridge. */ - int use_pref_addr = (r->ri != NULL && - r->ri->purpose == ROUTER_PURPOSE_BRIDGE); - info = extend_info_from_node(r, use_pref_addr); + /* If we're a client, use the preferred address rather than the + primary address, for potentially connecting to an IPv6 OR + port. */ + info = extend_info_from_node(r, server_mode(get_options()) == 0); tor_assert(info); } } else { @@ -3858,9 +3618,10 @@ onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice) /** Allocate a new extend_info object based on the various arguments. */ extend_info_t * -extend_info_alloc(const char *nickname, const char *digest, - crypto_pk_t *onion_key, - const tor_addr_t *addr, uint16_t port) +extend_info_new(const char *nickname, const char *digest, + crypto_pk_t *onion_key, + const curve25519_public_key_t *curve25519_key, + const tor_addr_t *addr, uint16_t port) { extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t)); memcpy(info->identity_digest, digest, DIGEST_LEN); @@ -3868,52 +3629,59 @@ extend_info_alloc(const char *nickname, const char *digest, strlcpy(info->nickname, nickname, sizeof(info->nickname)); if (onion_key) info->onion_key = crypto_pk_dup_key(onion_key); +#ifdef CURVE25519_ENABLED + if (curve25519_key) + memcpy(&info->curve25519_onion_key, curve25519_key, + sizeof(curve25519_public_key_t)); +#else + (void)curve25519_key; +#endif tor_addr_copy(&info->addr, addr); info->port = port; return info; } -/** Allocate and return a new extend_info_t that can be used to build - * a circuit to or through the router <b>r</b>. Use the primary - * address of the router unless <b>for_direct_connect</b> is true, in - * which case the preferred address is used instead. */ +/** Allocate and return a new extend_info that can be used to build a + * circuit to or through the node <b>node</b>. Use the primary address + * of the node (i.e. its IPv4 address) unless + * <b>for_direct_connect</b> is true, in which case the preferred + * address is used instead. May return NULL if there is not enough + * info about <b>node</b> to extend to it--for example, if there is no + * routerinfo_t or microdesc_t. + **/ extend_info_t * -extend_info_from_router(const routerinfo_t *r, int for_direct_connect) +extend_info_from_node(const node_t *node, int for_direct_connect) { tor_addr_port_t ap; - tor_assert(r); + + if (node->ri == NULL && (node->rs == NULL || node->md == NULL)) + return NULL; if (for_direct_connect) - router_get_pref_orport(r, &ap); + node_get_pref_orport(node, &ap); else - router_get_prim_orport(r, &ap); - return extend_info_alloc(r->nickname, r->cache_info.identity_digest, - r->onion_pkey, &ap.addr, ap.port); -} + node_get_prim_orport(node, &ap); -/** Allocate and return a new extend_info that can be used to build a - * circuit to or through the node <b>node</b>. Use the primary address - * of the node unless <b>for_direct_connect</b> is true, in which case - * the preferred address is used instead. May return NULL if there is - * not enough info about <b>node</b> to extend to it--for example, if - * there is no routerinfo_t or microdesc_t. - **/ -extend_info_t * -extend_info_from_node(const node_t *node, int for_direct_connect) -{ - if (node->ri) { - return extend_info_from_router(node->ri, for_direct_connect); - } else if (node->rs && node->md) { - tor_addr_t addr; - tor_addr_from_ipv4h(&addr, node->rs->addr); - return extend_info_alloc(node->rs->nickname, + log_debug(LD_CIRC, "using %s for %s", + fmt_addrport(&ap.addr, ap.port), + node->ri ? node->ri->nickname : node->rs->nickname); + + if (node->ri) + return extend_info_new(node->ri->nickname, + node->identity, + node->ri->onion_pkey, + node->ri->onion_curve25519_pkey, + &ap.addr, + ap.port); + else if (node->rs && node->md) + return extend_info_new(node->rs->nickname, node->identity, node->md->onion_pkey, - &addr, - node->rs->or_port); - } else { + node->md->onion_curve25519_pkey, + &ap.addr, + ap.port); + else return NULL; - } } /** Release storage held by an extend_info_t struct. */ @@ -3966,2067 +3734,3 @@ build_state_get_exit_nickname(cpath_build_state_t *state) return state->chosen_exit->nickname; } -/** Check whether the entry guard <b>e</b> is usable, given the directory - * authorities' opinion about the router (stored in <b>ri</b>) and the user's - * configuration (in <b>options</b>). Set <b>e</b>->bad_since - * accordingly. Return true iff the entry guard's status changes. - * - * If it's not usable, set *<b>reason</b> to a static string explaining why. - */ -static int -entry_guard_set_status(entry_guard_t *e, const node_t *node, - time_t now, const or_options_t *options, - const char **reason) -{ - char buf[HEX_DIGEST_LEN+1]; - int changed = 0; - - *reason = NULL; - - /* Do we want to mark this guard as bad? */ - if (!node) - *reason = "unlisted"; - else if (!node->is_running) - *reason = "down"; - else if (options->UseBridges && (!node->ri || - node->ri->purpose != ROUTER_PURPOSE_BRIDGE)) - *reason = "not a bridge"; - else if (options->UseBridges && !node_is_a_configured_bridge(node)) - *reason = "not a configured bridge"; - else if (!options->UseBridges && !node->is_possible_guard && - !routerset_contains_node(options->EntryNodes,node)) - *reason = "not recommended as a guard"; - else if (routerset_contains_node(options->ExcludeNodes, node)) - *reason = "excluded"; - else if (e->path_bias_disabled) - *reason = "path-biased"; - - if (*reason && ! e->bad_since) { - /* Router is newly bad. */ - base16_encode(buf, sizeof(buf), e->identity, DIGEST_LEN); - log_info(LD_CIRC, "Entry guard %s (%s) is %s: marking as unusable.", - e->nickname, buf, *reason); - - e->bad_since = now; - control_event_guard(e->nickname, e->identity, "BAD"); - changed = 1; - } else if (!*reason && e->bad_since) { - /* There's nothing wrong with the router any more. */ - base16_encode(buf, sizeof(buf), e->identity, DIGEST_LEN); - log_info(LD_CIRC, "Entry guard %s (%s) is no longer unusable: " - "marking as ok.", e->nickname, buf); - - e->bad_since = 0; - control_event_guard(e->nickname, e->identity, "GOOD"); - changed = 1; - } - return changed; -} - -/** Return true iff enough time has passed since we last tried to connect - * to the unreachable guard <b>e</b> that we're willing to try again. */ -static int -entry_is_time_to_retry(entry_guard_t *e, time_t now) -{ - long diff; - if (e->last_attempted < e->unreachable_since) - return 1; - diff = now - e->unreachable_since; - if (diff < 6*60*60) - return now > (e->last_attempted + 60*60); - else if (diff < 3*24*60*60) - return now > (e->last_attempted + 4*60*60); - else if (diff < 7*24*60*60) - return now > (e->last_attempted + 18*60*60); - else - return now > (e->last_attempted + 36*60*60); -} - -/** Return the node corresponding to <b>e</b>, if <b>e</b> is - * working well enough that we are willing to use it as an entry - * right now. (Else return NULL.) In particular, it must be - * - Listed as either up or never yet contacted; - * - 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> - * (unless it's a configured EntryNode); - * - Allowed by our current ReachableORAddresses config option; and - * - 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 const node_t * -entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, - int assume_reachable, const char **msg) -{ - const node_t *node; - const or_options_t *options = get_options(); - tor_assert(msg); - - if (e->path_bias_disabled) { - *msg = "path-biased"; - return NULL; - } - 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))) { - *msg = "unreachable"; - return NULL; - } - node = node_get_by_id(e->identity); - if (!node || !node_has_descriptor(node)) { - *msg = "no descriptor"; - return NULL; - } - if (get_options()->UseBridges) { - if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) { - *msg = "not a bridge"; - return NULL; - } - if (!node_is_a_configured_bridge(node)) { - *msg = "not a configured bridge"; - return NULL; - } - } else { /* !get_options()->UseBridges */ - if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) { - *msg = "not general-purpose"; - return NULL; - } - } - if (routerset_contains_node(options->EntryNodes, node)) { - /* they asked for it, they get it */ - need_uptime = need_capacity = 0; - } - if (node_is_unreliable(node, need_uptime, need_capacity, 0)) { - *msg = "not fast/stable"; - return NULL; - } - if (!fascist_firewall_allows_node(node)) { - *msg = "unreachable by config"; - return NULL; - } - return node; -} - -/** Return the number of entry guards that we think are usable. */ -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, &msg)) - ++n; - }); - return n; -} - -/** If <b>digest</b> matches the identity of any node in the - * entry_guards list, return that node. Else return NULL. */ -static entry_guard_t * -entry_guard_get_by_id_digest(const char *digest) -{ - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, - if (tor_memeq(digest, entry->identity, DIGEST_LEN)) - return entry; - ); - return NULL; -} - -/** Dump a description of our list of entry guards to the log at level - * <b>severity</b>. */ -static void -log_entry_guards(int severity) -{ - smartlist_t *elements = smartlist_new(); - char *s; - - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) - { - const char *msg = NULL; - if (entry_is_live(e, 0, 1, 0, &msg)) - smartlist_add_asprintf(elements, "%s [%s] (up %s)", - e->nickname, - hex_str(e->identity, DIGEST_LEN), - e->made_contact ? "made-contact" : "never-contacted"); - else - smartlist_add_asprintf(elements, "%s [%s] (%s, %s)", - e->nickname, - hex_str(e->identity, DIGEST_LEN), - msg, - e->made_contact ? "made-contact" : "never-contacted"); - } - SMARTLIST_FOREACH_END(e); - - s = smartlist_join_strings(elements, ",", 0, NULL); - SMARTLIST_FOREACH(elements, char*, cp, tor_free(cp)); - smartlist_free(elements); - log_fn(severity,LD_CIRC,"%s",s); - tor_free(s); -} - -/** Called when one or more guards that we would previously have used for some - * purpose are no longer in use because a higher-priority guard has become - * usable again. */ -static void -control_event_guard_deferred(void) -{ - /* XXXX We don't actually have a good way to figure out _how many_ entries - * are live for some purpose. We need an entry_is_even_slightly_live() - * function for this to work right. NumEntryGuards isn't reliable: if we - * need guards with weird properties, we can have more than that number - * live. - **/ -#if 0 - int n = 0; - const char *msg; - const 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, &msg)) { - if (n++ == options->NumEntryGuards) { - control_event_guard(entry->nickname, entry->identity, "DEFERRED"); - return; - } - } - }); -#endif -} - -/** Add a new (preferably stable and fast) router to our - * entry_guards list. Return a pointer to the router if we succeed, - * or NULL if we can't find any more suitable entries. - * - * If <b>chosen</b> is defined, use that one, and if it's not - * already in our entry_guards list, put it at the *beginning*. - * Else, put the one we pick at the end of the list. */ -static const node_t * -add_an_entry_guard(const node_t *chosen, int reset_status, int prepend) -{ - const node_t *node; - entry_guard_t *entry; - - if (chosen) { - node = chosen; - entry = entry_guard_get_by_id_digest(node->identity); - if (entry) { - if (reset_status) { - entry->bad_since = 0; - entry->can_retry = 1; - } - return NULL; - } - } else { - node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL); - if (!node) - return NULL; - } - entry = tor_malloc_zero(sizeof(entry_guard_t)); - log_info(LD_CIRC, "Chose %s as new entry guard.", - node_describe(node)); - strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname)); - memcpy(entry->identity, node->identity, DIGEST_LEN); - /* Choose expiry time smudged over the past month. The goal here - * is to a) spread out when Tor clients rotate their guards, so they - * don't all select them on the same day, and b) avoid leaving a - * precise timestamp in the state file about when we first picked - * this guard. For details, see the Jan 2010 or-dev thread. */ - entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); - entry->chosen_by_version = tor_strdup(VERSION); - if (prepend) - smartlist_insert(entry_guards, 0, entry); - else - smartlist_add(entry_guards, entry); - control_event_guard(entry->nickname, entry->identity, "NEW"); - control_event_guard_deferred(); - log_entry_guards(LOG_INFO); - return node; -} - -/** If the use of entry guards is configured, choose more entry guards - * until we have enough in the list. */ -static void -pick_entry_guards(const or_options_t *options) -{ - int changed = 0; - - tor_assert(entry_guards); - - while (num_live_entry_guards() < options->NumEntryGuards) { - if (!add_an_entry_guard(NULL, 0, 0)) - break; - changed = 1; - } - if (changed) - entry_guards_changed(); -} - -/** How long (in seconds) do we allow an entry guard to be nonfunctional, - * unlisted, excluded, or otherwise nonusable before we give up on it? */ -#define ENTRY_GUARD_REMOVE_AFTER (30*24*60*60) - -/** Release all storage held by <b>e</b>. */ -static void -entry_guard_free(entry_guard_t *e) -{ - if (!e) - return; - tor_free(e->chosen_by_version); - tor_free(e); -} - -/** Remove any entry guard which was selected by an unknown version of Tor, - * or which was selected by a version of Tor that's known to select - * entry guards badly, or which was selected more 2 months ago. */ -/* XXXX The "obsolete guards" and "chosen long ago guards" things should - * probably be different functions. */ -static int -remove_obsolete_entry_guards(time_t now) -{ - int changed = 0, i; - - for (i = 0; i < smartlist_len(entry_guards); ++i) { - entry_guard_t *entry = smartlist_get(entry_guards, i); - const char *ver = entry->chosen_by_version; - const char *msg = NULL; - tor_version_t v; - int version_is_bad = 0, date_is_bad = 0; - if (!ver) { - msg = "does not say what version of Tor it was selected by"; - version_is_bad = 1; - } else if (tor_version_parse(ver, &v)) { - msg = "does not seem to be from any recognized version of Tor"; - version_is_bad = 1; - } else { - char *tor_ver = NULL; - tor_asprintf(&tor_ver, "Tor %s", ver); - if ((tor_version_as_new_as(tor_ver, "0.1.0.10-alpha") && - !tor_version_as_new_as(tor_ver, "0.1.2.16-dev")) || - (tor_version_as_new_as(tor_ver, "0.2.0.0-alpha") && - !tor_version_as_new_as(tor_ver, "0.2.0.6-alpha")) || - /* above are bug 440; below are bug 1217 */ - (tor_version_as_new_as(tor_ver, "0.2.1.3-alpha") && - !tor_version_as_new_as(tor_ver, "0.2.1.23")) || - (tor_version_as_new_as(tor_ver, "0.2.2.0-alpha") && - !tor_version_as_new_as(tor_ver, "0.2.2.7-alpha"))) { - msg = "was selected without regard for guard bandwidth"; - version_is_bad = 1; - } - tor_free(tor_ver); - } - if (!version_is_bad && entry->chosen_on_date + 3600*24*60 < now) { - /* It's been 2 months since the date listed in our state file. */ - msg = "was selected several months ago"; - date_is_bad = 1; - } - - if (version_is_bad || date_is_bad) { /* we need to drop it */ - char dbuf[HEX_DIGEST_LEN+1]; - tor_assert(msg); - base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN); - log_fn(version_is_bad ? LOG_NOTICE : LOG_INFO, LD_CIRC, - "Entry guard '%s' (%s) %s. (Version=%s.) Replacing it.", - entry->nickname, dbuf, msg, ver?escaped(ver):"none"); - control_event_guard(entry->nickname, entry->identity, "DROPPED"); - entry_guard_free(entry); - smartlist_del_keeporder(entry_guards, i--); - log_entry_guards(LOG_INFO); - changed = 1; - } - } - - return changed ? 1 : 0; -} - -/** Remove all entry guards that have been down or unlisted for so - * 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(time_t now) -{ - char dbuf[HEX_DIGEST_LEN+1]; - char tbuf[ISO_TIME_LEN+1]; - int i; - int changed = 0; - - for (i = 0; i < smartlist_len(entry_guards); ) { - entry_guard_t *entry = smartlist_get(entry_guards, i); - if (entry->bad_since && - ! entry->path_bias_disabled && - entry->bad_since + ENTRY_GUARD_REMOVE_AFTER < now) { - - base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN); - format_local_iso_time(tbuf, entry->bad_since); - log_info(LD_CIRC, "Entry guard '%s' (%s) has been down or unlisted " - "since %s local time; removing.", - entry->nickname, dbuf, tbuf); - control_event_guard(entry->nickname, entry->identity, "DROPPED"); - entry_guard_free(entry); - smartlist_del_keeporder(entry_guards, i); - log_entry_guards(LOG_INFO); - changed = 1; - } else - ++i; - } - return changed ? 1 : 0; -} - -/** A new directory or router-status has arrived; update the down/listed - * status of the entry guards. - * - * An entry is 'down' if the directory lists it as nonrunning. - * An entry is 'unlisted' if the directory doesn't include it. - * - * Don't call this on startup; only on a fresh download. Otherwise we'll - * think that things are unlisted. - */ -void -entry_guards_compute_status(const or_options_t *options, time_t now) -{ - int changed = 0; - digestmap_t *reasons; - - if (! entry_guards) - return; - - 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) - { - const node_t *r = node_get_by_id(entry->identity); - const char *reason = NULL; - if (entry_guard_set_status(entry, r, now, options, &reason)) - changed = 1; - - if (entry->bad_since) - tor_assert(reason); - if (reason) - digestmap_set(reasons, entry->identity, (char*)reason); - } - SMARTLIST_FOREACH_END(entry); - - if (remove_dead_entry_guards(now)) - changed = 1; - if (remove_obsolete_entry_guards(now)) - changed = 1; - - if (changed) { - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { - const char *reason = digestmap_get(reasons, entry->identity); - const char *live_msg = ""; - const node_t *r = entry_is_live(entry, 0, 1, 0, &live_msg); - log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", - entry->nickname, - hex_str(entry->identity, DIGEST_LEN), - entry->unreachable_since ? "unreachable" : "reachable", - entry->bad_since ? "unusable" : "usable", - reason ? ", ": "", - reason ? reason : "", - 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)); - log_entry_guards(LOG_INFO); - entry_guards_changed(); - } - - digestmap_free(reasons, NULL); -} - -/** Called when a connection to an OR with the identity digest <b>digest</b> - * is established (<b>succeeded</b>==1) or has failed (<b>succeeded</b>==0). - * If the OR is an entry, change that entry's up/down status. - * Return 0 normally, or -1 if we want to tear down the new connection. - * - * If <b>mark_relay_status</b>, also call router_set_status() on this - * relay. - * - * XXX024 change succeeded and mark_relay_status into 'int flags'. - */ -int -entry_guard_register_connect_status(const char *digest, int succeeded, - int mark_relay_status, time_t now) -{ - int changed = 0; - int refuse_conn = 0; - int first_contact = 0; - entry_guard_t *entry = NULL; - int idx = -1; - char buf[HEX_DIGEST_LEN+1]; - - if (! entry_guards) - return 0; - - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { - tor_assert(e); - if (tor_memeq(e->identity, digest, DIGEST_LEN)) { - entry = e; - idx = e_sl_idx; - break; - } - } SMARTLIST_FOREACH_END(e); - - if (!entry) - return 0; - - base16_encode(buf, sizeof(buf), entry->identity, DIGEST_LEN); - - if (succeeded) { - if (entry->unreachable_since) { - log_info(LD_CIRC, "Entry guard '%s' (%s) is now reachable again. Good.", - entry->nickname, buf); - entry->can_retry = 0; - entry->unreachable_since = 0; - entry->last_attempted = now; - control_event_guard(entry->nickname, entry->identity, "UP"); - changed = 1; - } - if (!entry->made_contact) { - entry->made_contact = 1; - first_contact = changed = 1; - } - } else { /* ! succeeded */ - if (!entry->made_contact) { - /* We've never connected to this one. */ - log_info(LD_CIRC, - "Connection to never-contacted entry guard '%s' (%s) failed. " - "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); - changed = 1; - } else if (!entry->unreachable_since) { - log_info(LD_CIRC, "Unable to connect to entry guard '%s' (%s). " - "Marking as unreachable.", entry->nickname, buf); - entry->unreachable_since = entry->last_attempted = now; - control_event_guard(entry->nickname, entry->identity, "DOWN"); - changed = 1; - entry->can_retry = 0; /* We gave it an early chance; no good. */ - } else { - char tbuf[ISO_TIME_LEN+1]; - format_iso_time(tbuf, entry->unreachable_since); - log_debug(LD_CIRC, "Failed to connect to unreachable entry guard " - "'%s' (%s). It has been unreachable since %s.", - entry->nickname, buf, tbuf); - entry->last_attempted = now; - entry->can_retry = 0; /* We gave it an early chance; no good. */ - } - } - - /* if the caller asked us to, also update the is_running flags for this - * relay */ - if (mark_relay_status) - router_set_status(digest, succeeded); - - if (first_contact) { - /* We've just added a new long-term entry guard. Perhaps the network just - * came back? We should give our earlier entries another try too, - * and close this connection so we don't use it before we've given - * the others a shot. */ - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { - if (e == entry) - break; - if (e->made_contact) { - const char *msg; - const node_t *r = entry_is_live(e, 0, 1, 1, &msg); - if (r && e->unreachable_since) { - refuse_conn = 1; - e->can_retry = 1; - } - } - } SMARTLIST_FOREACH_END(e); - if (refuse_conn) { - log_info(LD_CIRC, - "Connected to new entry guard '%s' (%s). Marking earlier " - "entry guards up. %d/%d entry guards usable/new.", - entry->nickname, buf, - num_live_entry_guards(), smartlist_len(entry_guards)); - log_entry_guards(LOG_INFO); - changed = 1; - } - } - - if (changed) - entry_guards_changed(); - return refuse_conn ? -1 : 0; -} - -/** When we try to choose an entry guard, should we parse and add - * config's EntryNodes first? */ -static int should_add_entry_nodes = 0; - -/** Called when the value of EntryNodes changes in our configuration. */ -void -entry_nodes_should_be_added(void) -{ - log_info(LD_CIRC, "EntryNodes config option set. Putting configured " - "relays at the front of the entry guard list."); - should_add_entry_nodes = 1; -} - -/** Adjust the entry guards list so that it only contains entries from - * EntryNodes, adding new entries from EntryNodes to the list as needed. */ -static void -entry_guards_set_from_config(const or_options_t *options) -{ - smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps; - smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list; - tor_assert(entry_guards); - - should_add_entry_nodes = 0; - - if (!options->EntryNodes) { - /* It's possible that a controller set EntryNodes, thus making - * should_add_entry_nodes set, then cleared it again, all before the - * call to choose_random_entry() that triggered us. If so, just return. - */ - return; - } - - { - char *string = routerset_to_string(options->EntryNodes); - log_info(LD_CIRC,"Adding configured EntryNodes '%s'.", string); - tor_free(string); - } - - entry_nodes = smartlist_new(); - worse_entry_nodes = smartlist_new(); - entry_fps = smartlist_new(); - old_entry_guards_on_list = smartlist_new(); - old_entry_guards_not_on_list = smartlist_new(); - - /* Split entry guards into those on the list and those not. */ - - routerset_get_all_nodes(entry_nodes, options->EntryNodes, - options->ExcludeNodes, 0); - SMARTLIST_FOREACH(entry_nodes, const node_t *,node, - smartlist_add(entry_fps, (void*)node->identity)); - - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, { - if (smartlist_digest_isin(entry_fps, e->identity)) - smartlist_add(old_entry_guards_on_list, e); - else - smartlist_add(old_entry_guards_not_on_list, e); - }); - - /* Remove all currently configured guard nodes, excluded nodes, unreachable - * nodes, or non-Guard nodes from entry_nodes. */ - SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { - if (entry_guard_get_by_id_digest(node->identity)) { - SMARTLIST_DEL_CURRENT(entry_nodes, node); - continue; - } else if (routerset_contains_node(options->ExcludeNodes, node)) { - SMARTLIST_DEL_CURRENT(entry_nodes, node); - continue; - } else if (!fascist_firewall_allows_node(node)) { - SMARTLIST_DEL_CURRENT(entry_nodes, node); - continue; - } else if (! node->is_possible_guard) { - smartlist_add(worse_entry_nodes, (node_t*)node); - SMARTLIST_DEL_CURRENT(entry_nodes, node); - } - } SMARTLIST_FOREACH_END(node); - - /* Now build the new entry_guards list. */ - smartlist_clear(entry_guards); - /* First, the previously configured guards that are in EntryNodes. */ - smartlist_add_all(entry_guards, old_entry_guards_on_list); - /* Next, scramble the rest of EntryNodes, putting the guards first. */ - smartlist_shuffle(entry_nodes); - smartlist_shuffle(worse_entry_nodes); - smartlist_add_all(entry_nodes, worse_entry_nodes); - - /* Next, the rest of EntryNodes */ - SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { - add_an_entry_guard(node, 0, 0); - if (smartlist_len(entry_guards) > options->NumEntryGuards * 10) - break; - } SMARTLIST_FOREACH_END(node); - log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(entry_guards)); - /* Finally, free the remaining previously configured guards that are not in - * EntryNodes. */ - SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e, - entry_guard_free(e)); - - smartlist_free(entry_nodes); - smartlist_free(worse_entry_nodes); - smartlist_free(entry_fps); - smartlist_free(old_entry_guards_on_list); - smartlist_free(old_entry_guards_not_on_list); - entry_guards_changed(); -} - -/** 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 must stick to it. - */ -int -entry_list_is_constrained(const or_options_t *options) -{ - if (options->EntryNodes) - return 1; - if (options->UseBridges) - return 1; - return 0; -} - -/** Pick a live (up and listed) entry guard from entry_guards. If - * <b>state</b> is non-NULL, this is for a specific circuit -- - * make sure not to pick this circuit's exit or any node in the - * exit's family. If <b>state</b> is NULL, we're looking for a random - * guard (likely a bridge). */ -const node_t * -choose_random_entry(cpath_build_state_t *state) -{ - const or_options_t *options = get_options(); - smartlist_t *live_entry_guards = smartlist_new(); - smartlist_t *exit_family = smartlist_new(); - const node_t *chosen_exit = - state?build_state_get_exit_node(state) : NULL; - const node_t *node = NULL; - int need_uptime = state ? state->need_uptime : 0; - int need_capacity = state ? state->need_capacity : 0; - int preferred_min, consider_exit_family = 0; - - if (chosen_exit) { - nodelist_add_node_and_family(exit_family, chosen_exit); - consider_exit_family = 1; - } - - if (!entry_guards) - entry_guards = smartlist_new(); - - if (should_add_entry_nodes) - entry_guards_set_from_config(options); - - if (!entry_list_is_constrained(options) && - smartlist_len(entry_guards) < options->NumEntryGuards) - pick_entry_guards(options); - - retry: - smartlist_clear(live_entry_guards); - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { - const char *msg; - node = entry_is_live(entry, need_uptime, need_capacity, 0, &msg); - if (!node) - continue; /* down, no point */ - if (node == chosen_exit) - continue; /* don't pick the same node for entry and exit */ - if (consider_exit_family && smartlist_isin(exit_family, node)) - continue; /* avoid relays that are family members of our exit */ -#if 0 /* since EntryNodes is always strict now, this clause is moot */ - if (options->EntryNodes && - !routerset_contains_node(options->EntryNodes, node)) { - /* We've come to the end of our preferred entry nodes. */ - if (smartlist_len(live_entry_guards)) - goto choose_and_finish; /* only choose from the ones we like */ - if (options->StrictNodes) { - /* in theory this case should never happen, since - * entry_guards_set_from_config() drops unwanted relays */ - tor_fragile_assert(); - } else { - log_info(LD_CIRC, - "No relays from EntryNodes available. Using others."); - } - } -#endif - smartlist_add(live_entry_guards, (void*)node); - if (!entry->made_contact) { - /* Always start with the first not-yet-contacted entry - * guard. Otherwise we might add several new ones, pick - * 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) - goto choose_and_finish; /* we have enough */ - } SMARTLIST_FOREACH_END(entry); - - if (entry_list_is_constrained(options)) { - /* If we prefer the entry nodes we've got, and we have at least - * 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_constrained(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 - * be a long time til we get it. -RD */ - node = add_an_entry_guard(NULL, 0, 0); - if (node) { - entry_guards_changed(); - /* XXX we start over here in case the new node we added shares - * a family with our exit node. There's a chance that we'll just - * load up on entry guards here, if the network we're using is - * one big family. Perhaps we should teach add_an_entry_guard() - * to understand nodes-to-avoid-if-possible? -RD */ - goto retry; - } - } - if (!node && need_uptime) { - need_uptime = 0; /* try without that requirement */ - goto retry; - } - if (!node && need_capacity) { - /* still no? last attempt, try without requiring capacity */ - need_capacity = 0; - goto retry; - } -#if 0 - /* Removing this retry logic: if we only allow one exit, and it is in the - same family as all our entries, then we are just plain not going to win - here. */ - if (!node && entry_list_is_constrained(options) && consider_exit_family) { - /* still no? if we're using bridges or have strictentrynodes - * set, and our chosen exit is in the same family as all our - * bridges/entry guards, then be flexible about families. */ - consider_exit_family = 0; - goto retry; - } -#endif - /* live_entry_guards may be empty below. Oh well, we tried. */ - } - - choose_and_finish: - 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. */ - node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD); - } else { - /* We choose uniformly at random here, because choose_good_entry_server() - * already weights its choices by bandwidth, so we don't want to - * *double*-weight our guard selection. */ - node = smartlist_choose(live_entry_guards); - } - smartlist_free(live_entry_guards); - smartlist_free(exit_family); - return node; -} - -/** Parse <b>state</b> and learn about the entry guards it describes. - * If <b>set</b> is true, and there are no errors, replace the global - * entry_list with what we find. - * On success, return 0. On failure, alloc into *<b>msg</b> a string - * describing the error, and return -1. - */ -int -entry_guards_parse_state(or_state_t *state, int set, char **msg) -{ - entry_guard_t *node = NULL; - smartlist_t *new_entry_guards = smartlist_new(); - config_line_t *line; - time_t now = time(NULL); - const char *state_version = state->TorVersion; - digestmap_t *added_by = digestmap_new(); - - *msg = NULL; - for (line = state->EntryGuards; line; line = line->next) { - if (!strcasecmp(line->key, "EntryGuard")) { - smartlist_t *args = smartlist_new(); - node = tor_malloc_zero(sizeof(entry_guard_t)); - /* all entry guards on disk have been contacted */ - node->made_contact = 1; - smartlist_add(new_entry_guards, node); - smartlist_split_string(args, line->value, " ", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - if (smartlist_len(args)<2) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Too few arguments to EntryGuard"); - } else if (!is_legal_nickname(smartlist_get(args,0))) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Bad nickname for EntryGuard"); - } else { - strlcpy(node->nickname, smartlist_get(args,0), MAX_NICKNAME_LEN+1); - if (base16_decode(node->identity, DIGEST_LEN, smartlist_get(args,1), - strlen(smartlist_get(args,1)))<0) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Bad hex digest for EntryGuard"); - } - } - SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); - smartlist_free(args); - if (*msg) - break; - } else if (!strcasecmp(line->key, "EntryGuardDownSince") || - !strcasecmp(line->key, "EntryGuardUnlistedSince")) { - time_t when; - time_t last_try = 0; - if (!node) { - *msg = tor_strdup("Unable to parse entry nodes: " - "EntryGuardDownSince/UnlistedSince without EntryGuard"); - break; - } - if (parse_iso_time(line->value, &when)<0) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Bad time in EntryGuardDownSince/UnlistedSince"); - break; - } - if (when > now) { - /* It's a bad idea to believe info in the future: you can wind - * up with timeouts that aren't allowed to happen for years. */ - continue; - } - if (strlen(line->value) >= ISO_TIME_LEN+ISO_TIME_LEN+1) { - /* ignore failure */ - (void) parse_iso_time(line->value+ISO_TIME_LEN+1, &last_try); - } - if (!strcasecmp(line->key, "EntryGuardDownSince")) { - node->unreachable_since = when; - node->last_attempted = last_try; - } else { - node->bad_since = when; - } - } else if (!strcasecmp(line->key, "EntryGuardAddedBy")) { - char d[DIGEST_LEN]; - /* format is digest version date */ - if (strlen(line->value) < HEX_DIGEST_LEN+1+1+1+ISO_TIME_LEN) { - log_warn(LD_BUG, "EntryGuardAddedBy line is not long enough."); - continue; - } - if (base16_decode(d, sizeof(d), line->value, HEX_DIGEST_LEN)<0 || - line->value[HEX_DIGEST_LEN] != ' ') { - log_warn(LD_BUG, "EntryGuardAddedBy line %s does not begin with " - "hex digest", escaped(line->value)); - continue; - } - digestmap_set(added_by, d, tor_strdup(line->value+HEX_DIGEST_LEN+1)); - } else if (!strcasecmp(line->key, "EntryGuardPathBias")) { - const or_options_t *options = get_options(); - unsigned hop_cnt, success_cnt; - - if (!node) { - *msg = tor_strdup("Unable to parse entry nodes: " - "EntryGuardPathBias without EntryGuard"); - break; - } - - if (tor_sscanf(line->value, "%u %u", &success_cnt, &hop_cnt) != 2) { - log_warn(LD_GENERAL, "Unable to parse guard path bias info: " - "Misformated EntryGuardPathBias %s", escaped(line->value)); - continue; - } - - node->first_hops = hop_cnt; - node->circuit_successes = success_cnt; - log_info(LD_GENERAL, "Read %u/%u path bias for node %s", - node->circuit_successes, node->first_hops, node->nickname); - /* Note: We rely on the < comparison here to allow us to set a 0 - * rate and disable the feature entirely. If refactoring, don't - * change to <= */ - if (node->circuit_successes/((double)node->first_hops) - < pathbias_get_disable_rate(options)) { - node->path_bias_disabled = 1; - log_info(LD_GENERAL, - "Path bias is too high (%u/%u); disabling node %s", - node->circuit_successes, node->first_hops, node->nickname); - } - - } else { - log_warn(LD_BUG, "Unexpected key %s", line->key); - } - } - - SMARTLIST_FOREACH_BEGIN(new_entry_guards, entry_guard_t *, e) { - char *sp; - char *val = digestmap_get(added_by, e->identity); - if (val && (sp = strchr(val, ' '))) { - time_t when; - *sp++ = '\0'; - if (parse_iso_time(sp, &when)<0) { - log_warn(LD_BUG, "Can't read time %s in EntryGuardAddedBy", sp); - } else { - e->chosen_by_version = tor_strdup(val); - e->chosen_on_date = when; - } - } else { - if (state_version) { - e->chosen_by_version = tor_strdup(state_version); - e->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); - } - } - if (e->path_bias_disabled && !e->bad_since) - e->bad_since = time(NULL); - } - SMARTLIST_FOREACH_END(e); - - if (*msg || !set) { - SMARTLIST_FOREACH(new_entry_guards, entry_guard_t *, e, - entry_guard_free(e)); - smartlist_free(new_entry_guards); - } else { /* !err && set */ - if (entry_guards) { - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, - entry_guard_free(e)); - smartlist_free(entry_guards); - } - entry_guards = new_entry_guards; - entry_guards_dirty = 0; - /* XXX024 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(now)) - entry_guards_dirty = 1; - } - digestmap_free(added_by, _tor_free); - return *msg ? -1 : 0; -} - -/** Our list of entry guards has changed, or some element of one - * of our entry guards has changed. Write the changes to disk within - * the next few minutes. - */ -static void -entry_guards_changed(void) -{ - time_t when; - entry_guards_dirty = 1; - - /* or_state_save() will call entry_guards_update_state(). */ - when = get_options()->AvoidDiskWrites ? time(NULL) + 3600 : time(NULL)+600; - or_state_mark_dirty(get_or_state(), when); -} - -/** If the entry guard info has not changed, do nothing and return. - * Otherwise, free the EntryGuards piece of <b>state</b> and create - * a new one out of the global entry_guards list, and then mark - * <b>state</b> dirty so it will get saved to disk. - */ -void -entry_guards_update_state(or_state_t *state) -{ - config_line_t **next, *line; - if (! entry_guards_dirty) - return; - - config_free_lines(state->EntryGuards); - next = &state->EntryGuards; - *next = NULL; - if (!entry_guards) - entry_guards = smartlist_new(); - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { - char dbuf[HEX_DIGEST_LEN+1]; - if (!e->made_contact) - continue; /* don't write this one to disk */ - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuard"); - base16_encode(dbuf, sizeof(dbuf), e->identity, DIGEST_LEN); - tor_asprintf(&line->value, "%s %s", e->nickname, dbuf); - next = &(line->next); - if (e->unreachable_since) { - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardDownSince"); - line->value = tor_malloc(ISO_TIME_LEN+1+ISO_TIME_LEN+1); - format_iso_time(line->value, e->unreachable_since); - if (e->last_attempted) { - line->value[ISO_TIME_LEN] = ' '; - format_iso_time(line->value+ISO_TIME_LEN+1, e->last_attempted); - } - next = &(line->next); - } - if (e->bad_since) { - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardUnlistedSince"); - line->value = tor_malloc(ISO_TIME_LEN+1); - format_iso_time(line->value, e->bad_since); - next = &(line->next); - } - if (e->chosen_on_date && e->chosen_by_version && - !strchr(e->chosen_by_version, ' ')) { - char d[HEX_DIGEST_LEN+1]; - char t[ISO_TIME_LEN+1]; - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardAddedBy"); - base16_encode(d, sizeof(d), e->identity, DIGEST_LEN); - format_iso_time(t, e->chosen_on_date); - tor_asprintf(&line->value, "%s %s %s", - d, e->chosen_by_version, t); - next = &(line->next); - } - if (e->first_hops) { - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardPathBias"); - tor_asprintf(&line->value, "%u %u", - e->circuit_successes, e->first_hops); - next = &(line->next); - } - - } SMARTLIST_FOREACH_END(e); - if (!get_options()->AvoidDiskWrites) - or_state_mark_dirty(get_or_state(), 0); - entry_guards_dirty = 0; -} - -/** If <b>question</b> is the string "entry-guards", then dump - * to *<b>answer</b> a newly allocated string describing all of - * the nodes in the global entry_guards list. See control-spec.txt - * for details. - * For backward compatibility, we also handle the string "helper-nodes". - * */ -int -getinfo_helper_entry_guards(control_connection_t *conn, - const char *question, char **answer, - const char **errmsg) -{ - (void) conn; - (void) errmsg; - - if (!strcmp(question,"entry-guards") || - !strcmp(question,"helper-nodes")) { - smartlist_t *sl = smartlist_new(); - char tbuf[ISO_TIME_LEN+1]; - char nbuf[MAX_VERBOSE_NICKNAME_LEN+1]; - if (!entry_guards) - entry_guards = smartlist_new(); - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { - const char *status = NULL; - time_t when = 0; - const node_t *node; - - if (!e->made_contact) { - status = "never-connected"; - } else if (e->bad_since) { - when = e->bad_since; - status = "unusable"; - } else { - status = "up"; - } - - node = node_get_by_id(e->identity); - if (node) { - node_get_verbose_nickname(node, nbuf); - } else { - nbuf[0] = '$'; - base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN); - /* 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); - smartlist_add_asprintf(sl, "%s %s %s\n", nbuf, status, tbuf); - } else { - smartlist_add_asprintf(sl, "%s %s\n", nbuf, status); - } - } SMARTLIST_FOREACH_END(e); - *answer = smartlist_join_strings(sl, "", 0, NULL); - SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); - smartlist_free(sl); - } - return 0; -} - -/** A list of configured bridges. Whenever we actually get a descriptor - * for one, we add it as an entry guard. Note that the order of bridges - * in this list does not necessarily correspond to the order of bridges - * in the torrc. */ -static smartlist_t *bridge_list = NULL; - -/** Mark every entry of the bridge list to be removed on our next call to - * sweep_bridge_list unless it has first been un-marked. */ -void -mark_bridge_list(void) -{ - if (!bridge_list) - bridge_list = smartlist_new(); - SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, - b->marked_for_removal = 1); -} - -/** Remove every entry of the bridge list that was marked with - * mark_bridge_list if it has not subsequently been un-marked. */ -void -sweep_bridge_list(void) -{ - if (!bridge_list) - bridge_list = smartlist_new(); - SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) { - if (b->marked_for_removal) { - SMARTLIST_DEL_CURRENT(bridge_list, b); - bridge_free(b); - } - } SMARTLIST_FOREACH_END(b); -} - -/** Initialize the bridge list to empty, creating it if needed. */ -static void -clear_bridge_list(void) -{ - if (!bridge_list) - bridge_list = smartlist_new(); - SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b)); - smartlist_clear(bridge_list); -} - -/** Free the bridge <b>bridge</b>. */ -static void -bridge_free(bridge_info_t *bridge) -{ - if (!bridge) - return; - - tor_free(bridge->transport_name); - tor_free(bridge); -} - -/** A list of pluggable transports found in torrc. */ -static smartlist_t *transport_list = NULL; - -/** Mark every entry of the transport list to be removed on our next call to - * sweep_transport_list unless it has first been un-marked. */ -void -mark_transport_list(void) -{ - if (!transport_list) - transport_list = smartlist_new(); - SMARTLIST_FOREACH(transport_list, transport_t *, t, - t->marked_for_removal = 1); -} - -/** Remove every entry of the transport list that was marked with - * mark_transport_list if it has not subsequently been un-marked. */ -void -sweep_transport_list(void) -{ - if (!transport_list) - transport_list = smartlist_new(); - SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) { - if (t->marked_for_removal) { - SMARTLIST_DEL_CURRENT(transport_list, t); - transport_free(t); - } - } SMARTLIST_FOREACH_END(t); -} - -/** Initialize the pluggable transports list to empty, creating it if - * needed. */ -void -clear_transport_list(void) -{ - if (!transport_list) - transport_list = smartlist_new(); - SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t)); - smartlist_clear(transport_list); -} - -/** Free the pluggable transport struct <b>transport</b>. */ -void -transport_free(transport_t *transport) -{ - if (!transport) - return; - - tor_free(transport->name); - tor_free(transport); -} - -/** Returns the transport in our transport list that has the name <b>name</b>. - * Else returns NULL. */ -transport_t * -transport_get_by_name(const char *name) -{ - tor_assert(name); - - if (!transport_list) - return NULL; - - SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) { - if (!strcmp(transport->name, name)) - return transport; - } SMARTLIST_FOREACH_END(transport); - - return NULL; -} - -/** Returns a transport_t struct for a transport proxy supporting the - protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using - SOCKS version <b>socks_ver</b>. */ -transport_t * -transport_new(const tor_addr_t *addr, uint16_t port, - const char *name, int socks_ver) -{ - transport_t *t = tor_malloc_zero(sizeof(transport_t)); - - tor_addr_copy(&t->addr, addr); - t->port = port; - t->name = tor_strdup(name); - t->socks_version = socks_ver; - - return t; -} - -/** Resolve any conflicts that the insertion of transport <b>t</b> - * might cause. - * Return 0 if <b>t</b> is OK and should be registered, 1 if there is - * a transport identical to <b>t</b> already registered and -1 if - * <b>t</b> cannot be added due to conflicts. */ -static int -transport_resolve_conflicts(transport_t *t) -{ - /* This is how we resolve transport conflicts: - - If there is already a transport with the same name and addrport, - we either have duplicate torrc lines OR we are here post-HUP and - this transport was here pre-HUP as well. In any case, mark the - old transport so that it doesn't get removed and ignore the new - one. Our caller has to free the new transport so we return '1' to - signify this. - - If there is already a transport with the same name but different - addrport: - * if it's marked for removal, it means that it either has a lower - priority than 't' in torrc (otherwise the mark would have been - cleared by the paragraph above), or it doesn't exist at all in - the post-HUP torrc. We destroy the old transport and register 't'. - * if it's *not* marked for removal, it means that it was newly - added in the post-HUP torrc or that it's of higher priority, in - this case we ignore 't'. */ - transport_t *t_tmp = transport_get_by_name(t->name); - if (t_tmp) { /* same name */ - if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) { - /* same name *and* addrport */ - t_tmp->marked_for_removal = 0; - return 1; - } else { /* same name but different addrport */ - char *new_transport_addr = tor_strdup(fmt_addr(&t->addr)); - if (t_tmp->marked_for_removal) { /* marked for removal */ - log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' " - "but there was already a transport marked for deletion at " - "'%s:%u'. We deleted the old transport and registered the " - "new one.", t->name, new_transport_addr, t->port, - fmt_addr(&t_tmp->addr), t_tmp->port); - smartlist_remove(transport_list, t_tmp); - transport_free(t_tmp); - tor_free(new_transport_addr); - } else { /* *not* marked for removal */ - log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' " - "but the same transport already exists at '%s:%u'. " - "Skipping.", t->name, new_transport_addr, t->port, - fmt_addr(&t_tmp->addr), t_tmp->port); - tor_free(new_transport_addr); - return -1; - } - } - } - - return 0; -} - -/** Add transport <b>t</b> to the internal list of pluggable - * transports. - * Returns 0 if the transport was added correctly, 1 if the same - * transport was already registered (in this case the caller must - * free the transport) and -1 if there was an error. */ -int -transport_add(transport_t *t) -{ - int r; - tor_assert(t); - - r = transport_resolve_conflicts(t); - - switch (r) { - case 0: /* should register transport */ - if (!transport_list) - transport_list = smartlist_new(); - smartlist_add(transport_list, t); - return 0; - default: /* let our caller know the return code */ - return r; - } -} - -/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>. - * <b>name</b> is set to the name of the protocol this proxy uses. - * <b>socks_ver</b> is set to the SOCKS version of the proxy. */ -int -transport_add_from_config(const tor_addr_t *addr, uint16_t port, - const char *name, int socks_ver) -{ - transport_t *t = transport_new(addr, port, name, socks_ver); - - int r = transport_add(t); - - switch (r) { - case -1: - default: - log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.", - t->name, fmt_addr(&t->addr), t->port); - transport_free(t); - return -1; - case 1: - log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.", - t->name, fmt_addr(&t->addr), t->port); - transport_free(t); /* falling */ - return 0; - case 0: - log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.", - t->name, fmt_addr(&t->addr), t->port); - return 0; - } -} - -/** Return a bridge pointer if <b>ri</b> is one of our known bridges - * (either by comparing keys if possible, else by comparing addr/port). - * Else return NULL. */ -static bridge_info_t * -get_configured_bridge_by_addr_port_digest(const 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_compare(&bridge->addr, addr, CMP_EXACT) && - bridge->port == port) - return bridge; - if (digest && tor_memeq(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(const routerinfo_t *ri) -{ - tor_addr_port_t ap; - - router_get_pref_orport(ri, &ap); - return get_configured_bridge_by_addr_port_digest(&ap.addr, ap.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(const routerinfo_t *ri) -{ - return get_configured_bridge_by_routerinfo(ri) ? 1 : 0; -} - -/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */ -int -node_is_a_configured_bridge(const node_t *node) -{ - int retval = 0; /* Negative. */ - smartlist_t *orports = NULL; - - if (!node) - goto out; - - orports = node_get_all_orports(node); - if (orports == NULL) - goto out; - - SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, orport) { - if (get_configured_bridge_by_addr_port_digest(&orport->addr, orport->port, - node->identity) != NULL) { - retval = 1; - goto out; - } - } SMARTLIST_FOREACH_END(orport); - - out: - if (orports != NULL) { - SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p)); - smartlist_free(orports); - orports = NULL; - } - return retval; -} - -/** 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(const 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); - } -} - -/** Return true if <b>bridge</b> has the same identity digest as - * <b>digest</b>. If <b>digest</b> is NULL, it matches - * bridges with unspecified identity digests. */ -static int -bridge_has_digest(const bridge_info_t *bridge, const char *digest) -{ - if (digest) - return tor_memeq(digest, bridge->identity, DIGEST_LEN); - else - return tor_digest_is_zero(bridge->identity); -} - -/** We are about to add a new bridge at <b>addr</b>:<b>port</b>, with optional - * <b>digest</b> and <b>transport_name</b>. Mark for removal any previously - * existing bridge with the same address and port, and warn the user as - * appropriate. - */ -static void -bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port, - const char *digest, const char *transport_name) -{ - /* Iterate the already-registered bridge list: - - If you find a bridge with the same adress and port, mark it for - removal. It doesn't make sense to have two active bridges with - the same IP:PORT. If the bridge in question has a different - digest or transport than <b>digest</b>/<b>transport_name</b>, - it's probably a misconfiguration and we should warn the user. - */ - SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) { - if (bridge->marked_for_removal) - continue; - - if (tor_addr_eq(&bridge->addr, addr) && (bridge->port == port)) { - - bridge->marked_for_removal = 1; - - if (!bridge_has_digest(bridge, digest) || - strcmp_opt(bridge->transport_name, transport_name)) { - /* warn the user */ - char *bridge_description_new, *bridge_description_old; - tor_asprintf(&bridge_description_new, "%s:%u:%s:%s", - fmt_addr(addr), port, - digest ? hex_str(digest, DIGEST_LEN) : "", - transport_name ? transport_name : ""); - tor_asprintf(&bridge_description_old, "%s:%u:%s:%s", - fmt_addr(&bridge->addr), bridge->port, - tor_digest_is_zero(bridge->identity) ? - "" : hex_str(bridge->identity,DIGEST_LEN), - bridge->transport_name ? bridge->transport_name : ""); - - log_warn(LD_GENERAL,"Tried to add bridge '%s', but we found a conflict" - " with the already registered bridge '%s'. We will discard" - " the old bridge and keep '%s'. If this is not what you" - " wanted, please change your configuration file accordingly.", - bridge_description_new, bridge_description_old, - bridge_description_new); - - tor_free(bridge_description_new); - tor_free(bridge_description_old); - } - } - } SMARTLIST_FOREACH_END(bridge); -} - -/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b> - * is set, it tells us the identity key too. If we already had the - * bridge in our list, unmark it, and don't actually add anything new. - * If <b>transport_name</b> is non-NULL - the bridge is associated with a - * pluggable transport - we assign the transport to the bridge. */ -void -bridge_add_from_config(const tor_addr_t *addr, uint16_t port, - const char *digest, const char *transport_name) -{ - bridge_info_t *b; - - bridge_resolve_conflicts(addr, port, digest, transport_name); - - b = tor_malloc_zero(sizeof(bridge_info_t)); - tor_addr_copy(&b->addr, addr); - b->port = port; - if (digest) - memcpy(b->identity, digest, DIGEST_LEN); - if (transport_name) - b->transport_name = tor_strdup(transport_name); - b->fetch_status.schedule = DL_SCHED_BRIDGE; - if (!bridge_list) - bridge_list = smartlist_new(); - - smartlist_add(bridge_list, b); -} - -/** Return true iff <b>routerset</b> contains the bridge <b>bridge</b>. */ -static int -routerset_contains_bridge(const routerset_t *routerset, - const bridge_info_t *bridge) -{ - int result; - extend_info_t *extinfo; - tor_assert(bridge); - if (!routerset) - return 0; - - extinfo = extend_info_alloc( - NULL, bridge->identity, NULL, &bridge->addr, bridge->port); - result = routerset_contains_extendinfo(routerset, extinfo); - extend_info_free(extinfo); - return result; -} - -/** If <b>digest</b> is one of our known bridges, return it. */ -static bridge_info_t * -find_bridge_by_digest(const char *digest) -{ - SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, - { - if (tor_memeq(bridge->identity, digest, DIGEST_LEN)) - return bridge; - }); - return NULL; -} - -/* DOCDOC find_transport_name_by_bridge_addrport */ -const char * -find_transport_name_by_bridge_addrport(const tor_addr_t *addr, uint16_t port) -{ - if (!bridge_list) - return NULL; - - SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) { - if (tor_addr_eq(&bridge->addr, addr) && - (bridge->port == port)) - return bridge->transport_name; - } SMARTLIST_FOREACH_END(bridge); - - return NULL; -} - -/** If <b>addr</b> and <b>port</b> match the address and port of a - * bridge of ours that uses pluggable transports, place its transport - * in <b>transport</b>. - * - * Return 0 on success (found a transport, or found a bridge with no - * transport, or found no bridge); return -1 if we should be using a - * transport, but the transport could not be found. - */ -int -find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, - const transport_t **transport) -{ - *transport = NULL; - if (!bridge_list) - return 0; - - SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) { - if (tor_addr_eq(&bridge->addr, addr) && - (bridge->port == port)) { /* bridge matched */ - if (bridge->transport_name) { /* it also uses pluggable transports */ - *transport = transport_get_by_name(bridge->transport_name); - if (*transport == NULL) { /* it uses pluggable transports, but - the transport could not be found! */ - return -1; - } - return 0; - } else { /* bridge matched, but it doesn't use transports. */ - break; - } - } - } SMARTLIST_FOREACH_END(bridge); - - *transport = NULL; - return 0; -} - -/** We need to ask <b>bridge</b> for its server descriptor. */ -static void -launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) -{ - char *address; - const or_options_t *options = get_options(); - - if (connection_get_by_type_addr_port_purpose( - CONN_TYPE_DIR, &bridge->addr, bridge->port, - DIR_PURPOSE_FETCH_SERVERDESC)) - return; /* it's already on the way */ - - if (routerset_contains_bridge(options->ExcludeNodes, bridge)) { - download_status_mark_impossible(&bridge->fetch_status); - log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.", - safe_str_client(fmt_addr(&bridge->addr))); - return; - } - - address = tor_dup_addr(&bridge->addr); - - directory_initiate_command(address, &bridge->addr, - bridge->port, 0, - 0, /* does not matter */ - 1, bridge->identity, - DIR_PURPOSE_FETCH_SERVERDESC, - ROUTER_PURPOSE_BRIDGE, - 0, "authority.z", NULL, 0, 0); - tor_free(address); -} - -/** Fetching the bridge descriptor from the bridge authority returned a - * "not found". Fall back to trying a direct fetch. */ -void -retry_bridge_descriptor_fetch_directly(const char *digest) -{ - bridge_info_t *bridge = find_bridge_by_digest(digest); - if (!bridge) - return; /* not found? oh well. */ - - launch_direct_bridge_descriptor_fetch(bridge); -} - -/** For each bridge in our list for which we don't currently have a - * descriptor, fetch a new copy of its descriptor -- either directly - * from the bridge or via a bridge authority. */ -void -fetch_bridge_descriptors(const or_options_t *options, time_t now) -{ - int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO); - int ask_bridge_directly; - int can_use_bridge_authority; - - if (!bridge_list) - return; - - /* If we still have unconfigured managed proxies, don't go and - connect to a bridge. */ - if (pt_proxies_configuration_pending()) - return; - - SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) - { - if (!download_status_is_ready(&bridge->fetch_status, now, - IMPOSSIBLE_TO_DOWNLOAD)) - continue; /* don't bother, no need to retry yet */ - if (routerset_contains_bridge(options->ExcludeNodes, bridge)) { - download_status_mark_impossible(&bridge->fetch_status); - log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.", - safe_str_client(fmt_addr(&bridge->addr))); - continue; - } - - /* schedule another fetch as if this one will fail, in case it does */ - download_status_failed(&bridge->fetch_status, 0); - - can_use_bridge_authority = !tor_digest_is_zero(bridge->identity) && - num_bridge_auths; - ask_bridge_directly = !can_use_bridge_authority || - !options->UpdateBridgesFromAuthority; - log_debug(LD_DIR, "ask_bridge_directly=%d (%d, %d, %d)", - ask_bridge_directly, tor_digest_is_zero(bridge->identity), - !options->UpdateBridgesFromAuthority, !num_bridge_auths); - - if (ask_bridge_directly && - !fascist_firewall_allows_address_or(&bridge->addr, bridge->port)) { - log_notice(LD_DIR, "Bridge at '%s:%d' isn't reachable by our " - "firewall policy. %s.", fmt_addr(&bridge->addr), - bridge->port, - can_use_bridge_authority ? - "Asking bridge authority instead" : "Skipping"); - if (can_use_bridge_authority) - ask_bridge_directly = 0; - else - continue; - } - - if (ask_bridge_directly) { - /* we need to ask the bridge itself for its descriptor. */ - launch_direct_bridge_descriptor_fetch(bridge); - } else { - /* We have a digest and we want to ask an authority. We could - * combine all the requests into one, but that may give more - * hints to the bridge authority than we want to give. */ - char resource[10 + HEX_DIGEST_LEN]; - memcpy(resource, "fp/", 3); - base16_encode(resource+3, HEX_DIGEST_LEN+1, - bridge->identity, DIGEST_LEN); - memcpy(resource+3+HEX_DIGEST_LEN, ".z", 3); - log_info(LD_DIR, "Fetching bridge info '%s' from bridge authority.", - resource); - directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC, - ROUTER_PURPOSE_BRIDGE, resource, 0); - } - } - SMARTLIST_FOREACH_END(bridge); -} - -/** If our <b>bridge</b> is configured to be a different address than - * the bridge gives in <b>node</b>, rewrite the routerinfo - * we received to use the address we meant to use. Now we handle - * multihomed bridges better. - */ -static void -rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node) -{ - /* XXXX move this function. */ - /* XXXX overridden addresses should really live in the node_t, so that the - * routerinfo_t and the microdesc_t can be immutable. But we can only - * do that safely if we know that no function that connects to an OR - * does so through an address from any source other than node_get_addr(). - */ - tor_addr_t addr; - - if (node->ri) { - routerinfo_t *ri = node->ri; - tor_addr_from_ipv4h(&addr, ri->addr); - - if ((!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) && - bridge->port == ri->or_port) || - (!tor_addr_compare(&bridge->addr, &ri->ipv6_addr, CMP_EXACT) && - bridge->port == ri->ipv6_orport)) { - /* they match, so no need to do anything */ - } else { - if (tor_addr_family(&bridge->addr) == AF_INET) { - ri->addr = tor_addr_to_ipv4h(&bridge->addr); - tor_free(ri->address); - ri->address = tor_dup_ip(ri->addr); - ri->or_port = bridge->port; - log_info(LD_DIR, - "Adjusted bridge routerinfo for '%s' to match configured " - "address %s:%d.", - ri->nickname, ri->address, ri->or_port); - } else if (tor_addr_family(&bridge->addr) == AF_INET6) { - tor_addr_copy(&ri->ipv6_addr, &bridge->addr); - ri->ipv6_orport = bridge->port; - log_info(LD_DIR, - "Adjusted bridge routerinfo for '%s' to match configured " - "address %s:%d.", - ri->nickname, fmt_addr(&ri->ipv6_addr), ri->ipv6_orport); - } else { - log_err(LD_BUG, "Address family not supported: %d.", - tor_addr_family(&bridge->addr)); - return; - } - } - - /* Indicate that we prefer connecting to this bridge over the - protocol that the bridge address indicates. Last bridge - descriptor handled wins. */ - ri->ipv6_preferred = tor_addr_family(&bridge->addr) == AF_INET6; - - /* XXXipv6 we lack support for falling back to another address for - the same relay, warn the user */ - if (!tor_addr_is_null(&ri->ipv6_addr)) { - tor_addr_port_t ap; - router_get_pref_orport(ri, &ap); - log_notice(LD_CONFIG, - "Bridge '%s' has both an IPv4 and an IPv6 address. " - "Will prefer using its %s address (%s:%d).", - ri->nickname, - ri->ipv6_preferred ? "IPv6" : "IPv4", - fmt_addr(&ap.addr), ap.port); - } - } - if (node->rs) { - routerstatus_t *rs = node->rs; - tor_addr_from_ipv4h(&addr, rs->addr); - - if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) && - bridge->port == rs->or_port) { - /* they match, so no need to do anything */ - } else { - rs->addr = tor_addr_to_ipv4h(&bridge->addr); - rs->or_port = bridge->port; - log_info(LD_DIR, - "Adjusted bridge routerstatus for '%s' to match " - "configured address %s:%d.", - rs->nickname, fmt_addr(&bridge->addr), rs->or_port); - } - } -} - -/** We just learned a descriptor for a bridge. See if that - * digest is in our entry guard list, and add it if not. */ -void -learned_bridge_descriptor(routerinfo_t *ri, int from_cache) -{ - tor_assert(ri); - tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE); - if (get_options()->UseBridges) { - int first = !any_bridge_descriptors_known(); - bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri); - time_t now = time(NULL); - router_set_status(ri->cache_info.identity_digest, 1); - - if (bridge) { /* if we actually want to use this one */ - node_t *node; - /* it's here; schedule its re-fetch for a long time from now. */ - if (!from_cache) - download_status_reset(&bridge->fetch_status); - - node = node_get_mutable_by_id(ri->cache_info.identity_digest); - tor_assert(node); - rewrite_node_address_for_bridge(bridge, node); - add_an_entry_guard(node, 1, 1); - - log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname, - from_cache ? "cached" : "fresh", router_describe(ri)); - /* set entry->made_contact so if it goes down we don't drop it from - * our entry node list */ - entry_guard_register_connect_status(ri->cache_info.identity_digest, - 1, 0, now); - if (first) - routerlist_retry_directory_downloads(now); - } - } -} - -/** Return 1 if any of our entry guards have descriptors that - * are marked with purpose 'bridge' and are running. Else return 0. - * - * We use this function to decide if we're ready to start building - * circuits through our bridges, or if we need to wait until the - * directory "server/authority" requests finish. */ -int -any_bridge_descriptors_known(void) -{ - tor_assert(get_options()->UseBridges); - return choose_random_entry(NULL)!=NULL ? 1 : 0; -} - -/** Return 1 if there are any directory conns fetching bridge descriptors - * that aren't marked for close. We use this to guess if we should tell - * the controller that we have a problem. */ -int -any_pending_bridge_descriptor_fetches(void) -{ - smartlist_t *conns = get_connection_array(); - SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { - if (conn->type == CONN_TYPE_DIR && - conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC && - TO_DIR_CONN(conn)->router_purpose == ROUTER_PURPOSE_BRIDGE && - !conn->marked_for_close && - conn->linked && - conn->linked_conn && !conn->linked_conn->marked_for_close) { - log_debug(LD_DIR, "found one: %s", conn->address); - return 1; - } - } SMARTLIST_FOREACH_END(conn); - return 0; -} - -/** 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 -entries_retry_helper(const or_options_t *options, int act) -{ - const node_t *node; - int any_known = 0; - int any_running = 0; - int need_bridges = options->UseBridges != 0; - if (!entry_guards) - entry_guards = smartlist_new(); - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { - node = node_get_by_id(e->identity); - if (node && node_has_descriptor(node) && - node_is_bridge(node) == need_bridges) { - any_known = 1; - if (node->is_running) - any_running = 1; /* some entry is both known and running */ - else if (act) { - /* Mark all current connections to this OR as unhealthy, since - * 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(node->identity, 1); - - /* mark this entry node for retry */ - router_set_status(node->identity, 1); - e->can_retry = 1; - e->bad_since = 0; - } - } - } SMARTLIST_FOREACH_END(e); - log_debug(LD_DIR, "%d: any_known %d, any_running %d", - act, any_known, any_running); - return any_known && !any_running; -} - -/** Do we know any descriptors for our bridges / entrynodes, and are - * all the ones we have descriptors for down? */ -int -entries_known_but_down(const or_options_t *options) -{ - tor_assert(entry_list_is_constrained(options)); - return entries_retry_helper(options, 0); -} - -/** Mark all down known bridges / entrynodes up. */ -void -entries_retry_all(const or_options_t *options) -{ - tor_assert(entry_list_is_constrained(options)); - entries_retry_helper(options, 1); -} - -/** Return true if we've ever had a bridge running a Tor version that can't - * provide microdescriptors to us. In that case fall back to asking for - * full descriptors. Eventually all bridges will support microdescriptors - * and we can take this check out; see bug 4013. */ -int -any_bridges_dont_support_microdescriptors(void) -{ - const node_t *node; - static int ever_answered_yes = 0; - if (!get_options()->UseBridges || !entry_guards) - return 0; - if (ever_answered_yes) - return 1; /* if we ever answer 'yes', always answer 'yes' */ - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { - node = node_get_by_id(e->identity); - if (node && node->ri && - node_is_bridge(node) && node_is_a_configured_bridge(node) && - !tor_version_supports_microdescriptors(node->ri->platform)) { - /* This is one of our current bridges, and we know enough about - * it to know that it won't be able to answer our microdescriptor - * questions. */ - ever_answered_yes = 1; - return 1; - } - } SMARTLIST_FOREACH_END(e); - return 0; -} - -/** Release all storage held by the list of entry guards and related - * memory structs. */ -void -entry_guards_free_all(void) -{ - if (entry_guards) { - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, - entry_guard_free(e)); - smartlist_free(entry_guards); - entry_guards = NULL; - } - clear_bridge_list(); - clear_transport_list(); - smartlist_free(bridge_list); - smartlist_free(transport_list); - bridge_list = NULL; - transport_list = NULL; -} - diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index fc6ca65fca..a3091707e8 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,36 +9,20 @@ * \brief Header file for circuitbuild.c. **/ -#ifndef _TOR_CIRCUITBUILD_H -#define _TOR_CIRCUITBUILD_H - -/** Represents a pluggable transport proxy used by a bridge. */ -typedef struct { - /** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */ - int socks_version; - /** Name of pluggable transport protocol */ - char *name; - /** Address of proxy */ - tor_addr_t addr; - /** Port of proxy */ - uint16_t port; - /** Boolean: We are re-parsing our transport list, and we are going to remove - * this one if we don't find it in the list of configured transports. */ - unsigned marked_for_removal : 1; -} transport_t; +#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); -int circuit_build_times_disabled(void); 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); +void circuit_n_chan_done(channel_t *chan, 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); @@ -46,127 +30,43 @@ 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); +struct created_cell_t; +int circuit_finish_handshake(origin_circuit_t *circ, + const struct created_cell_t *created_cell); +int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, + int reason); +int onionskin_answer(or_circuit_t *circ, + const struct created_cell_t *created_cell, + const char *keys, + const uint8_t *rend_circ_nonce); 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_t *onion_key, - const tor_addr_t *addr, uint16_t port); -extend_info_t *extend_info_from_router(const routerinfo_t *r, - int for_direct_connect); -extend_info_t *extend_info_from_node(const node_t *node, - int for_direct_connect); +extend_info_t *extend_info_new(const char *nickname, const char *digest, + crypto_pk_t *onion_key, + const curve25519_public_key_t *curve25519_key, + const tor_addr_t *addr, uint16_t port); +extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect); extend_info_t *extend_info_dup(extend_info_t *info); void extend_info_free(extend_info_t *info); const node_t *build_state_get_exit_node(cpath_build_state_t *state); const char *build_state_get_exit_nickname(cpath_build_state_t *state); -void entry_guards_compute_status(const or_options_t *options, time_t now); -int entry_guard_register_connect_status(const char *digest, int succeeded, - int mark_relay_status, time_t now); -void entry_nodes_should_be_added(void); -int entry_list_is_constrained(const or_options_t *options); -const node_t *choose_random_entry(cpath_build_state_t *state); -int entry_guards_parse_state(or_state_t *state, int set, char **msg); -void entry_guards_update_state(or_state_t *state); -int getinfo_helper_entry_guards(control_connection_t *conn, - const char *question, char **answer, - const char **errmsg); - -void mark_bridge_list(void); -void sweep_bridge_list(void); -void mark_transport_list(void); -void sweep_transport_list(void); - -int routerinfo_is_a_configured_bridge(const routerinfo_t *ri); -int node_is_a_configured_bridge(const node_t *node); -void learned_router_identity(const tor_addr_t *addr, uint16_t port, - const char *digest); -void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, - const char *digest, - const char *transport_name); -void retry_bridge_descriptor_fetch_directly(const char *digest); -void fetch_bridge_descriptors(const or_options_t *options, time_t now); -void learned_bridge_descriptor(routerinfo_t *ri, int from_cache); -int any_bridge_descriptors_known(void); -int any_pending_bridge_descriptor_fetches(void); -int entries_known_but_down(const or_options_t *options); -void entries_retry_all(const or_options_t *options); - -int any_bridges_dont_support_microdescriptors(void); - -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_free_timeouts(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); - -/* DOCDOC circuit_build_times_get_bw_scale */ -int circuit_build_times_get_bw_scale(networkstatus_t *ns); - -void clear_transport_list(void); -int transport_add_from_config(const tor_addr_t *addr, uint16_t port, - const char *name, int socks_ver); -int transport_add(transport_t *t); -void transport_free(transport_t *transport); -transport_t *transport_new(const tor_addr_t *addr, uint16_t port, - const char *name, int socks_ver); - -/* DOCDOC find_transport_name_by_bridge_addrport */ -const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr, - uint16_t port); - -int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, - const transport_t **transport); -transport_t *transport_get_by_name(const char *name); +const node_t *choose_good_entry_server(uint8_t purpose, + cpath_build_state_t *state); +double pathbias_get_extreme_rate(const or_options_t *options); +double pathbias_get_extreme_use_rate(const or_options_t *options); +int pathbias_get_dropguards(const or_options_t *options); +void pathbias_count_timeout(origin_circuit_t *circ); +int pathbias_check_close(origin_circuit_t *circ, int reason); +int pathbias_check_probe_response(circuit_t *circ, const cell_t *cell); +void pathbias_count_use_attempt(origin_circuit_t *circ); +void pathbias_mark_use_success(origin_circuit_t *circ); +void pathbias_mark_use_rollback(origin_circuit_t *circ); +const char *pathbias_state_to_string(path_state_t state); #endif diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 6250c11d2e..c7b15e40ba 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1,7 +1,7 @@ /* Copyright 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,9 +10,11 @@ **/ #include "or.h" +#include "channel.h" #include "circuitbuild.h" #include "circuitlist.h" #include "circuituse.h" +#include "circuitstats.h" #include "connection.h" #include "config.h" #include "connection_edge.h" @@ -21,11 +23,14 @@ #include "networkstatus.h" #include "nodelist.h" #include "onion.h" +#include "onion_fast.h" +#include "policies.h" #include "relay.h" #include "rendclient.h" #include "rendcommon.h" #include "rephist.h" #include "routerlist.h" +#include "routerset.h" #include "ht.h" /********* START VARIABLES **********/ @@ -33,8 +38,8 @@ /** A global list of all circuits at this hop. */ circuit_t *global_circuitlist=NULL; -/** A list of all the circuits in CIRCUIT_STATE_OR_WAIT. */ -static smartlist_t *circuits_pending_or_conns=NULL; +/** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */ +static smartlist_t *circuits_pending_chans = NULL; static void circuit_free(circuit_t *circ); static void circuit_free_cpath(crypt_path_t *cpath); @@ -43,154 +48,190 @@ static void cpath_ref_decref(crypt_path_reference_t *cpath_ref); /********* END VARIABLES ************/ -/** A map from OR connection and circuit ID to circuit. (Lookup performance is +/** A map from channel and circuit ID to circuit. (Lookup performance is * very important here, since we need to do it every time a cell arrives.) */ -typedef struct orconn_circid_circuit_map_t { - HT_ENTRY(orconn_circid_circuit_map_t) node; - or_connection_t *or_conn; +typedef struct chan_circid_circuit_map_t { + HT_ENTRY(chan_circid_circuit_map_t) node; + channel_t *chan; circid_t circ_id; circuit_t *circuit; -} orconn_circid_circuit_map_t; +} chan_circid_circuit_map_t; -/** Helper for hash tables: compare the OR connection and circuit ID for a and +/** Helper for hash tables: compare the channel and circuit ID for a and * b, and return less than, equal to, or greater than zero appropriately. */ static INLINE int -_orconn_circid_entries_eq(orconn_circid_circuit_map_t *a, - orconn_circid_circuit_map_t *b) +chan_circid_entries_eq_(chan_circid_circuit_map_t *a, + chan_circid_circuit_map_t *b) { - return a->or_conn == b->or_conn && a->circ_id == b->circ_id; + return a->chan == b->chan && a->circ_id == b->circ_id; } /** Helper: return a hash based on circuit ID and the pointer value of - * or_conn in <b>a</b>. */ + * chan in <b>a</b>. */ static INLINE unsigned int -_orconn_circid_entry_hash(orconn_circid_circuit_map_t *a) +chan_circid_entry_hash_(chan_circid_circuit_map_t *a) { - return (((unsigned)a->circ_id)<<8) ^ (unsigned)(uintptr_t)(a->or_conn); + return ((unsigned)a->circ_id) ^ (unsigned)(uintptr_t)(a->chan); } -/** Map from [orconn,circid] to circuit. */ -static HT_HEAD(orconn_circid_map, orconn_circid_circuit_map_t) - orconn_circid_circuit_map = HT_INITIALIZER(); -HT_PROTOTYPE(orconn_circid_map, orconn_circid_circuit_map_t, node, - _orconn_circid_entry_hash, _orconn_circid_entries_eq) -HT_GENERATE(orconn_circid_map, orconn_circid_circuit_map_t, node, - _orconn_circid_entry_hash, _orconn_circid_entries_eq, 0.6, +/** Map from [chan,circid] to circuit. */ +static HT_HEAD(chan_circid_map, chan_circid_circuit_map_t) + chan_circid_map = HT_INITIALIZER(); +HT_PROTOTYPE(chan_circid_map, chan_circid_circuit_map_t, node, + chan_circid_entry_hash_, chan_circid_entries_eq_) +HT_GENERATE(chan_circid_map, chan_circid_circuit_map_t, node, + chan_circid_entry_hash_, chan_circid_entries_eq_, 0.6, malloc, realloc, free) -/** The most recently returned entry from circuit_get_by_circid_orconn; +/** The most recently returned entry from circuit_get_by_circid_chan; * used to improve performance when many cells arrive in a row from the * same circuit. */ -orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL; +chan_circid_circuit_map_t *_last_circid_chan_ent = NULL; -/** Implementation helper for circuit_set_{p,n}_circid_orconn: A circuit ID - * and/or or_connection for circ has just changed from <b>old_conn, old_id</b> - * to <b>conn, id</b>. Adjust the conn,circid map as appropriate, removing +/** Implementation helper for circuit_set_{p,n}_circid_channel: A circuit ID + * and/or channel for circ has just changed from <b>old_chan, old_id</b> + * to <b>chan, id</b>. Adjust the chan,circid map as appropriate, removing * the old entry (if any) and adding a new one. */ static void -circuit_set_circid_orconn_helper(circuit_t *circ, int direction, - circid_t id, - or_connection_t *conn) +circuit_set_circid_chan_helper(circuit_t *circ, int direction, + circid_t id, + channel_t *chan) { - orconn_circid_circuit_map_t search; - orconn_circid_circuit_map_t *found; - or_connection_t *old_conn, **conn_ptr; + chan_circid_circuit_map_t search; + chan_circid_circuit_map_t *found; + channel_t *old_chan, **chan_ptr; circid_t old_id, *circid_ptr; - int was_active, make_active; + int make_active, attached = 0; if (direction == CELL_DIRECTION_OUT) { - conn_ptr = &circ->n_conn; + chan_ptr = &circ->n_chan; circid_ptr = &circ->n_circ_id; - was_active = circ->next_active_on_n_conn != NULL; - make_active = circ->n_conn_cells.n > 0; + make_active = circ->n_chan_cells.n > 0; } else { or_circuit_t *c = TO_OR_CIRCUIT(circ); - conn_ptr = &c->p_conn; + chan_ptr = &c->p_chan; circid_ptr = &c->p_circ_id; - was_active = c->next_active_on_p_conn != NULL; - make_active = c->p_conn_cells.n > 0; + make_active = c->p_chan_cells.n > 0; } - old_conn = *conn_ptr; + old_chan = *chan_ptr; old_id = *circid_ptr; - if (id == old_id && conn == old_conn) + if (id == old_id && chan == old_chan) return; - if (_last_circid_orconn_ent && - ((old_id == _last_circid_orconn_ent->circ_id && - old_conn == _last_circid_orconn_ent->or_conn) || - (id == _last_circid_orconn_ent->circ_id && - conn == _last_circid_orconn_ent->or_conn))) { - _last_circid_orconn_ent = NULL; + if (_last_circid_chan_ent && + ((old_id == _last_circid_chan_ent->circ_id && + old_chan == _last_circid_chan_ent->chan) || + (id == _last_circid_chan_ent->circ_id && + chan == _last_circid_chan_ent->chan))) { + _last_circid_chan_ent = NULL; } - if (old_conn) { /* we may need to remove it from the conn-circid map */ - tor_assert(old_conn->_base.magic == OR_CONNECTION_MAGIC); + if (old_chan) { + /* + * If we're changing channels or ID and had an old channel and a non + * zero old ID and weren't marked for close (i.e., we should have been + * attached), detach the circuit. ID changes require this because + * circuitmux hashes on (channel_id, circuit_id). + */ + if (old_id != 0 && (old_chan != chan || old_id != id) && + !(circ->marked_for_close)) { + tor_assert(old_chan->cmux); + circuitmux_detach_circuit(old_chan->cmux, circ); + } + + /* we may need to remove it from the conn-circid map */ search.circ_id = old_id; - search.or_conn = old_conn; - found = HT_REMOVE(orconn_circid_map, &orconn_circid_circuit_map, &search); + search.chan = old_chan; + found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search); if (found) { tor_free(found); - --old_conn->n_circuits; + if (direction == CELL_DIRECTION_OUT) { + /* One fewer circuits use old_chan as n_chan */ + --(old_chan->num_n_circuits); + } else { + /* One fewer circuits use old_chan as p_chan */ + --(old_chan->num_p_circuits); + } } - if (was_active && old_conn != conn) - make_circuit_inactive_on_conn(circ,old_conn); } /* Change the values only after we have possibly made the circuit inactive - * on the previous conn. */ - *conn_ptr = conn; + * on the previous chan. */ + *chan_ptr = chan; *circid_ptr = id; - if (conn == NULL) + if (chan == NULL) return; /* now add the new one to the conn-circid map */ search.circ_id = id; - search.or_conn = conn; - found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search); + search.chan = chan; + found = HT_FIND(chan_circid_map, &chan_circid_map, &search); if (found) { found->circuit = circ; } else { - found = tor_malloc_zero(sizeof(orconn_circid_circuit_map_t)); + found = tor_malloc_zero(sizeof(chan_circid_circuit_map_t)); found->circ_id = id; - found->or_conn = conn; + found->chan = chan; found->circuit = circ; - HT_INSERT(orconn_circid_map, &orconn_circid_circuit_map, found); + HT_INSERT(chan_circid_map, &chan_circid_map, found); + } + + /* + * Attach to the circuitmux if we're changing channels or IDs and + * have a new channel and ID to use and the circuit is not marked for + * close. + */ + if (chan && id != 0 && (old_chan != chan || old_id != id) && + !(circ->marked_for_close)) { + tor_assert(chan->cmux); + circuitmux_attach_circuit(chan->cmux, circ, direction); + attached = 1; } - if (make_active && old_conn != conn) - make_circuit_active_on_conn(circ,conn); - ++conn->n_circuits; + /* + * This is a no-op if we have no cells, but if we do it marks us active to + * the circuitmux + */ + if (make_active && attached) + update_circuit_on_cmux(circ, direction); + + /* Adjust circuit counts on new channel */ + if (direction == CELL_DIRECTION_OUT) { + ++chan->num_n_circuits; + } else { + ++chan->num_p_circuits; + } } /** Set the p_conn field of a circuit <b>circ</b>, along * with the corresponding circuit ID, and add the circuit as appropriate - * to the (orconn,id)-\>circuit map. */ + * to the (chan,id)-\>circuit map. */ void -circuit_set_p_circid_orconn(or_circuit_t *circ, circid_t id, - or_connection_t *conn) +circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id, + channel_t *chan) { - circuit_set_circid_orconn_helper(TO_CIRCUIT(circ), CELL_DIRECTION_IN, - id, conn); + circuit_set_circid_chan_helper(TO_CIRCUIT(circ), CELL_DIRECTION_IN, + id, chan); - if (conn) - tor_assert(bool_eq(circ->p_conn_cells.n, circ->next_active_on_p_conn)); + if (chan) + tor_assert(bool_eq(circ->p_chan_cells.n, circ->next_active_on_p_chan)); } /** Set the n_conn field of a circuit <b>circ</b>, along * with the corresponding circuit ID, and add the circuit as appropriate - * to the (orconn,id)-\>circuit map. */ + * to the (chan,id)-\>circuit map. */ void -circuit_set_n_circid_orconn(circuit_t *circ, circid_t id, - or_connection_t *conn) +circuit_set_n_circid_chan(circuit_t *circ, circid_t id, + channel_t *chan) { - circuit_set_circid_orconn_helper(circ, CELL_DIRECTION_OUT, id, conn); + circuit_set_circid_chan_helper(circ, CELL_DIRECTION_OUT, id, chan); - if (conn) - tor_assert(bool_eq(circ->n_conn_cells.n, circ->next_active_on_n_conn)); + if (chan) + tor_assert(bool_eq(circ->n_chan_cells.n, circ->next_active_on_n_chan)); } /** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing @@ -201,18 +242,18 @@ circuit_set_state(circuit_t *circ, uint8_t state) tor_assert(circ); if (state == circ->state) return; - if (!circuits_pending_or_conns) - circuits_pending_or_conns = smartlist_new(); - if (circ->state == CIRCUIT_STATE_OR_WAIT) { + if (!circuits_pending_chans) + circuits_pending_chans = smartlist_new(); + if (circ->state == CIRCUIT_STATE_CHAN_WAIT) { /* remove from waiting-circuit list. */ - smartlist_remove(circuits_pending_or_conns, circ); + smartlist_remove(circuits_pending_chans, circ); } - if (state == CIRCUIT_STATE_OR_WAIT) { + if (state == CIRCUIT_STATE_CHAN_WAIT) { /* add to waiting-circuit list. */ - smartlist_add(circuits_pending_or_conns, circ); + smartlist_add(circuits_pending_chans, circ); } if (state == CIRCUIT_STATE_OPEN) - tor_assert(!circ->n_conn_onionskin); + tor_assert(!circ->n_chan_create_cell); circ->state = state; } @@ -231,51 +272,53 @@ circuit_add(circuit_t *circ) } } -/** Append to <b>out</b> all circuits in state OR_WAIT waiting for +/** Append to <b>out</b> all circuits in state CHAN_WAIT waiting for * the given connection. */ void -circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn) +circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan) { tor_assert(out); - tor_assert(or_conn); + tor_assert(chan); - if (!circuits_pending_or_conns) + if (!circuits_pending_chans) return; - SMARTLIST_FOREACH_BEGIN(circuits_pending_or_conns, circuit_t *, circ) { + SMARTLIST_FOREACH_BEGIN(circuits_pending_chans, circuit_t *, circ) { if (circ->marked_for_close) continue; if (!circ->n_hop) continue; - tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT); + tor_assert(circ->state == CIRCUIT_STATE_CHAN_WAIT); if (tor_digest_is_zero(circ->n_hop->identity_digest)) { /* Look at addr/port. This is an unkeyed connection. */ - if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) || - circ->n_hop->port != or_conn->_base.port) + if (!channel_matches_extend_info(chan, circ->n_hop)) continue; } else { /* We expected a key. See if it's the right one. */ - if (tor_memneq(or_conn->identity_digest, - circ->n_hop->identity_digest, DIGEST_LEN)) + if (tor_memneq(chan->identity_digest, + circ->n_hop->identity_digest, DIGEST_LEN)) continue; } smartlist_add(out, circ); } SMARTLIST_FOREACH_END(circ); } -/** Return the number of circuits in state OR_WAIT, waiting for the given - * connection. */ +/** Return the number of circuits in state CHAN_WAIT, waiting for the given + * channel. */ int -circuit_count_pending_on_or_conn(or_connection_t *or_conn) +circuit_count_pending_on_channel(channel_t *chan) { int cnt; smartlist_t *sl = smartlist_new(); - circuit_get_all_pending_on_or_conn(sl, or_conn); + + tor_assert(chan); + + circuit_get_all_pending_on_channel(sl, chan); cnt = smartlist_len(sl); smartlist_free(sl); log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs", - or_conn->nickname ? or_conn->nickname : "NULL", - or_conn->_base.address, + chan->nickname ? chan->nickname : "NULL", + channel_get_canonical_remote_descr(chan), cnt); return cnt; } @@ -310,7 +353,7 @@ circuit_close_all_marked(void) /** Return the head of the global linked list of circuits. */ circuit_t * -_circuit_get_global_list(void) +circuit_get_global_list_(void) { return global_circuitlist; } @@ -323,7 +366,7 @@ circuit_state_to_string(int state) switch (state) { case CIRCUIT_STATE_BUILDING: return "doing handshakes"; case CIRCUIT_STATE_ONIONSKIN_PENDING: return "processing the onion"; - case CIRCUIT_STATE_OR_WAIT: return "connecting to server"; + case CIRCUIT_STATE_CHAN_WAIT: return "connecting to server"; case CIRCUIT_STATE_OPEN: return "open"; default: log_warn(LD_BUG, "Unknown circuit state %d", state); @@ -372,6 +415,8 @@ circuit_purpose_to_controller_string(uint8_t purpose) return "MEASURE_TIMEOUT"; case CIRCUIT_PURPOSE_CONTROLLER: return "CONTROLLER"; + case CIRCUIT_PURPOSE_PATH_BIAS_TESTING: + return "PATH_BIAS_TESTING"; default: tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose); @@ -399,6 +444,7 @@ circuit_purpose_to_controller_hs_state_string(uint8_t purpose) case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT: case CIRCUIT_PURPOSE_TESTING: case CIRCUIT_PURPOSE_CONTROLLER: + case CIRCUIT_PURPOSE_PATH_BIAS_TESTING: return NULL; case CIRCUIT_PURPOSE_INTRO_POINT: @@ -486,6 +532,9 @@ circuit_purpose_to_string(uint8_t purpose) case CIRCUIT_PURPOSE_CONTROLLER: return "Circuit made by controller"; + case CIRCUIT_PURPOSE_PATH_BIAS_TESTING: + return "Path-bias testing circuit"; + default: tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose); return buf; @@ -514,15 +563,14 @@ init_circuit_base(circuit_t *circ) { tor_gettimeofday(&circ->timestamp_created); + // Gets reset when we send CREATE_FAST. + // circuit_expire_building() expects these to be equal + // until the orconn is built. + circ->timestamp_began = circ->timestamp_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); } @@ -538,7 +586,7 @@ origin_circuit_new(void) static uint32_t n_circuits_allocated = 1; circ = tor_malloc_zero(sizeof(origin_circuit_t)); - circ->_base.magic = ORIGIN_CIRCUIT_MAGIC; + circ->base_.magic = ORIGIN_CIRCUIT_MAGIC; circ->next_stream_id = crypto_rand_int(1<<16); circ->global_identifier = n_circuits_allocated++; @@ -555,31 +603,21 @@ origin_circuit_new(void) /** Allocate a new or_circuit_t, connected to <b>p_conn</b> as * <b>p_circ_id</b>. If <b>p_conn</b> is NULL, the circuit is unattached. */ or_circuit_t * -or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn) +or_circuit_new(circid_t p_circ_id, channel_t *p_chan) { /* CircIDs */ or_circuit_t *circ; circ = tor_malloc_zero(sizeof(or_circuit_t)); - circ->_base.magic = OR_CIRCUIT_MAGIC; + circ->base_.magic = OR_CIRCUIT_MAGIC; - if (p_conn) - circuit_set_p_circid_orconn(circ, p_circ_id, p_conn); + if (p_chan) + circuit_set_p_circid_chan(circ, p_circ_id, p_chan); circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT; 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; } @@ -619,6 +657,7 @@ circuit_free(circuit_t *circ) memwipe(ocirc->socks_password, 0x06, ocirc->socks_password_len); tor_free(ocirc->socks_password); } + addr_policy_list_free(ocirc->prepend_policy); } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); /* Remember cell statistics for this circuit before deallocating. */ @@ -635,27 +674,27 @@ circuit_free(circuit_t *circ) if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; - tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC); + tor_assert(other->base_.magic == OR_CIRCUIT_MAGIC); other->rend_splice = NULL; } /* remove from map. */ - circuit_set_p_circid_orconn(ocirc, 0, NULL); + circuit_set_p_circid_chan(ocirc, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ - cell_queue_clear(ô->p_conn_cells); + cell_queue_clear(ô->p_chan_cells); } extend_info_free(circ->n_hop); - tor_free(circ->n_conn_onionskin); + tor_free(circ->n_chan_create_cell); /* Remove from map. */ - circuit_set_n_circid_orconn(circ, 0, NULL); + circuit_set_n_circid_chan(circ, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ - cell_queue_clear(&circ->n_conn_cells); + cell_queue_clear(&circ->n_chan_cells); memwipe(mem, 0xAA, memlen); /* poison memory */ tor_free(mem); @@ -670,7 +709,7 @@ circuit_free_cpath(crypt_path_t *cpath) if (!cpath) return; - /* it's a doubly linked list, so we have to notice when we've + /* it's a circular list, so we have to notice when we've * gone through it once. */ while (cpath->next && cpath->next != head) { victim = cpath; @@ -681,6 +720,14 @@ circuit_free_cpath(crypt_path_t *cpath) circuit_free_cpath_node(cpath); } +/** Remove all the items in the cpath on <b>circ</b>.*/ +void +circuit_clear_cpath(origin_circuit_t *circ) +{ + circuit_free_cpath(circ->cpath); + circ->cpath = NULL; +} + /** Release all storage held by circuits. */ void circuit_free_all(void) @@ -701,10 +748,10 @@ circuit_free_all(void) global_circuitlist = next; } - smartlist_free(circuits_pending_or_conns); - circuits_pending_or_conns = NULL; + smartlist_free(circuits_pending_chans); + circuits_pending_chans = NULL; - HT_CLEAR(orconn_circid_map, &orconn_circid_circuit_map); + HT_CLEAR(chan_circid_map, &chan_circid_map); } /** Deallocate space associated with the cpath node <b>victim</b>. */ @@ -718,7 +765,8 @@ circuit_free_cpath_node(crypt_path_t *victim) crypto_cipher_free(victim->b_crypto); crypto_digest_free(victim->f_digest); crypto_digest_free(victim->b_digest); - crypto_dh_free(victim->dh_handshake_state); + onion_handshake_state_release(&victim->handshake_state); + crypto_dh_free(victim->rend_dh_handshake_state); extend_info_free(victim->extend_info); memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */ @@ -741,14 +789,18 @@ cpath_ref_decref(crypt_path_reference_t *cpath_ref) * of information about circuit <b>circ</b>. */ static void -circuit_dump_details(int severity, circuit_t *circ, int conn_array_index, - const char *type, int this_circid, int other_circid) +circuit_dump_conn_details(int severity, + circuit_t *circ, + int conn_array_index, + const char *type, + circid_t this_circid, + circid_t other_circid) { - log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), " - "state %d (%s), born %ld:", - conn_array_index, type, this_circid, other_circid, circ->state, - circuit_state_to_string(circ->state), - (long)circ->timestamp_created.tv_sec); + tor_log(severity, LD_CIRC, "Conn %d has %s circuit: circID %u " + "(other side %u), state %d (%s), born %ld:", + conn_array_index, type, (unsigned)this_circid, (unsigned)other_circid, + circ->state, circuit_state_to_string(circ->state), + (long)circ->timestamp_began.tv_sec); if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */ circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ)); } @@ -763,50 +815,101 @@ circuit_dump_by_conn(connection_t *conn, int severity) circuit_t *circ; edge_connection_t *tmpconn; - for (circ=global_circuitlist;circ;circ = circ->next) { + for (circ = global_circuitlist; circ; circ = circ->next) { circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0; - if (circ->marked_for_close) + + if (circ->marked_for_close) { continue; + } - if (! CIRCUIT_IS_ORIGIN(circ)) + if (!CIRCUIT_IS_ORIGIN(circ)) { p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; + } - if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_conn && - TO_CONN(TO_OR_CIRCUIT(circ)->p_conn) == conn) - circuit_dump_details(severity, circ, conn->conn_array_index, "App-ward", - p_circ_id, n_circ_id); if (CIRCUIT_IS_ORIGIN(circ)) { for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn; tmpconn=tmpconn->next_stream) { if (TO_CONN(tmpconn) == conn) { - circuit_dump_details(severity, circ, conn->conn_array_index, - "App-ward", p_circ_id, n_circ_id); + circuit_dump_conn_details(severity, circ, conn->conn_array_index, + "App-ward", p_circ_id, n_circ_id); } } } - if (circ->n_conn && TO_CONN(circ->n_conn) == conn) - circuit_dump_details(severity, circ, conn->conn_array_index, "Exit-ward", - n_circ_id, p_circ_id); + if (! CIRCUIT_IS_ORIGIN(circ)) { for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn; tmpconn=tmpconn->next_stream) { if (TO_CONN(tmpconn) == conn) { - circuit_dump_details(severity, circ, conn->conn_array_index, - "Exit-ward", n_circ_id, p_circ_id); + circuit_dump_conn_details(severity, circ, conn->conn_array_index, + "Exit-ward", n_circ_id, p_circ_id); } } } - if (!circ->n_conn && circ->n_hop && - tor_addr_eq(&circ->n_hop->addr, &conn->addr) && - circ->n_hop->port == conn->port && - conn->type == CONN_TYPE_OR && - tor_memeq(TO_OR_CONN(conn)->identity_digest, - circ->n_hop->identity_digest, DIGEST_LEN)) { - circuit_dump_details(severity, circ, conn->conn_array_index, - (circ->state == CIRCUIT_STATE_OPEN && - !CIRCUIT_IS_ORIGIN(circ)) ? - "Endpoint" : "Pending", - n_circ_id, p_circ_id); + } +} + +/** A helper function for circuit_dump_by_chan() below. Log a bunch + * of information about circuit <b>circ</b>. + */ +static void +circuit_dump_chan_details(int severity, + circuit_t *circ, + channel_t *chan, + const char *type, + circid_t this_circid, + circid_t other_circid) +{ + tor_log(severity, LD_CIRC, "Conn %p has %s circuit: circID %u " + "(other side %u), state %d (%s), born %ld:", + chan, type, (unsigned)this_circid, (unsigned)other_circid, circ->state, + circuit_state_to_string(circ->state), + (long)circ->timestamp_began.tv_sec); + if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */ + circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ)); + } +} + +/** Log, at severity <b>severity</b>, information about each circuit + * that is connected to <b>chan</b>. + */ +void +circuit_dump_by_chan(channel_t *chan, int severity) +{ + circuit_t *circ; + + tor_assert(chan); + + for (circ = global_circuitlist; circ; circ = circ->next) { + circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0; + + if (circ->marked_for_close) { + continue; + } + + if (!CIRCUIT_IS_ORIGIN(circ)) { + p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; + } + + if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_chan && + TO_OR_CIRCUIT(circ)->p_chan == chan) { + circuit_dump_chan_details(severity, circ, chan, "App-ward", + p_circ_id, n_circ_id); + } + + if (circ->n_chan && circ->n_chan == chan) { + circuit_dump_chan_details(severity, circ, chan, "Exit-ward", + n_circ_id, p_circ_id); + } + + if (!circ->n_chan && circ->n_hop && + channel_matches_extend_info(chan, circ->n_hop) && + tor_memeq(chan->identity_digest, + circ->n_hop->identity_digest, DIGEST_LEN)) { + circuit_dump_chan_details(severity, circ, chan, + (circ->state == CIRCUIT_STATE_OPEN && + !CIRCUIT_IS_ORIGIN(circ)) ? + "Endpoint" : "Pending", + n_circ_id, p_circ_id); } } } @@ -831,27 +934,39 @@ circuit_get_by_global_id(uint32_t id) /** Return a circ such that: * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and - * - circ is attached to <b>conn</b>, either as p_conn or n_conn. + * - circ is attached to <b>chan</b>, either as p_chan or n_chan. * Return NULL if no such circuit exists. */ static INLINE circuit_t * -circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn) +circuit_get_by_circid_channel_impl(circid_t circ_id, channel_t *chan) { - orconn_circid_circuit_map_t search; - orconn_circid_circuit_map_t *found; + chan_circid_circuit_map_t search; + chan_circid_circuit_map_t *found; - if (_last_circid_orconn_ent && - circ_id == _last_circid_orconn_ent->circ_id && - conn == _last_circid_orconn_ent->or_conn) { - found = _last_circid_orconn_ent; + if (_last_circid_chan_ent && + circ_id == _last_circid_chan_ent->circ_id && + chan == _last_circid_chan_ent->chan) { + found = _last_circid_chan_ent; } else { search.circ_id = circ_id; - search.or_conn = conn; - found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search); - _last_circid_orconn_ent = found; + search.chan = chan; + found = HT_FIND(chan_circid_map, &chan_circid_map, &search); + _last_circid_chan_ent = found; } - if (found && found->circuit) + if (found && found->circuit) { + log_debug(LD_CIRC, + "circuit_get_by_circid_channel_impl() returning circuit %p for" + " circ_id %u, channel ID " U64_FORMAT " (%p)", + found->circuit, (unsigned)circ_id, + U64_PRINTF_ARG(chan->global_identifier), chan); return found->circuit; + } + + log_debug(LD_CIRC, + "circuit_get_by_circid_channel_impl() found nothing for" + " circ_id %u, channel ID " U64_FORMAT " (%p)", + (unsigned)circ_id, + U64_PRINTF_ARG(chan->global_identifier), chan); return NULL; /* The rest of this checks for bugs. Disabled by default. */ @@ -861,15 +976,15 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn) for (circ=global_circuitlist;circ;circ = circ->next) { if (! CIRCUIT_IS_ORIGIN(circ)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); - if (or_circ->p_conn == conn && or_circ->p_circ_id == circ_id) { + if (or_circ->p_chan == chan && or_circ->p_circ_id == circ_id) { log_warn(LD_BUG, - "circuit matches p_conn, but not in hash table (Bug!)"); + "circuit matches p_chan, but not in hash table (Bug!)"); return circ; } } - if (circ->n_conn == conn && circ->n_circ_id == circ_id) { + if (circ->n_chan == chan && circ->n_circ_id == circ_id) { log_warn(LD_BUG, - "circuit matches n_conn, but not in hash table (Bug!)"); + "circuit matches n_chan, but not in hash table (Bug!)"); return circ; } } @@ -879,26 +994,38 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn) /** Return a circ such that: * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and - * - circ is attached to <b>conn</b>, either as p_conn or n_conn. + * - circ is attached to <b>chan</b>, either as p_chan or n_chan. * - circ is not marked for close. * Return NULL if no such circuit exists. */ circuit_t * -circuit_get_by_circid_orconn(circid_t circ_id, or_connection_t *conn) +circuit_get_by_circid_channel(circid_t circ_id, channel_t *chan) { - circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn); + circuit_t *circ = circuit_get_by_circid_channel_impl(circ_id, chan); if (!circ || circ->marked_for_close) return NULL; else return circ; } +/** Return a circ such that: + * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and + * - circ is attached to <b>chan</b>, either as p_chan or n_chan. + * Return NULL if no such circuit exists. + */ +circuit_t * +circuit_get_by_circid_channel_even_if_marked(circid_t circ_id, + channel_t *chan) +{ + return circuit_get_by_circid_channel_impl(circ_id, chan); +} + /** Return true iff the circuit ID <b>circ_id</b> is currently used by a - * circuit, marked or not, on <b>conn</b>. */ + * circuit, marked or not, on <b>chan</b>. */ int -circuit_id_in_use_on_orconn(circid_t circ_id, or_connection_t *conn) +circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan) { - return circuit_get_by_circid_orconn_impl(circ_id, conn) != NULL; + return circuit_get_by_circid_channel_impl(circ_id, chan) != NULL; } /** Return the circuit that a given edge connection is using. */ @@ -915,27 +1042,32 @@ circuit_get_by_edge_conn(edge_connection_t *conn) return circ; } -/** For each circuit that has <b>conn</b> as n_conn or p_conn, unlink the - * circuit from the orconn,circid map, and mark it for close if it hasn't +/** For each circuit that has <b>chan</b> as n_chan or p_chan, unlink the + * circuit from the chan,circid map, and mark it for close if it hasn't * been marked already. */ void -circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason) +circuit_unlink_all_from_channel(channel_t *chan, int reason) { circuit_t *circ; - connection_or_unlink_all_active_circs(conn); + channel_unlink_all_circuits(chan); for (circ = global_circuitlist; circ; circ = circ->next) { int mark = 0; - if (circ->n_conn == conn) { - circuit_set_n_circid_orconn(circ, 0, NULL); - mark = 1; + if (circ->n_chan == chan) { + circuit_set_n_circid_chan(circ, 0, NULL); + mark = 1; + + /* If we didn't request this closure, pass the remote + * bit to mark_for_close. */ + if (chan->reason_for_closing != CHANNEL_CLOSE_REQUESTED) + reason |= END_CIRC_REASON_FLAG_REMOTE; } if (! CIRCUIT_IS_ORIGIN(circ)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); - if (or_circ->p_conn == conn) { - circuit_set_p_circid_orconn(or_circ, 0, NULL); + if (or_circ->p_chan == chan) { + circuit_set_p_circid_chan(or_circ, 0, NULL); mark = 1; } } @@ -1059,7 +1191,7 @@ origin_circuit_t * circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int flags) { - circuit_t *_circ; + circuit_t *circ_; origin_circuit_t *best=NULL; int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0; int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0; @@ -1075,16 +1207,17 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, "capacity %d, internal %d", purpose, need_uptime, need_capacity, internal); - for (_circ=global_circuitlist; _circ; _circ = _circ->next) { - if (CIRCUIT_IS_ORIGIN(_circ) && - _circ->state == CIRCUIT_STATE_OPEN && - !_circ->marked_for_close && - _circ->purpose == CIRCUIT_PURPOSE_C_GENERAL && - !_circ->timestamp_dirty) { - origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(_circ); + for (circ_=global_circuitlist; circ_; circ_ = circ_->next) { + if (CIRCUIT_IS_ORIGIN(circ_) && + circ_->state == CIRCUIT_STATE_OPEN && + !circ_->marked_for_close && + circ_->purpose == CIRCUIT_PURPOSE_C_GENERAL && + !circ_->timestamp_dirty) { + origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(circ_); if ((!need_uptime || circ->build_state->need_uptime) && (!need_capacity || circ->build_state->need_capacity) && (internal == circ->build_state->is_internal) && + !circ->unusable_for_new_conns && circ->remaining_relay_early_cells && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN && !circ->build_state->onehop_tunnel && @@ -1180,20 +1313,17 @@ circuit_mark_all_unused_circs(void) * This is useful for letting the user change pseudonyms, so new * streams will not be linkable to old streams. */ -/* XXX024 this is a bad name for what this function does */ void -circuit_expire_all_dirty_circs(void) +circuit_mark_all_dirty_circs_as_unusable(void) { circuit_t *circ; - const or_options_t *options = get_options(); for (circ=global_circuitlist; circ; circ = circ->next) { if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && - circ->timestamp_dirty) - /* XXXX024 This is a screwed-up way to say "This is too dirty - * for new circuits. */ - circ->timestamp_dirty -= options->MaxCircuitDirtiness; + circ->timestamp_dirty) { + mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ)); + } } } @@ -1215,7 +1345,7 @@ circuit_expire_all_dirty_circs(void) * rendezvous stream), then mark the other circuit to close as well. */ void -_circuit_mark_for_close(circuit_t *circ, int reason, int line, +circuit_mark_for_close_(circuit_t *circ, int reason, int line, const char *file) { int orig_reason = reason; /* Passed to the controller */ @@ -1224,7 +1354,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, tor_assert(file); if (circ->marked_for_close) { - log(LOG_WARN,LD_BUG, + log_warn(LD_BUG, "Duplicate call to circuit_mark_for_close at %s:%d" " (first at %s:%d)", file, line, circ->marked_for_close_file, circ->marked_for_close); @@ -1238,7 +1368,13 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, } reason = END_CIRC_REASON_NONE; } + if (CIRCUIT_IS_ORIGIN(circ)) { + if (pathbias_check_close(TO_ORIGIN_CIRCUIT(circ), reason) == -1) { + /* Don't close it yet, we need to test it first */ + return; + } + /* We don't send reasons when closing circuits at the origin. */ reason = END_CIRC_REASON_NONE; } @@ -1246,7 +1382,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, if (reason & END_CIRC_REASON_FLAG_REMOTE) reason &= ~END_CIRC_REASON_FLAG_REMOTE; - if (reason < _END_CIRC_REASON_MIN || reason > _END_CIRC_REASON_MAX) { + if (reason < END_CIRC_REASON_MIN_ || reason > END_CIRC_REASON_MAX_) { if (!(orig_reason & END_CIRC_REASON_FLAG_REMOTE)) log_warn(LD_BUG, "Reason %d out of range at %s:%d", reason, file, line); reason = END_CIRC_REASON_NONE; @@ -1266,9 +1402,9 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, circuit_rep_hist_note_result(ocirc); } } - if (circ->state == CIRCUIT_STATE_OR_WAIT) { - if (circuits_pending_or_conns) - smartlist_remove(circuits_pending_or_conns, circ); + if (circ->state == CIRCUIT_STATE_CHAN_WAIT) { + if (circuits_pending_chans) + smartlist_remove(circuits_pending_chans, circ); } if (CIRCUIT_IS_ORIGIN(circ)) { control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ), @@ -1305,9 +1441,15 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, INTRO_POINT_FAILURE_UNREACHABLE); } } - 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 (circ->n_chan) { + circuit_clear_cell_queue(circ, circ->n_chan); + /* Only send destroy if the channel isn't closing anyway */ + if (!(circ->n_chan->state == CHANNEL_STATE_CLOSING || + circ->n_chan->state == CHANNEL_STATE_CLOSED || + circ->n_chan->state == CHANNEL_STATE_ERROR)) { + channel_send_destroy(circ->n_circ_id, circ->n_chan, reason); + } + circuitmux_detach_circuit(circ->n_chan->cmux, circ); } if (! CIRCUIT_IS_ORIGIN(circ)) { @@ -1320,7 +1462,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, while (or_circ->resolving_streams) { conn = or_circ->resolving_streams; or_circ->resolving_streams = conn->next_stream; - if (!conn->_base.marked_for_close) { + if (!conn->base_.marked_for_close) { /* The client will see a DESTROY, and infer that the connections * are closing because the circuit is getting torn down. No need * to send an end cell. */ @@ -1332,9 +1474,15 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, conn->on_circuit = NULL; } - 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); + if (or_circ->p_chan) { + circuit_clear_cell_queue(circ, or_circ->p_chan); + /* Only send destroy if the channel isn't closing anyway */ + if (!(or_circ->p_chan->state == CHANNEL_STATE_CLOSING || + or_circ->p_chan->state == CHANNEL_STATE_CLOSED || + or_circ->p_chan->state == CHANNEL_STATE_ERROR)) { + channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason); + } + circuitmux_detach_circuit(or_circ->p_chan->cmux, circ); } } else { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); @@ -1350,7 +1498,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, if (!CIRCUIT_IS_ORIGIN(circ)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); if (or_circ->rend_splice) { - if (!or_circ->rend_splice->_base.marked_for_close) { + if (!or_circ->rend_splice->base_.marked_for_close) { /* do this after marking this circuit, to avoid infinite recursion. */ circuit_mark_for_close(TO_CIRCUIT(or_circ->rend_splice), reason); } @@ -1368,18 +1516,20 @@ marked_circuit_free_cells(circuit_t *circ) log_warn(LD_BUG, "Called on non-marked circuit"); return; } - cell_queue_clear(&circ->n_conn_cells); + cell_queue_clear(&circ->n_chan_cells); if (! CIRCUIT_IS_ORIGIN(circ)) - cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_conn_cells); + cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_chan_cells); } /** Return the number of cells used by the circuit <b>c</b>'s cell queues. */ static size_t n_cells_in_circ_queues(const circuit_t *c) { - size_t n = c->n_conn_cells.n; - if (! CIRCUIT_IS_ORIGIN(c)) - n += TO_OR_CIRCUIT((circuit_t*)c)->p_conn_cells.n; + size_t n = c->n_chan_cells.n; + if (! CIRCUIT_IS_ORIGIN(c)) { + circuit_t *cc = (circuit_t *) c; + n += TO_OR_CIRCUIT(cc)->p_chan_cells.n; + } return n; } @@ -1395,13 +1545,13 @@ static uint32_t circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) { uint32_t age = 0; - if (c->n_conn_cells.head) - age = now - c->n_conn_cells.head->inserted_time; + if (c->n_chan_cells.head) + age = now - c->n_chan_cells.head->inserted_time; if (! CIRCUIT_IS_ORIGIN(c)) { const or_circuit_t *orcirc = TO_OR_CIRCUIT((circuit_t*)c); - if (orcirc->p_conn_cells.head) { - uint32_t age2 = now - orcirc->p_conn_cells.head->inserted_time; + if (orcirc->p_chan_cells.head) { + uint32_t age2 = now - orcirc->p_chan_cells.head->inserted_time; if (age2 > age) return age2; } @@ -1514,7 +1664,8 @@ assert_cpath_layer_ok(const crypt_path_t *cp) tor_assert(cp->b_crypto); /* fall through */ case CPATH_STATE_CLOSED: - tor_assert(!cp->dh_handshake_state); + /*XXXX Assert that there's no handshake_state either. */ + tor_assert(!cp->rend_dh_handshake_state); break; case CPATH_STATE_AWAITING_KEYS: /* tor_assert(cp->dh_handshake_state); */ @@ -1562,8 +1713,8 @@ assert_circuit_ok(const circuit_t *c) tor_assert(c); tor_assert(c->magic == ORIGIN_CIRCUIT_MAGIC || c->magic == OR_CIRCUIT_MAGIC); - tor_assert(c->purpose >= _CIRCUIT_PURPOSE_MIN && - c->purpose <= _CIRCUIT_PURPOSE_MAX); + tor_assert(c->purpose >= CIRCUIT_PURPOSE_MIN_ && + c->purpose <= CIRCUIT_PURPOSE_MAX_); { /* Having a separate variable for this pleases GCC 4.2 in ways I hope I @@ -1575,33 +1726,33 @@ assert_circuit_ok(const circuit_t *c) or_circ = TO_OR_CIRCUIT(nonconst_circ); } - if (c->n_conn) { + if (c->n_chan) { tor_assert(!c->n_hop); if (c->n_circ_id) { /* We use the _impl variant here to make sure we don't fail on marked * circuits, which would not be returned by the regular function. */ - circuit_t *c2 = circuit_get_by_circid_orconn_impl(c->n_circ_id, - c->n_conn); + circuit_t *c2 = circuit_get_by_circid_channel_impl(c->n_circ_id, + c->n_chan); tor_assert(c == c2); } } - if (or_circ && or_circ->p_conn) { + if (or_circ && or_circ->p_chan) { if (or_circ->p_circ_id) { /* ibid */ - circuit_t *c2 = circuit_get_by_circid_orconn_impl(or_circ->p_circ_id, - or_circ->p_conn); + circuit_t *c2 = circuit_get_by_circid_channel_impl(or_circ->p_circ_id, + or_circ->p_chan); tor_assert(c == c2); } } if (or_circ) for (conn = or_circ->n_streams; conn; conn = conn->next_stream) - tor_assert(conn->_base.type == CONN_TYPE_EXIT); + tor_assert(conn->base_.type == CONN_TYPE_EXIT); tor_assert(c->deliver_window >= 0); tor_assert(c->package_window >= 0); if (c->state == CIRCUIT_STATE_OPEN) { - tor_assert(!c->n_conn_onionskin); + tor_assert(!c->n_chan_create_cell); if (or_circ) { tor_assert(or_circ->n_crypto); tor_assert(or_circ->p_crypto); @@ -1609,12 +1760,12 @@ assert_circuit_ok(const circuit_t *c) tor_assert(or_circ->p_digest); } } - if (c->state == CIRCUIT_STATE_OR_WAIT && !c->marked_for_close) { - tor_assert(circuits_pending_or_conns && - smartlist_isin(circuits_pending_or_conns, c)); + if (c->state == CIRCUIT_STATE_CHAN_WAIT && !c->marked_for_close) { + tor_assert(circuits_pending_chans && + smartlist_contains(circuits_pending_chans, c)); } else { - tor_assert(!circuits_pending_or_conns || - !smartlist_isin(circuits_pending_or_conns, c)); + tor_assert(!circuits_pending_chans || + !smartlist_contains(circuits_pending_chans, c)); } if (origin_circ && origin_circ->cpath) { assert_cpath_ok(origin_circ->cpath); diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h index 44f0c1fe3b..acc4b81fcd 100644 --- a/src/or/circuitlist.h +++ b/src/or/circuitlist.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,29 +9,33 @@ * \brief Header file for circuitlist.c. **/ -#ifndef _TOR_CIRCUITLIST_H -#define _TOR_CIRCUITLIST_H +#ifndef TOR_CIRCUITLIST_H +#define TOR_CIRCUITLIST_H -circuit_t * _circuit_get_global_list(void); +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); const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose); const char *circuit_purpose_to_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_dump_by_chan(channel_t *chan, int severity); +void circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id, + channel_t *chan); +void circuit_set_n_circid_chan(circuit_t *circ, circid_t id, + channel_t *chan); 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); +or_circuit_t *or_circuit_new(circid_t p_circ_id, channel_t *p_chan); +circuit_t *circuit_get_by_circid_channel(circid_t circ_id, + channel_t *chan); +circuit_t * +circuit_get_by_circid_channel_even_if_marked(circid_t circ_id, + channel_t *chan); +int circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan); circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn); -void circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason); +void circuit_unlink_all_from_channel(channel_t *chan, int reason); origin_circuit_t *circuit_get_by_global_id(uint32_t id); origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data( const rend_data_t *rend_data); @@ -42,17 +46,18 @@ 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, +void circuit_mark_all_dirty_circs_as_unusable(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); +void circuit_clear_cpath(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); +void circuit_get_all_pending_on_channel(smartlist_t *out, + channel_t *chan); +int circuit_count_pending_on_channel(channel_t *chan); #define circuit_mark_for_close(c, reason) \ - _circuit_mark_for_close((c), (reason), __LINE__, _SHORT_FILE_) + 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); diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c new file mode 100644 index 0000000000..545cfd0650 --- /dev/null +++ b/src/or/circuitmux.c @@ -0,0 +1,1745 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuitmux.c + * \brief Circuit mux/cell selection abstraction + **/ + +#include "or.h" +#include "channel.h" +#include "circuitlist.h" +#include "circuitmux.h" + +/* + * Private typedefs for circuitmux.c + */ + +/* + * Map of muxinfos for circuitmux_t to use; struct is defined below (name + * of struct must match HT_HEAD line). + */ +typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t; + +/* + * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to + * break the hash table code). + */ +typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t; + +/* + * Anything the mux wants to store per-circuit in the map; right now just + * a count of queued cells. + */ + +typedef struct circuit_muxinfo_s circuit_muxinfo_t; + +/* + * Structures for circuitmux.c + */ + +/* + * A circuitmux is a collection of circuits; it tracks which subset + * of the attached circuits are 'active' (i.e., have cells available + * to transmit) and how many cells on each. It expoes three distinct + * interfaces to other components: + * + * To channels, which each have a circuitmux_t, the supported operations + * are: + * + * circuitmux_get_first_active_circuit(): + * + * Pick one of the circuitmux's active circuits to send cells from. + * + * circuitmux_notify_xmit_cells(): + * + * Notify the circuitmux that cells have been sent on a circuit. + * + * To circuits, the exposed operations are: + * + * circuitmux_attach_circuit(): + * + * Attach a circuit to the circuitmux; this will allocate any policy- + * specific data wanted for this circuit and add it to the active + * circuits list if it has queued cells. + * + * circuitmux_detach_circuit(): + * + * Detach a circuit from the circuitmux, freeing associated structures. + * + * circuitmux_clear_num_cells(): + * + * Clear the circuitmux's cell counter for this circuit. + * + * circuitmux_set_num_cells(): + * + * Set the circuitmux's cell counter for this circuit. + * + * See circuitmux.h for the circuitmux_policy_t data structure, which contains + * a table of function pointers implementing a circuit selection policy, and + * circuitmux_ewma.c for an example of a circuitmux policy. Circuitmux + * policies can be manipulated with: + * + * circuitmux_get_policy(): + * + * Return the current policy for a circuitmux_t, if any. + * + * circuitmux_clear_policy(): + * + * Remove a policy installed on a circuitmux_t, freeing all associated + * data. The circuitmux will revert to the built-in round-robin behavior. + * + * circuitmux_set_policy(): + * + * Install a policy on a circuitmux_t; the appropriate callbacks will be + * made to attach all existing circuits to the new policy. + * + */ + +struct circuitmux_s { + /* Keep count of attached, active circuits */ + unsigned int n_circuits, n_active_circuits; + + /* Total number of queued cells on all circuits */ + unsigned int n_cells; + + /* + * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t + */ + chanid_circid_muxinfo_map_t *chanid_circid_map; + + /* + * Double-linked ring of circuits with queued cells waiting for room to + * 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_head, *active_circuits_tail; + + /* + * Circuitmux policy; if this is non-NULL, it can override the built- + * in round-robin active circuits behavior. This is how EWMA works in + * the new circuitmux_t world. + */ + const circuitmux_policy_t *policy; + + /* Policy-specific data */ + circuitmux_policy_data_t *policy_data; +}; + +/* + * This struct holds whatever we want to store per attached circuit on a + * circuitmux_t; right now, just the count of queued cells and the direction. + */ + +struct circuit_muxinfo_s { + /* Count of cells on this circuit at last update */ + unsigned int cell_count; + /* Direction of flow */ + cell_direction_t direction; + /* Policy-specific data */ + circuitmux_policy_circ_data_t *policy_data; + /* Mark bit for consistency checker */ + unsigned int mark:1; +}; + +/* + * A map from channel ID and circuit ID to a circuit_muxinfo_t for that + * circuit. + */ + +struct chanid_circid_muxinfo_t { + HT_ENTRY(chanid_circid_muxinfo_t) node; + uint64_t chan_id; + circid_t circ_id; + circuit_muxinfo_t muxinfo; +}; + +/* + * Internal-use #defines + */ + +#ifdef CMUX_PARANOIA +#define circuitmux_assert_okay_paranoid(cmux) \ + circuitmux_assert_okay(cmux) +#else +#define circuitmux_assert_okay_paranoid(cmux) +#endif + +/* + * Static function declarations + */ + +static INLINE int +chanid_circid_entries_eq(chanid_circid_muxinfo_t *a, + chanid_circid_muxinfo_t *b); +static INLINE unsigned int +chanid_circid_entry_hash(chanid_circid_muxinfo_t *a); +static chanid_circid_muxinfo_t * +circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ); +static void +circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction); +static void +circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction); +static INLINE void +circuitmux_move_active_circ_to_tail(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction); +static INLINE circuit_t ** +circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ); +static INLINE circuit_t ** +circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ); +static void circuitmux_assert_okay_pass_one(circuitmux_t *cmux); +static void circuitmux_assert_okay_pass_two(circuitmux_t *cmux); +static void circuitmux_assert_okay_pass_three(circuitmux_t *cmux); + +/* Function definitions */ + +/** + * Linked list helpers + */ + +/** + * Move an active circuit to the tail of the cmux's active circuits list; + * used by circuitmux_notify_xmit_cells(). + */ + +static INLINE void +circuitmux_move_active_circ_to_tail(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction) +{ + circuit_t **next_p = NULL, **prev_p = NULL; + circuit_t **next_prev = NULL, **prev_next = NULL; + circuit_t **tail_next = NULL; + or_circuit_t *or_circ = NULL; + + tor_assert(cmux); + tor_assert(circ); + + circuitmux_assert_okay_paranoid(cmux); + + /* Figure out our next_p and prev_p for this cmux/direction */ + if (direction) { + if (direction == CELL_DIRECTION_OUT) { + tor_assert(circ->n_mux == cmux); + next_p = &(circ->next_active_on_n_chan); + prev_p = &(circ->prev_active_on_n_chan); + } else { + or_circ = TO_OR_CIRCUIT(circ); + tor_assert(or_circ->p_mux == cmux); + next_p = &(or_circ->next_active_on_p_chan); + prev_p = &(or_circ->prev_active_on_p_chan); + } + } else { + if (circ->n_mux == cmux) { + next_p = &(circ->next_active_on_n_chan); + prev_p = &(circ->prev_active_on_n_chan); + direction = CELL_DIRECTION_OUT; + } else { + or_circ = TO_OR_CIRCUIT(circ); + tor_assert(or_circ->p_mux == cmux); + next_p = &(or_circ->next_active_on_p_chan); + prev_p = &(or_circ->prev_active_on_p_chan); + direction = CELL_DIRECTION_IN; + } + } + tor_assert(next_p); + tor_assert(prev_p); + + /* Check if this really is an active circuit */ + if ((*next_p == NULL && *prev_p == NULL) && + !(circ == cmux->active_circuits_head || + circ == cmux->active_circuits_tail)) { + /* Not active, no-op */ + return; + } + + /* Check if this is already the tail */ + if (circ == cmux->active_circuits_tail) return; + + /* Okay, we have to move it; figure out next_prev and prev_next */ + if (*next_p) next_prev = circuitmux_prev_active_circ_p(cmux, *next_p); + if (*prev_p) prev_next = circuitmux_next_active_circ_p(cmux, *prev_p); + /* Adjust the previous node's next pointer, if any */ + if (prev_next) *prev_next = *next_p; + /* Otherwise, we were the head */ + else cmux->active_circuits_head = *next_p; + /* Adjust the next node's previous pointer, if any */ + if (next_prev) *next_prev = *prev_p; + /* We're out of the list; now re-attach at the tail */ + /* Adjust our next and prev pointers */ + *next_p = NULL; + *prev_p = cmux->active_circuits_tail; + /* Set the next pointer of the tail, or the head if none */ + if (cmux->active_circuits_tail) { + tail_next = circuitmux_next_active_circ_p(cmux, + cmux->active_circuits_tail); + *tail_next = circ; + } else { + cmux->active_circuits_head = circ; + } + /* Set the tail to this circuit */ + cmux->active_circuits_tail = circ; + + circuitmux_assert_okay_paranoid(cmux); +} + +static INLINE circuit_t ** +circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ) +{ + tor_assert(cmux); + tor_assert(circ); + + if (circ->n_mux == cmux) return &(circ->next_active_on_n_chan); + else { + tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux); + return &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan); + } +} + +static INLINE circuit_t ** +circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ) +{ + tor_assert(cmux); + tor_assert(circ); + + if (circ->n_mux == cmux) return &(circ->prev_active_on_n_chan); + else { + tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux); + return &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan); + } +} + +/** + * Helper for chanid_circid_cell_count_map_t hash table: compare the channel + * ID and circuit ID for a and b, and return less than, equal to, or greater + * than zero appropriately. + */ + +static INLINE int +chanid_circid_entries_eq(chanid_circid_muxinfo_t *a, + chanid_circid_muxinfo_t *b) +{ + return a->chan_id == b->chan_id && a->circ_id == b->circ_id; +} + +/** + * Helper: return a hash based on circuit ID and channel ID in a. + */ + +static INLINE unsigned int +chanid_circid_entry_hash(chanid_circid_muxinfo_t *a) +{ + return (((unsigned int)(a->circ_id) << 8) ^ + ((unsigned int)((a->chan_id >> 32) & 0xffffffff)) ^ + ((unsigned int)(a->chan_id & 0xffffffff))); +} + +/* Declare the struct chanid_circid_muxinfo_map type */ +HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t); + +/* Emit a bunch of hash table stuff */ +HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, + chanid_circid_entry_hash, chanid_circid_entries_eq); +HT_GENERATE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, + chanid_circid_entry_hash, chanid_circid_entries_eq, 0.6, + malloc, realloc, free); + +/* + * Circuitmux alloc/free functions + */ + +/** + * Allocate a new circuitmux_t + */ + +circuitmux_t * +circuitmux_alloc(void) +{ + circuitmux_t *rv = NULL; + + rv = tor_malloc_zero(sizeof(*rv)); + rv->chanid_circid_map = tor_malloc_zero(sizeof(*( rv->chanid_circid_map))); + HT_INIT(chanid_circid_muxinfo_map, rv->chanid_circid_map); + + return rv; +} + +/** + * Detach all circuits from a circuitmux (use before circuitmux_free()) + */ + +void +circuitmux_detach_all_circuits(circuitmux_t *cmux) +{ + chanid_circid_muxinfo_t **i = NULL, *to_remove; + channel_t *chan = NULL; + circuit_t *circ = NULL; + + tor_assert(cmux); + /* + * Don't circuitmux_assert_okay_paranoid() here; this gets called when + * channels are being freed and have already been unregistered, so + * the channel ID lookups it does will fail. + */ + + i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map); + while (i) { + to_remove = *i; + if (to_remove) { + /* Find a channel and circuit */ + chan = channel_find_by_global_id(to_remove->chan_id); + if (chan) { + circ = + circuit_get_by_circid_channel_even_if_marked(to_remove->circ_id, + chan); + if (circ) { + /* Clear the circuit's mux for this direction */ + if (to_remove->muxinfo.direction == CELL_DIRECTION_OUT) { + /* + * Update active_circuits et al.; this does policy notifies, so + * comes before freeing policy data + */ + + if (to_remove->muxinfo.cell_count > 0) { + circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_OUT); + } + + /* Clear n_mux */ + circ->n_mux = NULL; + } else if (circ->magic == OR_CIRCUIT_MAGIC) { + /* + * Update active_circuits et al.; this does policy notifies, so + * comes before freeing policy data + */ + + if (to_remove->muxinfo.cell_count > 0) { + circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_IN); + } + + /* + * It has a sensible p_chan and direction == CELL_DIRECTION_IN, + * so clear p_mux. + */ + TO_OR_CIRCUIT(circ)->p_mux = NULL; + } else { + /* Complain and move on */ + log_warn(LD_CIRC, + "Circuit %u/channel " U64_FORMAT " had direction == " + "CELL_DIRECTION_IN, but isn't an or_circuit_t", + (unsigned)to_remove->circ_id, + U64_PRINTF_ARG(to_remove->chan_id)); + } + + /* Free policy-specific data if we have it */ + if (to_remove->muxinfo.policy_data) { + /* + * If we have policy data, assert that we have the means to + * free it + */ + tor_assert(cmux->policy); + tor_assert(cmux->policy->free_circ_data); + /* Call free_circ_data() */ + cmux->policy->free_circ_data(cmux, + cmux->policy_data, + circ, + to_remove->muxinfo.policy_data); + to_remove->muxinfo.policy_data = NULL; + } + } else { + /* Complain and move on */ + log_warn(LD_CIRC, + "Couldn't find circuit %u (for channel " U64_FORMAT ")", + (unsigned)to_remove->circ_id, + U64_PRINTF_ARG(to_remove->chan_id)); + } + } else { + /* Complain and move on */ + log_warn(LD_CIRC, + "Couldn't find channel " U64_FORMAT " (for circuit id %u)", + U64_PRINTF_ARG(to_remove->chan_id), + (unsigned)to_remove->circ_id); + } + + /* Assert that we don't have un-freed policy data for this circuit */ + tor_assert(to_remove->muxinfo.policy_data == NULL); + } + + i = HT_NEXT_RMV(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i); + + /* Free it */ + tor_free(to_remove); + } + + cmux->n_circuits = 0; + cmux->n_active_circuits = 0; + cmux->n_cells = 0; +} + +/** + * Free a circuitmux_t; the circuits must be detached first with + * circuitmux_detach_all_circuits(). + */ + +void +circuitmux_free(circuitmux_t *cmux) +{ + if (!cmux) return; + + tor_assert(cmux->n_circuits == 0); + tor_assert(cmux->n_active_circuits == 0); + + /* + * Free policy-specific data if we have any; we don't + * need to do circuitmux_set_policy(cmux, NULL) to cover + * the circuits because they would have been handled in + * circuitmux_detach_all_circuits() before this was + * called. + */ + if (cmux->policy && cmux->policy->free_cmux_data) { + if (cmux->policy_data) { + cmux->policy->free_cmux_data(cmux, cmux->policy_data); + cmux->policy_data = NULL; + } + } else tor_assert(cmux->policy_data == NULL); + + if (cmux->chanid_circid_map) { + HT_CLEAR(chanid_circid_muxinfo_map, cmux->chanid_circid_map); + tor_free(cmux->chanid_circid_map); + } + + tor_free(cmux); +} + +/* + * Circuitmux policy control functions + */ + +/** + * Remove any policy installed on cmux; all policy data will be freed and + * cmux behavior will revert to the built-in round-robin active_circuits + * mechanism. + */ + +void +circuitmux_clear_policy(circuitmux_t *cmux) +{ + tor_assert(cmux); + + /* Internally, this is just setting policy to NULL */ + if (cmux->policy) { + circuitmux_set_policy(cmux, NULL); + } +} + +/** + * Return the policy currently installed on a circuitmux_t + */ + +const circuitmux_policy_t * +circuitmux_get_policy(circuitmux_t *cmux) +{ + tor_assert(cmux); + + return cmux->policy; +} + +/** + * Set policy; allocate for new policy, detach all circuits from old policy + * if any, attach them to new policy, and free old policy data. + */ + +void +circuitmux_set_policy(circuitmux_t *cmux, + const circuitmux_policy_t *pol) +{ + const circuitmux_policy_t *old_pol = NULL, *new_pol = NULL; + circuitmux_policy_data_t *old_pol_data = NULL, *new_pol_data = NULL; + chanid_circid_muxinfo_t **i = NULL; + channel_t *chan = NULL; + uint64_t last_chan_id_searched = 0; + circuit_t *circ = NULL; + + tor_assert(cmux); + + /* Set up variables */ + old_pol = cmux->policy; + old_pol_data = cmux->policy_data; + new_pol = pol; + + /* Check if this is the trivial case */ + if (old_pol == new_pol) return; + + /* Allocate data for new policy, if any */ + if (new_pol && new_pol->alloc_cmux_data) { + /* + * If alloc_cmux_data is not null, then we expect to get some policy + * data. Assert that we also have free_cmux_data so we can free it + * when the time comes, and allocate it. + */ + tor_assert(new_pol->free_cmux_data); + new_pol_data = new_pol->alloc_cmux_data(cmux); + tor_assert(new_pol_data); + } + + /* Install new policy and new policy data on cmux */ + cmux->policy = new_pol; + cmux->policy_data = new_pol_data; + + /* Iterate over all circuits, attaching/detaching each one */ + i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map); + while (i) { + /* Assert that this entry isn't NULL */ + tor_assert(*i); + + /* + * Get the channel; since normal case is all circuits on the mux share a + * channel, we cache last_chan_id_searched + */ + if (!chan || last_chan_id_searched != (*i)->chan_id) { + chan = channel_find_by_global_id((*i)->chan_id); + last_chan_id_searched = (*i)->chan_id; + } + tor_assert(chan); + + /* Get the circuit */ + circ = circuit_get_by_circid_channel_even_if_marked((*i)->circ_id, chan); + tor_assert(circ); + + /* Need to tell old policy it becomes inactive (i.e., it is active) ? */ + if (old_pol && old_pol->notify_circ_inactive && + (*i)->muxinfo.cell_count > 0) { + old_pol->notify_circ_inactive(cmux, old_pol_data, circ, + (*i)->muxinfo.policy_data); + } + + /* Need to free old policy data? */ + if ((*i)->muxinfo.policy_data) { + /* Assert that we have the means to free it if we have policy data */ + tor_assert(old_pol); + tor_assert(old_pol->free_circ_data); + /* Free it */ + old_pol->free_circ_data(cmux, old_pol_data, circ, + (*i)->muxinfo.policy_data); + (*i)->muxinfo.policy_data = NULL; + } + + /* Need to allocate new policy data? */ + if (new_pol && new_pol->alloc_circ_data) { + /* + * If alloc_circ_data is not null, we expect to get some per-circuit + * policy data. Assert that we also have free_circ_data so we can + * free it when the time comes, and allocate it. + */ + tor_assert(new_pol->free_circ_data); + (*i)->muxinfo.policy_data = + new_pol->alloc_circ_data(cmux, new_pol_data, circ, + (*i)->muxinfo.direction, + (*i)->muxinfo.cell_count); + } + + /* Need to make active on new policy? */ + if (new_pol && new_pol->notify_circ_active && + (*i)->muxinfo.cell_count > 0) { + new_pol->notify_circ_active(cmux, new_pol_data, circ, + (*i)->muxinfo.policy_data); + } + + /* Advance to next circuit map entry */ + i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i); + } + + /* Free data for old policy, if any */ + if (old_pol_data) { + /* + * If we had old policy data, we should have an old policy and a free + * function for it. + */ + tor_assert(old_pol); + tor_assert(old_pol->free_cmux_data); + old_pol->free_cmux_data(cmux, old_pol_data); + old_pol_data = NULL; + } +} + +/* + * Circuitmux/circuit attachment status inquiry functions + */ + +/** + * Query the direction of an attached circuit + */ + +cell_direction_t +circuitmux_attached_circuit_direction(circuitmux_t *cmux, circuit_t *circ) +{ + chanid_circid_muxinfo_t *hashent = NULL; + + /* Try to find a map entry */ + hashent = circuitmux_find_map_entry(cmux, circ); + + /* + * This function should only be called on attached circuits; assert that + * we had a map entry. + */ + tor_assert(hashent); + + /* Return the direction from the map entry */ + return hashent->muxinfo.direction; +} + +/** + * Find an entry in the cmux's map for this circuit or return NULL if there + * is none. + */ + +static chanid_circid_muxinfo_t * +circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ) +{ + chanid_circid_muxinfo_t search, *hashent = NULL; + + /* Sanity-check parameters */ + tor_assert(cmux); + tor_assert(cmux->chanid_circid_map); + tor_assert(circ); + + /* Check if we have n_chan */ + if (circ->n_chan) { + /* Okay, let's see if it's attached for n_chan/n_circ_id */ + search.chan_id = circ->n_chan->global_identifier; + search.circ_id = circ->n_circ_id; + + /* Query */ + hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map, + &search); + } + + /* Found something? */ + if (hashent) { + /* + * Assert that the direction makes sense for a hashent we found by + * n_chan/n_circ_id before we return it. + */ + tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_OUT); + } else { + /* Not there, have we got a p_chan/p_circ_id to try? */ + if (circ->magic == OR_CIRCUIT_MAGIC) { + search.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; + /* Check for p_chan */ + if (TO_OR_CIRCUIT(circ)->p_chan) { + search.chan_id = TO_OR_CIRCUIT(circ)->p_chan->global_identifier; + /* Okay, search for that */ + hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map, + &search); + /* Find anything? */ + if (hashent) { + /* Assert that the direction makes sense before we return it */ + tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_IN); + } + } + } + } + + /* Okay, hashent is it if it was there */ + return hashent; +} + +/** + * Query whether a circuit is attached to a circuitmux + */ + +int +circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ) +{ + chanid_circid_muxinfo_t *hashent = NULL; + + /* Look if it's in the circuit map */ + hashent = circuitmux_find_map_entry(cmux, circ); + + return (hashent != NULL); +} + +/** + * Query whether a circuit is active on a circuitmux + */ + +int +circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ) +{ + chanid_circid_muxinfo_t *hashent = NULL; + int is_active = 0; + + tor_assert(cmux); + tor_assert(circ); + + /* Look if it's in the circuit map */ + hashent = circuitmux_find_map_entry(cmux, circ); + if (hashent) { + /* Check the number of cells on this circuit */ + is_active = (hashent->muxinfo.cell_count > 0); + } + /* else not attached, so not active */ + + return is_active; +} + +/** + * Query number of available cells for a circuit on a circuitmux + */ + +unsigned int +circuitmux_num_cells_for_circuit(circuitmux_t *cmux, circuit_t *circ) +{ + chanid_circid_muxinfo_t *hashent = NULL; + unsigned int n_cells = 0; + + tor_assert(cmux); + tor_assert(circ); + + /* Look if it's in the circuit map */ + hashent = circuitmux_find_map_entry(cmux, circ); + if (hashent) { + /* Just get the cell count for this circuit */ + n_cells = hashent->muxinfo.cell_count; + } + /* else not attached, so 0 cells */ + + return n_cells; +} + +/** + * Query total number of available cells on a circuitmux + */ + +unsigned int +circuitmux_num_cells(circuitmux_t *cmux) +{ + tor_assert(cmux); + + return cmux->n_cells; +} + +/** + * Query total number of circuits active on a circuitmux + */ + +unsigned int +circuitmux_num_active_circuits(circuitmux_t *cmux) +{ + tor_assert(cmux); + + return cmux->n_active_circuits; +} + +/** + * Query total number of circuits attached to a circuitmux + */ + +unsigned int +circuitmux_num_circuits(circuitmux_t *cmux) +{ + tor_assert(cmux); + + return cmux->n_circuits; +} + +/* + * Functions for circuit code to call to update circuit status + */ + +/** + * Attach a circuit to a circuitmux, for the specified direction. + */ + +void +circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction) +{ + channel_t *chan = NULL; + uint64_t channel_id; + circid_t circ_id; + chanid_circid_muxinfo_t search, *hashent = NULL; + unsigned int cell_count; + + tor_assert(cmux); + tor_assert(circ); + tor_assert(direction == CELL_DIRECTION_IN || + direction == CELL_DIRECTION_OUT); + circuitmux_assert_okay_paranoid(cmux); + + /* + * Figure out which channel we're using, and get the circuit's current + * cell count and circuit ID; assert that the circuit is not already + * attached to another mux. + */ + if (direction == CELL_DIRECTION_OUT) { + /* It's n_chan */ + chan = circ->n_chan; + cell_count = circ->n_chan_cells.n; + circ_id = circ->n_circ_id; + } else { + /* We want p_chan */ + chan = TO_OR_CIRCUIT(circ)->p_chan; + cell_count = TO_OR_CIRCUIT(circ)->p_chan_cells.n; + circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; + } + /* Assert that we did get a channel */ + tor_assert(chan); + /* Assert that the circuit ID is sensible */ + tor_assert(circ_id != 0); + + /* Get the channel ID */ + channel_id = chan->global_identifier; + + /* See if we already have this one */ + search.chan_id = channel_id; + search.circ_id = circ_id; + hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map, + &search); + + if (hashent) { + /* + * This circuit was already attached to this cmux; make sure the + * directions match and update the cell count and active circuit count. + */ + log_info(LD_CIRC, + "Circuit %u on channel " U64_FORMAT " was already attached to " + "cmux %p (trying to attach to %p)", + (unsigned)circ_id, U64_PRINTF_ARG(channel_id), + ((direction == CELL_DIRECTION_OUT) ? + circ->n_mux : TO_OR_CIRCUIT(circ)->p_mux), + cmux); + + /* + * The mux pointer on this circuit and the direction in result should + * match; otherwise assert. + */ + if (direction == CELL_DIRECTION_OUT) tor_assert(circ->n_mux == cmux); + else tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux); + tor_assert(hashent->muxinfo.direction == direction); + + /* + * Looks okay; just update the cell count and active circuits if we must + */ + if (hashent->muxinfo.cell_count > 0 && cell_count == 0) { + --(cmux->n_active_circuits); + circuitmux_make_circuit_inactive(cmux, circ, direction); + } else if (hashent->muxinfo.cell_count == 0 && cell_count > 0) { + ++(cmux->n_active_circuits); + circuitmux_make_circuit_active(cmux, circ, direction); + } + cmux->n_cells -= hashent->muxinfo.cell_count; + cmux->n_cells += cell_count; + hashent->muxinfo.cell_count = cell_count; + } else { + /* + * New circuit; add an entry and update the circuit/active circuit + * counts. + */ + log_debug(LD_CIRC, + "Attaching circuit %u on channel " U64_FORMAT " to cmux %p", + (unsigned)circ_id, U64_PRINTF_ARG(channel_id), cmux); + + /* + * Assert that the circuit doesn't already have a mux for this + * direction. + */ + if (direction == CELL_DIRECTION_OUT) tor_assert(circ->n_mux == NULL); + else tor_assert(TO_OR_CIRCUIT(circ)->p_mux == NULL); + + /* Insert it in the map */ + hashent = tor_malloc_zero(sizeof(*hashent)); + hashent->chan_id = channel_id; + hashent->circ_id = circ_id; + hashent->muxinfo.cell_count = cell_count; + hashent->muxinfo.direction = direction; + /* Allocate policy specific circuit data if we need it */ + if (cmux->policy && cmux->policy->alloc_circ_data) { + /* Assert that we have the means to free policy-specific data */ + tor_assert(cmux->policy->free_circ_data); + /* Allocate it */ + hashent->muxinfo.policy_data = + cmux->policy->alloc_circ_data(cmux, + cmux->policy_data, + circ, + direction, + cell_count); + /* If we wanted policy data, it's an error not to get any */ + tor_assert(hashent->muxinfo.policy_data); + } + HT_INSERT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, + hashent); + + /* Set the circuit's mux for this direction */ + if (direction == CELL_DIRECTION_OUT) circ->n_mux = cmux; + else TO_OR_CIRCUIT(circ)->p_mux = cmux; + + /* Make sure the next/prev pointers are NULL */ + if (direction == CELL_DIRECTION_OUT) { + circ->next_active_on_n_chan = NULL; + circ->prev_active_on_n_chan = NULL; + } else { + TO_OR_CIRCUIT(circ)->next_active_on_p_chan = NULL; + TO_OR_CIRCUIT(circ)->prev_active_on_p_chan = NULL; + } + + /* Update counters */ + ++(cmux->n_circuits); + if (cell_count > 0) { + ++(cmux->n_active_circuits); + circuitmux_make_circuit_active(cmux, circ, direction); + } + cmux->n_cells += cell_count; + } + + circuitmux_assert_okay_paranoid(cmux); +} + +/** + * Detach a circuit from a circuitmux and update all counters as needed; + * no-op if not attached. + */ + +void +circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ) +{ + chanid_circid_muxinfo_t search, *hashent = NULL; + /* + * Use this to keep track of whether we found it for n_chan or + * p_chan for consistency checking. + */ + cell_direction_t last_searched_direction; + + tor_assert(cmux); + tor_assert(cmux->chanid_circid_map); + tor_assert(circ); + circuitmux_assert_okay_paranoid(cmux); + + /* See if we have it for n_chan/n_circ_id */ + if (circ->n_chan) { + search.chan_id = circ->n_chan->global_identifier; + search.circ_id = circ->n_circ_id; + hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map, + &search); + last_searched_direction = CELL_DIRECTION_OUT; + } + + /* Got one? If not, see if it's an or_circuit_t and try p_chan/p_circ_id */ + if (!hashent) { + if (circ->magic == OR_CIRCUIT_MAGIC) { + search.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; + if (TO_OR_CIRCUIT(circ)->p_chan) { + search.chan_id = TO_OR_CIRCUIT(circ)->p_chan->global_identifier; + hashent = HT_FIND(chanid_circid_muxinfo_map, + cmux->chanid_circid_map, + &search); + last_searched_direction = CELL_DIRECTION_IN; + } + } + } + + /* + * If hashent isn't NULL, we have a circuit to detach; don't remove it from + * the map until later of circuitmux_make_circuit_inactive() breaks. + */ + if (hashent) { + /* Update counters */ + --(cmux->n_circuits); + if (hashent->muxinfo.cell_count > 0) { + --(cmux->n_active_circuits); + /* This does policy notifies, so comes before freeing policy data */ + circuitmux_make_circuit_inactive(cmux, circ, last_searched_direction); + } + cmux->n_cells -= hashent->muxinfo.cell_count; + + /* Free policy-specific data if we have it */ + if (hashent->muxinfo.policy_data) { + /* If we have policy data, assert that we have the means to free it */ + tor_assert(cmux->policy); + tor_assert(cmux->policy->free_circ_data); + /* Call free_circ_data() */ + cmux->policy->free_circ_data(cmux, + cmux->policy_data, + circ, + hashent->muxinfo.policy_data); + hashent->muxinfo.policy_data = NULL; + } + + /* Consistency check: the direction must match the direction searched */ + tor_assert(last_searched_direction == hashent->muxinfo.direction); + /* Clear the circuit's mux for this direction */ + if (last_searched_direction == CELL_DIRECTION_OUT) circ->n_mux = NULL; + else TO_OR_CIRCUIT(circ)->p_mux = NULL; + + /* Now remove it from the map */ + HT_REMOVE(chanid_circid_muxinfo_map, cmux->chanid_circid_map, hashent); + + /* Free the hash entry */ + tor_free(hashent); + } + + circuitmux_assert_okay_paranoid(cmux); +} + +/** + * Make a circuit active; update active list and policy-specific info, but + * we don't mess with the counters or hash table here. + */ + +static void +circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction) +{ + circuit_t **next_active = NULL, **prev_active = NULL, **next_prev = NULL; + circuitmux_t *circuit_cmux = NULL; + chanid_circid_muxinfo_t *hashent = NULL; + channel_t *chan = NULL; + circid_t circ_id; + int already_active; + + tor_assert(cmux); + tor_assert(circ); + tor_assert(direction == CELL_DIRECTION_OUT || + direction == CELL_DIRECTION_IN); + /* + * Don't circuitmux_assert_okay_paranoid(cmux) here because the cell count + * already got changed and we have to update the list for it to be consistent + * again. + */ + + /* Get the right set of active list links for this direction */ + if (direction == CELL_DIRECTION_OUT) { + next_active = &(circ->next_active_on_n_chan); + prev_active = &(circ->prev_active_on_n_chan); + circuit_cmux = circ->n_mux; + chan = circ->n_chan; + circ_id = circ->n_circ_id; + } else { + next_active = &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan); + prev_active = &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan); + circuit_cmux = TO_OR_CIRCUIT(circ)->p_mux; + chan = TO_OR_CIRCUIT(circ)->p_chan; + circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; + } + + /* Assert that it is attached to this mux and a channel */ + tor_assert(cmux == circuit_cmux); + tor_assert(chan != NULL); + + /* + * Check if the circuit really was inactive; if it's active, at least one + * of the next_active and prev_active pointers will not be NULL, or this + * circuit will be either the head or tail of the list for this cmux. + */ + already_active = (*prev_active != NULL || *next_active != NULL || + cmux->active_circuits_head == circ || + cmux->active_circuits_tail == circ); + + /* If we're already active, log a warning and finish */ + if (already_active) { + log_warn(LD_CIRC, + "Circuit %u on channel " U64_FORMAT " was already active", + (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier)); + return; + } + + /* + * This is going at the head of the list; if the old head is not NULL, + * then its prev pointer should point to this. + */ + *next_active = cmux->active_circuits_head; /* Next is old head */ + *prev_active = NULL; /* Prev is NULL (this will be the head) */ + if (cmux->active_circuits_head) { + /* The list had an old head; update its prev pointer */ + next_prev = + circuitmux_prev_active_circ_p(cmux, cmux->active_circuits_head); + tor_assert(next_prev); + *next_prev = circ; + } else { + /* The list was empty; this becomes the tail as well */ + cmux->active_circuits_tail = circ; + } + /* This becomes the new head of the list */ + cmux->active_circuits_head = circ; + + /* Policy-specific notification */ + if (cmux->policy && + cmux->policy->notify_circ_active) { + /* Okay, we need to check the circuit for policy data now */ + hashent = circuitmux_find_map_entry(cmux, circ); + /* We should have found something */ + tor_assert(hashent); + /* Notify */ + cmux->policy->notify_circ_active(cmux, cmux->policy_data, + circ, hashent->muxinfo.policy_data); + } + + circuitmux_assert_okay_paranoid(cmux); +} + +/** + * Make a circuit inactive; update active list and policy-specific info, but + * we don't mess with the counters or hash table here. + */ + +static void +circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction) +{ + circuit_t **next_active = NULL, **prev_active = NULL; + circuit_t **next_prev = NULL, **prev_next = NULL; + circuitmux_t *circuit_cmux = NULL; + chanid_circid_muxinfo_t *hashent = NULL; + channel_t *chan = NULL; + circid_t circ_id; + int already_inactive; + + tor_assert(cmux); + tor_assert(circ); + tor_assert(direction == CELL_DIRECTION_OUT || + direction == CELL_DIRECTION_IN); + /* + * Don't circuitmux_assert_okay_paranoid(cmux) here because the cell count + * already got changed and we have to update the list for it to be consistent + * again. + */ + + /* Get the right set of active list links for this direction */ + if (direction == CELL_DIRECTION_OUT) { + next_active = &(circ->next_active_on_n_chan); + prev_active = &(circ->prev_active_on_n_chan); + circuit_cmux = circ->n_mux; + chan = circ->n_chan; + circ_id = circ->n_circ_id; + } else { + next_active = &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan); + prev_active = &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan); + circuit_cmux = TO_OR_CIRCUIT(circ)->p_mux; + chan = TO_OR_CIRCUIT(circ)->p_chan; + circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; + } + + /* Assert that it is attached to this mux and a channel */ + tor_assert(cmux == circuit_cmux); + tor_assert(chan != NULL); + + /* + * Check if the circuit really was active; if it's inactive, the + * next_active and prev_active pointers will be NULL and this circuit + * will not be the head or tail of the list for this cmux. + */ + already_inactive = (*prev_active == NULL && *next_active == NULL && + cmux->active_circuits_head != circ && + cmux->active_circuits_tail != circ); + + /* If we're already inactive, log a warning and finish */ + if (already_inactive) { + log_warn(LD_CIRC, + "Circuit %d on channel " U64_FORMAT " was already inactive", + (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier)); + return; + } + + /* Remove from the list; first get next_prev and prev_next */ + if (*next_active) { + /* + * If there's a next circuit, its previous circuit becomes this + * circuit's previous circuit. + */ + next_prev = circuitmux_prev_active_circ_p(cmux, *next_active); + } else { + /* Else, the tail becomes this circuit's previous circuit */ + next_prev = &(cmux->active_circuits_tail); + } + + /* Got next_prev, now prev_next */ + if (*prev_active) { + /* + * If there's a previous circuit, its next circuit becomes this circuit's + * next circuit. + */ + prev_next = circuitmux_next_active_circ_p(cmux, *prev_active); + } else { + /* Else, the head becomes this circuit's next circuit */ + prev_next = &(cmux->active_circuits_head); + } + + /* Assert that we got sensible values for the next/prev pointers */ + tor_assert(next_prev != NULL); + tor_assert(prev_next != NULL); + + /* Update the next/prev pointers - this removes circ from the list */ + *next_prev = *prev_active; + *prev_next = *next_active; + + /* Now null out prev_active/next_active */ + *prev_active = NULL; + *next_active = NULL; + + /* Policy-specific notification */ + if (cmux->policy && + cmux->policy->notify_circ_inactive) { + /* Okay, we need to check the circuit for policy data now */ + hashent = circuitmux_find_map_entry(cmux, circ); + /* We should have found something */ + tor_assert(hashent); + /* Notify */ + cmux->policy->notify_circ_inactive(cmux, cmux->policy_data, + circ, hashent->muxinfo.policy_data); + } + + circuitmux_assert_okay_paranoid(cmux); +} + +/** + * Clear the cell counter for a circuit on a circuitmux + */ + +void +circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ) +{ + /* This is the same as setting the cell count to zero */ + circuitmux_set_num_cells(cmux, circ, 0); +} + +/** + * Set the cell counter for a circuit on a circuitmux + */ + +void +circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ, + unsigned int n_cells) +{ + chanid_circid_muxinfo_t *hashent = NULL; + + tor_assert(cmux); + tor_assert(circ); + + circuitmux_assert_okay_paranoid(cmux); + + /* Search for this circuit's entry */ + hashent = circuitmux_find_map_entry(cmux, circ); + /* Assert that we found one */ + tor_assert(hashent); + + /* Update cmux cell counter */ + cmux->n_cells -= hashent->muxinfo.cell_count; + cmux->n_cells += n_cells; + + /* Do we need to notify a cmux policy? */ + if (cmux->policy && cmux->policy->notify_set_n_cells) { + /* Call notify_set_n_cells */ + cmux->policy->notify_set_n_cells(cmux, + cmux->policy_data, + circ, + hashent->muxinfo.policy_data, + n_cells); + } + + /* + * Update cmux active circuit counter: is the old cell count > 0 and the + * new cell count == 0 ? + */ + if (hashent->muxinfo.cell_count > 0 && n_cells == 0) { + --(cmux->n_active_circuits); + hashent->muxinfo.cell_count = n_cells; + circuitmux_make_circuit_inactive(cmux, circ, hashent->muxinfo.direction); + /* Is the old cell count == 0 and the new cell count > 0 ? */ + } else if (hashent->muxinfo.cell_count == 0 && n_cells > 0) { + ++(cmux->n_active_circuits); + hashent->muxinfo.cell_count = n_cells; + circuitmux_make_circuit_active(cmux, circ, hashent->muxinfo.direction); + } else { + /* + * Update the entry cell count like this so we can put a + * circuitmux_assert_okay_paranoid inside make_circuit_(in)active() too. + */ + hashent->muxinfo.cell_count = n_cells; + } + + circuitmux_assert_okay_paranoid(cmux); +} + +/* + * Functions for channel code to call to get a circuit to transmit from or + * notify that cells have been transmitted. + */ + +/** + * Pick a circuit to send from, using the active circuits list or a + * circuitmux policy if one is available. This is called from channel.c. + */ + +circuit_t * +circuitmux_get_first_active_circuit(circuitmux_t *cmux) +{ + circuit_t *circ = NULL; + + tor_assert(cmux); + + if (cmux->n_active_circuits > 0) { + /* We also must have a cell available for this to be the case */ + tor_assert(cmux->n_cells > 0); + /* Do we have a policy-provided circuit selector? */ + if (cmux->policy && cmux->policy->pick_active_circuit) { + circ = cmux->policy->pick_active_circuit(cmux, cmux->policy_data); + } + /* Fall back on the head of the active circuits list */ + if (!circ) { + tor_assert(cmux->active_circuits_head); + circ = cmux->active_circuits_head; + } + } else tor_assert(cmux->n_cells == 0); + + return circ; +} + +/** + * Notify the circuitmux that cells have been sent on a circuit; this + * is called from channel.c. + */ + +void +circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ, + unsigned int n_cells) +{ + chanid_circid_muxinfo_t *hashent = NULL; + int becomes_inactive = 0; + + tor_assert(cmux); + tor_assert(circ); + circuitmux_assert_okay_paranoid(cmux); + + if (n_cells == 0) return; + + /* + * To handle this, we have to: + * + * 1.) Adjust the circuit's cell counter in the cmux hash table + * 2.) Move the circuit to the tail of the active_circuits linked list + * for this cmux, or make the circuit inactive if the cell count + * went to zero. + * 3.) Call cmux->policy->notify_xmit_cells(), if any + */ + + /* Find the hash entry */ + hashent = circuitmux_find_map_entry(cmux, circ); + /* Assert that we found one */ + tor_assert(hashent); + + /* Adjust the cell counter and assert that we had that many cells to send */ + tor_assert(n_cells <= hashent->muxinfo.cell_count); + hashent->muxinfo.cell_count -= n_cells; + /* Do we need to make the circuit inactive? */ + if (hashent->muxinfo.cell_count == 0) becomes_inactive = 1; + /* Adjust the mux cell counter */ + cmux->n_cells -= n_cells; + + /* If we aren't making it inactive later, move it to the tail of the list */ + if (!becomes_inactive) { + circuitmux_move_active_circ_to_tail(cmux, circ, + hashent->muxinfo.direction); + } + + /* + * We call notify_xmit_cells() before making the circuit inactive if needed, + * so the policy can always count on this coming in on an active circuit. + */ + if (cmux->policy && cmux->policy->notify_xmit_cells) { + cmux->policy->notify_xmit_cells(cmux, cmux->policy_data, circ, + hashent->muxinfo.policy_data, + n_cells); + } + + /* + * Now make the circuit inactive if needed; this will call the policy's + * notify_circ_inactive() if present. + */ + if (becomes_inactive) { + --(cmux->n_active_circuits); + circuitmux_make_circuit_inactive(cmux, circ, hashent->muxinfo.direction); + } + + circuitmux_assert_okay_paranoid(cmux); +} + +/* + * Circuitmux consistency checking assertions + */ + +/** + * Check that circuitmux data structures are consistent and fail with an + * assert if not. + */ + +void +circuitmux_assert_okay(circuitmux_t *cmux) +{ + tor_assert(cmux); + + /* + * Pass 1: iterate the hash table; for each entry: + * a) Check that the circuit has this cmux for n_mux or p_mux + * b) If the cell_count is > 0, set the mark bit; otherwise clear it + * c) Also check activeness (cell_count > 0 should be active) + * d) Count the number of circuits, active circuits and queued cells + * and at the end check that they match the counters in the cmux. + * + * Pass 2: iterate the active circuits list; for each entry, + * make sure the circuit is attached to this mux and appears + * in the hash table. Make sure the mark bit is 1, and clear + * it in the hash table entry. Consistency-check the linked + * list pointers. + * + * Pass 3: iterate the hash table again; assert if any active circuits + * (mark bit set to 1) are discovered that weren't cleared in pass 2 + * (don't appear in the linked list). + */ + + circuitmux_assert_okay_pass_one(cmux); + circuitmux_assert_okay_pass_two(cmux); + circuitmux_assert_okay_pass_three(cmux); +} + +/** + * Do the first pass of circuitmux_assert_okay(); see the comment in that + * function. + */ + +static void +circuitmux_assert_okay_pass_one(circuitmux_t *cmux) +{ + chanid_circid_muxinfo_t **i = NULL; + uint64_t chan_id; + channel_t *chan; + circid_t circ_id; + circuit_t *circ; + or_circuit_t *or_circ; + unsigned int circ_is_active; + circuit_t **next_p, **prev_p; + unsigned int n_circuits, n_active_circuits, n_cells; + + tor_assert(cmux); + tor_assert(cmux->chanid_circid_map); + + /* Reset the counters */ + n_circuits = n_active_circuits = n_cells = 0; + /* Start iterating the hash table */ + i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map); + while (i) { + /* Assert that the hash table entry isn't null */ + tor_assert(*i); + + /* Get the channel and circuit id */ + chan_id = (*i)->chan_id; + circ_id = (*i)->circ_id; + + /* Find the channel and circuit, assert that they exist */ + chan = channel_find_by_global_id(chan_id); + tor_assert(chan); + circ = circuit_get_by_circid_channel_even_if_marked(circ_id, chan); + tor_assert(circ); + /* Clear the circ_is_active bit to start */ + circ_is_active = 0; + + /* Assert that we know which direction this is going */ + tor_assert((*i)->muxinfo.direction == CELL_DIRECTION_OUT || + (*i)->muxinfo.direction == CELL_DIRECTION_IN); + + if ((*i)->muxinfo.direction == CELL_DIRECTION_OUT) { + /* We should be n_mux on this circuit */ + tor_assert(cmux == circ->n_mux); + tor_assert(chan == circ->n_chan); + /* Get next and prev for next test */ + next_p = &(circ->next_active_on_n_chan); + prev_p = &(circ->prev_active_on_n_chan); + } else { + /* This should be an or_circuit_t and we should be p_mux */ + or_circ = TO_OR_CIRCUIT(circ); + tor_assert(cmux == or_circ->p_mux); + tor_assert(chan == or_circ->p_chan); + /* Get next and prev for next test */ + next_p = &(or_circ->next_active_on_p_chan); + prev_p = &(or_circ->prev_active_on_p_chan); + } + + /* + * Should this circuit be active? I.e., does the mux know about > 0 + * cells on it? + */ + circ_is_active = ((*i)->muxinfo.cell_count > 0); + + /* It should be in the linked list iff it's active */ + if (circ_is_active) { + /* Either we have a next link or we are the tail */ + tor_assert(*next_p || (circ == cmux->active_circuits_tail)); + /* Either we have a prev link or we are the head */ + tor_assert(*prev_p || (circ == cmux->active_circuits_head)); + /* Increment the active circuits counter */ + ++n_active_circuits; + } else { + /* Shouldn't be in list, so no next or prev link */ + tor_assert(!(*next_p)); + tor_assert(!(*prev_p)); + /* And can't be head or tail */ + tor_assert(circ != cmux->active_circuits_head); + tor_assert(circ != cmux->active_circuits_tail); + } + + /* Increment the circuits counter */ + ++n_circuits; + /* Adjust the cell counter */ + n_cells += (*i)->muxinfo.cell_count; + + /* Set the mark bit to circ_is_active */ + (*i)->muxinfo.mark = circ_is_active; + + /* Advance to the next entry */ + i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i); + } + + /* Now check the counters */ + tor_assert(n_cells == cmux->n_cells); + tor_assert(n_circuits == cmux->n_circuits); + tor_assert(n_active_circuits == cmux->n_active_circuits); +} + +/** + * Do the second pass of circuitmux_assert_okay(); see the comment in that + * function. + */ + +static void +circuitmux_assert_okay_pass_two(circuitmux_t *cmux) +{ + circuit_t *curr_circ, *prev_circ = NULL, *next_circ; + or_circuit_t *curr_or_circ; + uint64_t curr_chan_id; + circid_t curr_circ_id; + circuit_t **next_p, **prev_p; + channel_t *chan; + unsigned int n_active_circuits = 0; + cell_direction_t direction; + chanid_circid_muxinfo_t search, *hashent = NULL; + + tor_assert(cmux); + tor_assert(cmux->chanid_circid_map); + + /* + * Walk the linked list of active circuits in cmux; keep track of the + * previous circuit seen for consistency checking purposes. Count them + * to make sure the number in the linked list matches + * cmux->n_active_circuits. + */ + curr_circ = cmux->active_circuits_head; + while (curr_circ) { + /* Reset some things */ + chan = NULL; + curr_or_circ = NULL; + next_circ = NULL; + next_p = prev_p = NULL; + direction = 0; + + /* Figure out if this is n_mux or p_mux */ + if (cmux == curr_circ->n_mux) { + /* Get next_p and prev_p */ + next_p = &(curr_circ->next_active_on_n_chan); + prev_p = &(curr_circ->prev_active_on_n_chan); + /* Get the channel */ + chan = curr_circ->n_chan; + /* Get the circuit id */ + curr_circ_id = curr_circ->n_circ_id; + /* Remember the direction */ + direction = CELL_DIRECTION_OUT; + } else { + /* We must be p_mux and this must be an or_circuit_t */ + curr_or_circ = TO_OR_CIRCUIT(curr_circ); + tor_assert(cmux == curr_or_circ->p_mux); + /* Get next_p and prev_p */ + next_p = &(curr_or_circ->next_active_on_p_chan); + prev_p = &(curr_or_circ->prev_active_on_p_chan); + /* Get the channel */ + chan = curr_or_circ->p_chan; + /* Get the circuit id */ + curr_circ_id = curr_or_circ->p_circ_id; + /* Remember the direction */ + direction = CELL_DIRECTION_IN; + } + + /* Assert that we got a channel and get the channel ID */ + tor_assert(chan); + curr_chan_id = chan->global_identifier; + + /* Assert that prev_p points to last circuit we saw */ + tor_assert(*prev_p == prev_circ); + /* If that's NULL, assert that we are the head */ + if (!(*prev_p)) tor_assert(curr_circ == cmux->active_circuits_head); + + /* Get the next circuit */ + next_circ = *next_p; + /* If it's NULL, assert that we are the tail */ + if (!(*next_p)) tor_assert(curr_circ == cmux->active_circuits_tail); + + /* Now find the hash table entry for this circuit */ + search.chan_id = curr_chan_id; + search.circ_id = curr_circ_id; + hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map, + &search); + + /* Assert that we have one */ + tor_assert(hashent); + + /* Assert that the direction matches */ + tor_assert(direction == hashent->muxinfo.direction); + + /* Assert that the hash entry got marked in pass one */ + tor_assert(hashent->muxinfo.mark); + + /* Clear the mark */ + hashent->muxinfo.mark = 0; + + /* Increment the counter */ + ++n_active_circuits; + + /* Advance to the next active circuit and update prev_circ */ + prev_circ = curr_circ; + curr_circ = next_circ; + } + + /* Assert that the counter matches the cmux */ + tor_assert(n_active_circuits == cmux->n_active_circuits); +} + +/** + * Do the third pass of circuitmux_assert_okay(); see the comment in that + * function. + */ + +static void +circuitmux_assert_okay_pass_three(circuitmux_t *cmux) +{ + chanid_circid_muxinfo_t **i = NULL; + + tor_assert(cmux); + tor_assert(cmux->chanid_circid_map); + + /* Start iterating the hash table */ + i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map); + + /* Advance through each entry */ + while (i) { + /* Assert that it isn't null */ + tor_assert(*i); + + /* + * Assert that this entry is not marked - i.e., that either we didn't + * think it should be active in pass one or we saw it in the active + * circuits linked list. + */ + tor_assert(!((*i)->muxinfo.mark)); + + /* Advance to the next entry */ + i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i); + } +} + diff --git a/src/or/circuitmux.h b/src/or/circuitmux.h new file mode 100644 index 0000000000..25644ffab7 --- /dev/null +++ b/src/or/circuitmux.h @@ -0,0 +1,136 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuitmux.h + * \brief Header file for circuitmux.c + **/ + +#ifndef TOR_CIRCUITMUX_H +#define TOR_CIRCUITMUX_H + +#include "or.h" + +typedef struct circuitmux_policy_s circuitmux_policy_t; +typedef struct circuitmux_policy_data_s circuitmux_policy_data_t; +typedef struct circuitmux_policy_circ_data_s circuitmux_policy_circ_data_t; + +struct circuitmux_policy_s { + /* Allocate cmux-wide policy-specific data */ + circuitmux_policy_data_t * (*alloc_cmux_data)(circuitmux_t *cmux); + /* Free cmux-wide policy-specific data */ + void (*free_cmux_data)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data); + /* Allocate circuit policy-specific data for a newly attached circuit */ + circuitmux_policy_circ_data_t * + (*alloc_circ_data)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + cell_direction_t direction, + unsigned int cell_count); + /* Free circuit policy-specific data */ + void (*free_circ_data)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); + /* Notify that a circuit has become active/inactive */ + void (*notify_circ_active)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); + void (*notify_circ_inactive)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); + /* Notify of arriving/transmitted cells on a circuit */ + void (*notify_set_n_cells)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data, + unsigned int n_cells); + void (*notify_xmit_cells)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data, + unsigned int n_cells); + /* Choose a circuit */ + circuit_t * (*pick_active_circuit)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data); +}; + +/* + * Circuitmux policy implementations can subclass this to store circuitmux- + * wide data; it just has the magic number in the base struct. + */ + +struct circuitmux_policy_data_s { + uint32_t magic; +}; + +/* + * Circuitmux policy implementations can subclass this to store circuit- + * specific data; it just has the magic number in the base struct. + */ + +struct circuitmux_policy_circ_data_s { + uint32_t magic; +}; + +/* + * Upcast #defines for the above types + */ + +/** + * Convert a circuitmux_policy_data_t subtype to a circuitmux_policy_data_t. + */ + +#define TO_CMUX_POL_DATA(x) (&((x)->base_)) + +/** + * Convert a circuitmux_policy_circ_data_t subtype to a + * circuitmux_policy_circ_data_t. + */ + +#define TO_CMUX_POL_CIRC_DATA(x) (&((x)->base_)) + +/* Consistency check */ +void circuitmux_assert_okay(circuitmux_t *cmux); + +/* Create/destroy */ +circuitmux_t * circuitmux_alloc(void); +void circuitmux_detach_all_circuits(circuitmux_t *cmux); +void circuitmux_free(circuitmux_t *cmux); + +/* Policy control */ +void circuitmux_clear_policy(circuitmux_t *cmux); +const circuitmux_policy_t * circuitmux_get_policy(circuitmux_t *cmux); +void circuitmux_set_policy(circuitmux_t *cmux, + const circuitmux_policy_t *pol); + +/* Status inquiries */ +cell_direction_t circuitmux_attached_circuit_direction( + circuitmux_t *cmux, + circuit_t *circ); +int circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ); +int circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ); +unsigned int circuitmux_num_cells_for_circuit(circuitmux_t *cmux, + circuit_t *circ); +unsigned int circuitmux_num_cells(circuitmux_t *cmux); +unsigned int circuitmux_num_circuits(circuitmux_t *cmux); +unsigned int circuitmux_num_active_circuits(circuitmux_t *cmux); + +/* Channel interface */ +circuit_t * circuitmux_get_first_active_circuit(circuitmux_t *cmux); +void circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ, + unsigned int n_cells); + +/* Circuit interface */ +void circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ, + cell_direction_t direction); +void circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ); +void circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ); +void circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ, + unsigned int n_cells); + +#endif /* TOR_CIRCUITMUX_H */ + diff --git a/src/or/circuitmux_ewma.c b/src/or/circuitmux_ewma.c new file mode 100644 index 0000000000..3f37d7b9a0 --- /dev/null +++ b/src/or/circuitmux_ewma.c @@ -0,0 +1,684 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuitmux_ewma.c + * \brief EWMA circuit selection as a circuitmux_t policy + **/ + +#define TOR_CIRCUITMUX_EWMA_C_ + +#include <math.h> + +#include "or.h" +#include "circuitmux.h" +#include "circuitmux_ewma.h" +#include "networkstatus.h" + +/*** EWMA parameter #defines ***/ + +/** 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 + +/*** Some useful constant #defines ***/ + +/*DOCDOC*/ +#define EPSILON 0.00001 +/*DOCDOC*/ +#define LOG_ONEHALF -0.69314718055994529 + +/*** EWMA structures ***/ + +typedef struct cell_ewma_s cell_ewma_t; +typedef struct ewma_policy_data_s ewma_policy_data_t; +typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_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 channel_flush_from_first_active_circuit(). + */ + +struct cell_ewma_s { + /** 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 int last_adjusted_tick; + /** The EWMA of the cell count. */ + double cell_count; + /** True iff this is the cell count for a circuit's previous + * channel. */ + unsigned int is_for_p_chan : 1; + /** The position of the circuit within the OR connection's priority + * queue. */ + int heap_index; +}; + +struct ewma_policy_data_s { + circuitmux_policy_data_t base_; + + /** + * Priority queue of cell_ewma_t for circuits with queued cells waiting + * for room to free up on the channel that owns this circuitmux. Kept + * in heap order according to EWMA. This was formerly in channel_t, and + * in or_connection_t before that. + */ + smartlist_t *active_circuit_pqueue; + + /** + * The tick on which the cell_ewma_ts in active_circuit_pqueue last had + * their ewma values rescaled. This was formerly in channel_t, and in + * or_connection_t before that. + */ + unsigned int active_circuit_pqueue_last_recalibrated; +}; + +struct ewma_policy_circ_data_s { + circuitmux_policy_circ_data_t base_; + + /** + * The EWMA count for the number of cells flushed from this circuit + * onto this circuitmux. Used to determine which circuit to flush + * from next. This was formerly in circuit_t and or_circuit_t. + */ + cell_ewma_t cell_ewma; + + /** + * Pointer back to the circuit_t this is for; since we're separating + * out circuit selection policy like this, we can't attach cell_ewma_t + * to the circuit_t any more, so we can't use SUBTYPE_P directly to a + * circuit_t like before; instead get it here. + */ + circuit_t *circ; +}; + +#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU +#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U + +/*** Downcasts for the above types ***/ + +static ewma_policy_data_t * +TO_EWMA_POL_DATA(circuitmux_policy_data_t *); + +static ewma_policy_circ_data_t * +TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *); + +/** + * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert + * if the cast is impossible. + */ + +static INLINE ewma_policy_data_t * +TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) +{ + if (!pol) return NULL; + else { + tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); + return DOWNCAST(ewma_policy_data_t, pol); + } +} + +/** + * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t + * and assert if the cast is impossible. + */ + +static INLINE ewma_policy_circ_data_t * +TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) +{ + if (!pol) return NULL; + else { + tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); + return DOWNCAST(ewma_policy_circ_data_t, pol); + } +} + +/*** Static declarations for circuitmux_ewma.c ***/ + +static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma); +static int compare_cell_ewma_counts(const void *p1, const void *p2); +static unsigned cell_ewma_tick_from_timeval(const struct timeval *now, + double *remainder_out); +static circuit_t * cell_ewma_to_circuit(cell_ewma_t *ewma); +static INLINE double get_scale_factor(unsigned from_tick, unsigned to_tick); +static cell_ewma_t * pop_first_cell_ewma(ewma_policy_data_t *pol); +static void remove_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma); +static void scale_single_cell_ewma(cell_ewma_t *ewma, unsigned cur_tick); +static void scale_active_circuits(ewma_policy_data_t *pol, + unsigned cur_tick); + +/*** Circuitmux policy methods ***/ + +static circuitmux_policy_data_t * ewma_alloc_cmux_data(circuitmux_t *cmux); +static void ewma_free_cmux_data(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data); +static circuitmux_policy_circ_data_t * +ewma_alloc_circ_data(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data, + circuit_t *circ, cell_direction_t direction, + unsigned int cell_count); +static void +ewma_free_circ_data(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); +static void +ewma_notify_circ_active(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); +static void +ewma_notify_circ_inactive(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); +static void +ewma_notify_xmit_cells(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data, + unsigned int n_cells); +static circuit_t * +ewma_pick_active_circuit(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data); + +/*** EWMA global variables ***/ + +/** 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; +/* DOCDOC ewma_enabled */ +static int ewma_enabled = 0; + +/*** EWMA circuitmux_policy_t method table ***/ + +circuitmux_policy_t ewma_policy = { + /*.alloc_cmux_data =*/ ewma_alloc_cmux_data, + /*.free_cmux_data =*/ ewma_free_cmux_data, + /*.alloc_circ_data =*/ ewma_alloc_circ_data, + /*.free_circ_data =*/ ewma_free_circ_data, + /*.notify_circ_active =*/ ewma_notify_circ_active, + /*.notify_circ_inactive =*/ ewma_notify_circ_inactive, + /*.notify_set_n_cells =*/ NULL, /* EWMA doesn't need this */ + /*.notify_xmit_cells =*/ ewma_notify_xmit_cells, + /*.pick_active_circuit =*/ ewma_pick_active_circuit +}; + +/*** EWMA method implementations using the below EWMA helper functions ***/ + +/** + * Allocate an ewma_policy_data_t and upcast it to a circuitmux_policy_data_t; + * this is called when setting the policy on a circuitmux_t to ewma_policy. + */ + +static circuitmux_policy_data_t * +ewma_alloc_cmux_data(circuitmux_t *cmux) +{ + ewma_policy_data_t *pol = NULL; + + tor_assert(cmux); + + pol = tor_malloc_zero(sizeof(*pol)); + pol->base_.magic = EWMA_POL_DATA_MAGIC; + pol->active_circuit_pqueue = smartlist_new(); + pol->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick(); + + return TO_CMUX_POL_DATA(pol); +} + +/** + * Free an ewma_policy_data_t allocated with ewma_alloc_cmux_data() + */ + +static void +ewma_free_cmux_data(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data) +{ + ewma_policy_data_t *pol = NULL; + + tor_assert(cmux); + if (!pol_data) return; + + pol = TO_EWMA_POL_DATA(pol_data); + + smartlist_free(pol->active_circuit_pqueue); + tor_free(pol); +} + +/** + * Allocate an ewma_policy_circ_data_t and upcast it to a + * circuitmux_policy_data_t; this is called when attaching a circuit to a + * circuitmux_t with ewma_policy. + */ + +static circuitmux_policy_circ_data_t * +ewma_alloc_circ_data(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + cell_direction_t direction, + unsigned int cell_count) +{ + ewma_policy_circ_data_t *cdata = NULL; + + tor_assert(cmux); + tor_assert(pol_data); + tor_assert(circ); + tor_assert(direction == CELL_DIRECTION_OUT || + direction == CELL_DIRECTION_IN); + /* Shut the compiler up */ + tor_assert(cell_count == cell_count); + + cdata = tor_malloc_zero(sizeof(*cdata)); + cdata->base_.magic = EWMA_POL_CIRC_DATA_MAGIC; + cdata->circ = circ; + + /* + * Initialize the cell_ewma_t structure (formerly in + * init_circuit_base()) + */ + cdata->cell_ewma.last_adjusted_tick = cell_ewma_get_tick(); + cdata->cell_ewma.cell_count = 0.0; + cdata->cell_ewma.heap_index = -1; + if (direction == CELL_DIRECTION_IN) { + cdata->cell_ewma.is_for_p_chan = 1; + } else { + cdata->cell_ewma.is_for_p_chan = 0; + } + + return TO_CMUX_POL_CIRC_DATA(cdata); +} + +/** + * Free an ewma_policy_circ_data_t allocated with ewma_alloc_circ_data() + */ + +static void +ewma_free_circ_data(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data) + +{ + ewma_policy_circ_data_t *cdata = NULL; + + tor_assert(cmux); + tor_assert(circ); + tor_assert(pol_data); + + if (!pol_circ_data) return; + + cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data); + + tor_free(cdata); +} + +/** + * Handle circuit activation; this inserts the circuit's cell_ewma into + * the active_circuits_pqueue. + */ + +static void +ewma_notify_circ_active(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data) +{ + ewma_policy_data_t *pol = NULL; + ewma_policy_circ_data_t *cdata = NULL; + + tor_assert(cmux); + tor_assert(pol_data); + tor_assert(circ); + tor_assert(pol_circ_data); + + pol = TO_EWMA_POL_DATA(pol_data); + cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data); + + add_cell_ewma(pol, &(cdata->cell_ewma)); +} + +/** + * Handle circuit deactivation; this removes the circuit's cell_ewma from + * the active_circuits_pqueue. + */ + +static void +ewma_notify_circ_inactive(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data) +{ + ewma_policy_data_t *pol = NULL; + ewma_policy_circ_data_t *cdata = NULL; + + tor_assert(cmux); + tor_assert(pol_data); + tor_assert(circ); + tor_assert(pol_circ_data); + + pol = TO_EWMA_POL_DATA(pol_data); + cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data); + + remove_cell_ewma(pol, &(cdata->cell_ewma)); +} + +/** + * Update cell_ewma for this circuit after we've sent some cells, and + * remove/reinsert it in the queue. This used to be done (brokenly, + * see bug 6816) in channel_flush_from_first_active_circuit(). + */ + +static void +ewma_notify_xmit_cells(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data, + unsigned int n_cells) +{ + ewma_policy_data_t *pol = NULL; + ewma_policy_circ_data_t *cdata = NULL; + unsigned int tick; + double fractional_tick, ewma_increment; + /* The current (hi-res) time */ + struct timeval now_hires; + cell_ewma_t *cell_ewma, *tmp; + + tor_assert(cmux); + tor_assert(pol_data); + tor_assert(circ); + tor_assert(pol_circ_data); + tor_assert(n_cells > 0); + + pol = TO_EWMA_POL_DATA(pol_data); + cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data); + + /* Rescale the EWMAs if needed */ + tor_gettimeofday_cached(&now_hires); + tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick); + + if (tick != pol->active_circuit_pqueue_last_recalibrated) { + scale_active_circuits(pol, tick); + } + + /* How much do we adjust the cell count in cell_ewma by? */ + ewma_increment = + ((double)(n_cells)) * pow(ewma_scale_factor, -fractional_tick); + + /* Do the adjustment */ + cell_ewma = &(cdata->cell_ewma); + cell_ewma->cell_count += ewma_increment; + + /* + * Since we just sent on this circuit, it should be at the head of + * the queue. Pop the head, assert that it matches, then re-add. + */ + tmp = pop_first_cell_ewma(pol); + tor_assert(tmp == cell_ewma); + add_cell_ewma(pol, cell_ewma); +} + +/** + * Pick the preferred circuit to send from; this will be the one with + * the lowest EWMA value in the priority queue. This used to be done + * in channel_flush_from_first_active_circuit(). + */ + +static circuit_t * +ewma_pick_active_circuit(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data) +{ + ewma_policy_data_t *pol = NULL; + circuit_t *circ = NULL; + cell_ewma_t *cell_ewma = NULL; + + tor_assert(cmux); + tor_assert(pol_data); + + pol = TO_EWMA_POL_DATA(pol_data); + + if (smartlist_len(pol->active_circuit_pqueue) > 0) { + /* Get the head of the queue */ + cell_ewma = smartlist_get(pol->active_circuit_pqueue, 0); + circ = cell_ewma_to_circuit(cell_ewma); + } + + return circ; +} + +/** 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) +{ + ewma_policy_circ_data_t *cdata = NULL; + + tor_assert(ewma); + cdata = SUBTYPE_P(ewma, ewma_policy_circ_data_t, cell_ewma); + tor_assert(cdata); + + return cdata->circ; +} + +/* ==== 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. + */ + +/** 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; +} + +/** Tell the caller whether ewma_enabled is set */ +int +cell_ewma_enabled(void) +{ + return ewma_enabled; +} + +/** Compute and return the current cell_ewma tick. */ +unsigned int +cell_ewma_get_tick(void) +{ + return ((unsigned)approx_time() / EWMA_TICK_LEN); +} + +/** Adjust the global cell scale factor based on <b>options</b> */ +void +cell_ewma_set_scale_factor(const or_options_t *options, + const 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, -1, INT32_MAX)) >= 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 %f 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>chan</b> so + * that they are scaled with respect to <b>cur_tick</b> */ +static void +scale_active_circuits(ewma_policy_data_t *pol, unsigned cur_tick) +{ + double factor; + + tor_assert(pol); + tor_assert(pol->active_circuit_pqueue); + + factor = + get_scale_factor( + pol->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_BEGIN( + pol->active_circuit_pqueue, + cell_ewma_t *, e) { + tor_assert(e->last_adjusted_tick == + pol->active_circuit_pqueue_last_recalibrated); + e->cell_count *= factor; + e->last_adjusted_tick = cur_tick; + } SMARTLIST_FOREACH_END(e); + pol->active_circuit_pqueue_last_recalibrated = cur_tick; +} + +/** Rescale <b>ewma</b> to the same scale as <b>pol</b>, and add it to + * <b>pol</b>'s priority queue of active circuits */ +static void +add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma) +{ + tor_assert(pol); + tor_assert(pol->active_circuit_pqueue); + tor_assert(ewma); + tor_assert(ewma->heap_index == -1); + + scale_single_cell_ewma( + ewma, + pol->active_circuit_pqueue_last_recalibrated); + + smartlist_pqueue_add(pol->active_circuit_pqueue, + compare_cell_ewma_counts, + STRUCT_OFFSET(cell_ewma_t, heap_index), + ewma); +} + +/** Remove <b>ewma</b> from <b>pol</b>'s priority queue of active circuits */ +static void +remove_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma) +{ + tor_assert(pol); + tor_assert(pol->active_circuit_pqueue); + tor_assert(ewma); + tor_assert(ewma->heap_index != -1); + + smartlist_pqueue_remove(pol->active_circuit_pqueue, + compare_cell_ewma_counts, + STRUCT_OFFSET(cell_ewma_t, heap_index), + ewma); +} + +/** Remove and return the first cell_ewma_t from pol's priority queue of + * active circuits. Requires that the priority queue is nonempty. */ +static cell_ewma_t * +pop_first_cell_ewma(ewma_policy_data_t *pol) +{ + tor_assert(pol); + tor_assert(pol->active_circuit_pqueue); + + return smartlist_pqueue_pop(pol->active_circuit_pqueue, + compare_cell_ewma_counts, + STRUCT_OFFSET(cell_ewma_t, heap_index)); +} + diff --git a/src/or/circuitmux_ewma.h b/src/or/circuitmux_ewma.h new file mode 100644 index 0000000000..a512745c77 --- /dev/null +++ b/src/or/circuitmux_ewma.h @@ -0,0 +1,29 @@ +/* * Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuitmux_ewma.h + * \brief Header file for circuitmux_ewma.c + **/ + +#ifndef TOR_CIRCUITMUX_EWMA_H +#define TOR_CIRCUITMUX_EWMA_H + +#include "or.h" +#include "circuitmux.h" + +/* Everything but circuitmux_ewma.c should see this extern */ +#ifndef TOR_CIRCUITMUX_EWMA_C_ + +extern circuitmux_policy_t ewma_policy; + +#endif /* !(TOR_CIRCUITMUX_EWMA_C_) */ + +/* Externally visible EWMA functions */ +int cell_ewma_enabled(void); +unsigned int cell_ewma_get_tick(void); +void cell_ewma_set_scale_factor(const or_options_t *options, + const networkstatus_t *consensus); + +#endif /* TOR_CIRCUITMUX_EWMA_H */ + diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c new file mode 100644 index 0000000000..1d7812bf2b --- /dev/null +++ b/src/or/circuitstats.c @@ -0,0 +1,1556 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define CIRCUITSTATS_PRIVATE + +#include "or.h" +#include "circuitbuild.h" +#include "circuitstats.h" +#include "config.h" +#include "confparse.h" +#include "control.h" +#include "networkstatus.h" +#include "statefile.h" + +#undef log +#include <math.h> + +#define CBT_BIN_TO_MS(bin) ((bin)*CBT_BIN_WIDTH + (CBT_BIN_WIDTH/2)) + +/** Global list of circuit build times */ +// XXXX: 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. +/* XXXX024 Make this static; add accessor functions. */ +circuit_build_times_t circ_times; + +/** 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; + +/** + * This function decides if CBT learning should be disabled. It returns + * true if one or more of the following four conditions are met: + * + * 1. If the cbtdisabled consensus parameter is set. + * 2. If the torrc option LearnCircuitBuildTimeout is false. + * 3. If we are a directory authority + * 4. If we fail to write circuit build time history to our state file. + */ +int +circuit_build_times_disabled(void) +{ + if (unit_tests) { + return 0; + } else { + int consensus_disabled = networkstatus_get_param(NULL, "cbtdisabled", + 0, 0, 1); + int config_disabled = !get_options()->LearnCircuitBuildTimeout; + int dirauth_disabled = get_options()->AuthoritativeDir; + int state_disabled = did_last_state_file_write_fail() ? 1 : 0; + + if (consensus_disabled || config_disabled || dirauth_disabled || + state_disabled) { + log_debug(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 { + log_debug(LD_CIRC, + "CircuitBuildTime learning is not disabled. " + "Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d", + consensus_disabled, config_disabled, dirauth_disabled, + state_disabled); + return 0; + } + } +} + +/** + * Retrieve and bounds-check the cbtmaxtimeouts consensus paramter. + * + * Effect: When this many timeouts happen in the last 'cbtrecentcount' + * circuit attempts, the client should discard all of its history and + * begin learning a fresh timeout value. + */ +static int32_t +circuit_build_times_max_timeouts(void) +{ + int32_t cbt_maxtimeouts; + + cbt_maxtimeouts = networkstatus_get_param(NULL, "cbtmaxtimeouts", + CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT, + CBT_MIN_MAX_RECENT_TIMEOUT_COUNT, + CBT_MAX_MAX_RECENT_TIMEOUT_COUNT); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_max_timeouts() called, cbtmaxtimeouts is" + " %d", + cbt_maxtimeouts); + } + + return cbt_maxtimeouts; +} + +/** + * Retrieve and bounds-check the cbtnummodes consensus paramter. + * + * Effect: This value governs how many modes to use in the weighted + * average calculation of Pareto parameter Xm. A value of 3 introduces + * some bias (2-5% of CDF) under ideal conditions, but allows for better + * performance in the event that a client chooses guard nodes of radically + * different performance characteristics. + */ +static int32_t +circuit_build_times_default_num_xm_modes(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtnummodes", + CBT_DEFAULT_NUM_XM_MODES, + CBT_MIN_NUM_XM_MODES, + CBT_MAX_NUM_XM_MODES); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_default_num_xm_modes() called, cbtnummodes" + " is %d", + num); + } + + return num; +} + +/** + * Retrieve and bounds-check the cbtmincircs consensus paramter. + * + * Effect: This is the minimum number of circuits to build before + * computing a timeout. + */ +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, + CBT_MIN_MIN_CIRCUITS_TO_OBSERVE, + CBT_MAX_MIN_CIRCUITS_TO_OBSERVE); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_min_circs_to_observe() called, cbtmincircs" + " is %d", + num); + } + + 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(); +} + +/** + * Retrieve and bounds-check the cbtquantile consensus paramter. + * + * Effect: This is the position on the quantile curve to use to set the + * timeout value. It is a percent (10-99). + */ +double +circuit_build_times_quantile_cutoff(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtquantile", + CBT_DEFAULT_QUANTILE_CUTOFF, + CBT_MIN_QUANTILE_CUTOFF, + CBT_MAX_QUANTILE_CUTOFF); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_quantile_cutoff() called, cbtquantile" + " is %d", + num); + } + + return num/100.0; +} + +/** + * Retrieve and bounds-check the cbtclosequantile consensus paramter. + * + * Effect: This is the position on the quantile curve to use to set the + * timeout value to use to actually close circuits. It is a percent + * (0-99). + */ +static double +circuit_build_times_close_quantile(void) +{ + int32_t param; + /* Cast is safe - circuit_build_times_quantile_cutoff() is capped */ + int32_t min = (int)tor_lround(100*circuit_build_times_quantile_cutoff()); + param = networkstatus_get_param(NULL, "cbtclosequantile", + CBT_DEFAULT_CLOSE_QUANTILE, + CBT_MIN_CLOSE_QUANTILE, + CBT_MAX_CLOSE_QUANTILE); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_close_quantile() called, cbtclosequantile" + " is %d", param); + } + + if (param < min) { + log_warn(LD_DIR, "Consensus parameter cbtclosequantile is " + "too small, raising to %d", min); + param = min; + } + return param / 100.0; +} + +/** + * Retrieve and bounds-check the cbttestfreq consensus paramter. + * + * Effect: Describes how often in seconds to build a test circuit to + * gather timeout values. Only applies if less than 'cbtmincircs' + * have been recorded. + */ +static int32_t +circuit_build_times_test_frequency(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbttestfreq", + CBT_DEFAULT_TEST_FREQUENCY, + CBT_MIN_TEST_FREQUENCY, + CBT_MAX_TEST_FREQUENCY); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_test_frequency() called, cbttestfreq is %d", + num); + } + + return num; +} + +/** + * Retrieve and bounds-check the cbtmintimeout consensus parameter. + * + * Effect: This is the minimum allowed timeout value in milliseconds. + * The minimum is to prevent rounding to 0 (we only check once + * per second). + */ +static int32_t +circuit_build_times_min_timeout(void) +{ + int32_t num = networkstatus_get_param(NULL, "cbtmintimeout", + CBT_DEFAULT_TIMEOUT_MIN_VALUE, + CBT_MIN_TIMEOUT_MIN_VALUE, + CBT_MAX_TIMEOUT_MIN_VALUE); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_min_timeout() called, cbtmintimeout is %d", + num); + } + + return num; +} + +/** + * Retrieve and bounds-check the cbtinitialtimeout consensus paramter. + * + * Effect: This is the timeout value to use before computing a timeout, + * in milliseconds. + */ +int32_t +circuit_build_times_initial_timeout(void) +{ + int32_t min = circuit_build_times_min_timeout(); + int32_t param = networkstatus_get_param(NULL, "cbtinitialtimeout", + CBT_DEFAULT_TIMEOUT_INITIAL_VALUE, + CBT_MIN_TIMEOUT_INITIAL_VALUE, + CBT_MAX_TIMEOUT_INITIAL_VALUE); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_initial_timeout() called, " + "cbtinitialtimeout is %d", + param); + } + + if (param < min) { + log_warn(LD_DIR, "Consensus parameter cbtinitialtimeout is too small, " + "raising to %d", min); + param = min; + } + return param; +} + +/** + * Retrieve and bounds-check the cbtrecentcount consensus paramter. + * + * Effect: This is the number of circuit build times to keep track of + * for deciding if we hit cbtmaxtimeouts and need to reset our state + * and learn a new timeout. + */ +static int32_t +circuit_build_times_recent_circuit_count(networkstatus_t *ns) +{ + int32_t num; + num = networkstatus_get_param(ns, "cbtrecentcount", + CBT_DEFAULT_RECENT_CIRCUITS, + CBT_MIN_RECENT_CIRCUITS, + CBT_MAX_RECENT_CIRCUITS); + + if (!(get_options()->LearnCircuitBuildTimeout)) { + log_debug(LD_BUG, + "circuit_build_times_recent_circuit_count() called, " + "cbtrecentcount is %d", + num); + } + + 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; + + /* + * First check if we're doing adaptive timeouts at all; nothing to + * update if we aren't. + */ + + if (!circuit_build_times_disabled()) { + num = circuit_build_times_recent_circuit_count(ns); + + if (num > 0) { + if (num != cbt->liveness.num_recent_circs) { + int8_t *recent_circs; + log_notice(LD_CIRC, "The Tor Directory Consensus has changed how many " + "circuits we must track to detect network failures from %d " + "to %d.", cbt->liveness.num_recent_circs, num); + + tor_assert(cbt->liveness.timeouts_after_firsthop || + cbt->liveness.num_recent_circs == 0); + + /* + * 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); + if (cbt->liveness.timeouts_after_firsthop && + cbt->liveness.num_recent_circs > 0) { + 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; + } + /* else no change, nothing to do */ + } else { /* num == 0 */ + /* + * Weird. This probably shouldn't happen, so log a warning, but try + * to do something sensible anyway. + */ + + log_warn(LD_CIRC, + "The cbtrecentcircs consensus parameter came back zero! " + "This disables adaptive timeouts since we can't keep track of " + "any recent circuits."); + + circuit_build_times_free_timeouts(cbt); + } + } else { + /* + * Adaptive timeouts are disabled; this might be because of the + * LearnCircuitBuildTimes config parameter, and hence permanent, or + * the cbtdisabled consensus parameter, so it may be a new condition. + * Treat it like getting num == 0 above and free the circuit history + * if we have any. + */ + + circuit_build_times_free_timeouts(cbt); + } +} + +/** + * Return the initial default or configured timeout in milliseconds + */ +static double +circuit_build_times_get_initial_timeout(void) +{ + double timeout; + + /* + * Check if we have LearnCircuitBuildTimeout, and if we don't, + * always use CircuitBuildTimeout, no questions asked. + */ + if (!unit_tests && get_options()->CircuitBuildTimeout) { + timeout = get_options()->CircuitBuildTimeout*1000; + if (get_options()->LearnCircuitBuildTimeout && + 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)); + /* + * Check if we really are using adaptive timeouts, and don't keep + * track of this stuff if not. + */ + if (!circuit_build_times_disabled()) { + cbt->liveness.num_recent_circs = + circuit_build_times_recent_circuit_count(NULL); + cbt->liveness.timeouts_after_firsthop = + tor_malloc_zero(sizeof(int8_t)*cbt->liveness.num_recent_circs); + } else { + cbt->liveness.num_recent_circs = 0; + cbt->liveness.timeouts_after_firsthop = NULL; + } + cbt->close_ms = cbt->timeout_ms = circuit_build_times_get_initial_timeout(); + control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET); +} + +/** + * Free the saved timeouts, if the cbtdisabled consensus parameter got turned + * on or something. + */ + +void +circuit_build_times_free_timeouts(circuit_build_times_t *cbt) +{ + if (!cbt) return; + + if (cbt->liveness.timeouts_after_firsthop) { + tor_free(cbt->liveness.timeouts_after_firsthop); + } + + cbt->liveness.num_recent_circs = 0; +} + +#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</b> 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 most frequent build time bins. N is either + * 1 if we don't have enough circuit build time data collected, or + * determined by the consensus parameter cbtnummodes (default 3). + */ +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(); + + tor_assert(nbins > 0); + tor_assert(num_modes > 0); + + // 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)); + + /* Determine the N most common build times */ + 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]]); + } + + /* The following assert is safe, because we don't get called when we + * haven't observed at least CBT_MIN_MIN_CIRCUITS_TO_OBSERVE circuits. */ + tor_assert(bin_counts > 0); + + 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"); + tor_asprintf(&line->value, "%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. + * + * Adapted from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + */ +static void +circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, + build_time_t *raw_times, + uint32_t num_times) +{ + uint32_t n = num_times; + if (num_times > CBT_NCIRCUITS_TO_OBSERVE) { + log_notice(LD_CIRC, "The number of circuit times that this Tor version " + "uses to calculate build times is less than the number stored " + "in your state file. Decreasing the circuit time history from " + "%lu to %d.", (unsigned long)num_times, + CBT_NCIRCUITS_TO_OBSERVE); + } + + if (n > INT_MAX-1) { + log_warn(LD_CIRC, "For some insane reasons, you had %lu circuit build " + "observations in your state file. That's far too many; probably " + "there's a bug here.", (unsigned long)n); + n = INT_MAX-1; + } + + /* This code can only be run on a compact array */ + 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_new(); + 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) +{ + /* Check for NULLness because we might not be using adaptive timeouts */ + if (cbt->liveness.timeouts_after_firsthop && + cbt->liveness.num_recent_circs > 0) { + 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) +{ + /* Check for NULLness because we might not be using adaptive timeouts */ + if (cbt->liveness.timeouts_after_firsthop && + cbt->liveness.num_recent_circs > 0) { + 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_notice(LD_CIRC, + "A circuit somehow completed a hop while the network was " + "not live. The network was last live at %s, but the circuit " + "launched at %s. It's now %s. This could mean your clock " + "changed.", 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 recording.", + (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; + + if (cbt->liveness.timeouts_after_firsthop && + cbt->liveness.num_recent_circs > 0) { + /* 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); + if (cbt->liveness.timeouts_after_firsthop && + cbt->liveness.num_recent_circs > 0) { + 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 = %fmsec, close = %fmsec)", + 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, + "Your 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); + + if (cbt->timeout_ms > max_time) { + log_info(LD_CIRC, + "Circuit build timeout of %dms is beyond the maximum build " + "time we have ever observed. Capping it to %dms.", + (int)cbt->timeout_ms, max_time); + cbt->timeout_ms = max_time; + } + + if (max_time < INT32_MAX/2 && cbt->close_ms > 2*max_time) { + log_info(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; + } + + /* 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()); + + 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; + + /* + * Just return if we aren't using adaptive timeouts + */ + if (circuit_build_times_disabled()) + return; + + if (!circuit_build_times_set_timeout_worker(cbt)) + return; + + if (cbt->timeout_ms < circuit_build_times_min_timeout()) { + log_info(LD_CIRC, "Set buildtimeout to low value %fms. Setting to %dms", + cbt->timeout_ms, circuit_build_times_min_timeout()); + cbt->timeout_ms = circuit_build_times_min_timeout(); + if (cbt->close_ms < cbt->timeout_ms) { + /* 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_info(LD_CIRC, + "Based on %d circuit times, it looks like we don't need to " + "wait so long for circuits to finish. We will now assume a " + "circuit is too slow to use after waiting %ld seconds.", + cbt->total_build_times, + tor_lround(cbt->timeout_ms/1000)); + log_info(LD_CIRC, + "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f", + cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, + timeout_rate); + } else if (prev_timeout < tor_lround(cbt->timeout_ms/1000)) { + log_info(LD_CIRC, + "Based on %d circuit times, it looks like we need to wait " + "longer for circuits to finish. We will now assume a " + "circuit is too slow to use after waiting %ld seconds.", + cbt->total_build_times, + tor_lround(cbt->timeout_ms/1000)); + log_info(LD_CIRC, + "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f", + cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, + timeout_rate); + } else { + log_info(LD_CIRC, + "Set circuit build timeout to %lds (%fms, %fms, Xm: %d, a: %f," + " r: %f) based on %d circuit times", + tor_lround(cbt->timeout_ms/1000), + cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, timeout_rate, + cbt->total_build_times); + } +} +/** 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; +} + diff --git a/src/or/circuitstats.h b/src/or/circuitstats.h new file mode 100644 index 0000000000..87dce99f4f --- /dev/null +++ b/src/or/circuitstats.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-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file circuitstats.h + * \brief Header file for circuitstats.c + **/ + +#ifndef TOR_CIRCUITSTATS_H +#define TOR_CIRCUITSTATS_H + +extern circuit_build_times_t circ_times; + +int circuit_build_times_disabled(void); +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_free_timeouts(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 CIRCUITSTATS_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); + +/* DOCDOC circuit_build_times_get_bw_scale */ +int circuit_build_times_get_bw_scale(networkstatus_t *ns); + +#endif + diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 7218ecc077..c2d2b2e87c 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,13 +10,17 @@ **/ #include "or.h" +#include "addressmap.h" +#include "channel.h" #include "circuitbuild.h" #include "circuitlist.h" +#include "circuitstats.h" #include "circuituse.h" #include "config.h" #include "connection.h" #include "connection_edge.h" #include "control.h" +#include "entrynodes.h" #include "nodelist.h" #include "networkstatus.h" #include "policies.h" @@ -53,7 +57,7 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, tor_assert(conn); tor_assert(conn->socks_request); - if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn)) + if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_chan)) return 0; /* ignore non-open circs */ if (circ->marked_for_close) return 0; @@ -81,10 +85,14 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, } if (purpose == CIRCUIT_PURPOSE_C_GENERAL || - purpose == CIRCUIT_PURPOSE_C_REND_JOINED) + purpose == CIRCUIT_PURPOSE_C_REND_JOINED) { if (circ->timestamp_dirty && circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now) return 0; + } + + if (origin_circ->unusable_for_new_conns) + return 0; /* decide if this circ is suitable for this conn */ @@ -101,6 +109,8 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, return 0; if (purpose == CIRCUIT_PURPOSE_C_GENERAL) { + tor_addr_t addr; + const int family = tor_addr_parse(&addr, conn->socks_request->address); if (!exitnode && !build_state->onehop_tunnel) { log_debug(LD_CIRC,"Not considering circuit with unknown router."); return 0; /* this circuit is screwed and doesn't know it yet, @@ -121,9 +131,7 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, return 0; /* this is a circuit to somewhere else */ if (tor_digest_is_zero(digest)) { /* we don't know the digest; have to compare addr:port */ - tor_addr_t addr; - int r = tor_addr_parse(&addr, conn->socks_request->address); - if (r < 0 || + if (family < 0 || !tor_addr_eq(&build_state->chosen_exit->addr, &addr) || build_state->chosen_exit->port != conn->socks_request->port) return 0; @@ -135,6 +143,13 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, return 0; } } + if (origin_circ->prepend_policy && family != -1) { + int r = compare_tor_addr_to_addr_policy(&addr, + conn->socks_request->port, + origin_circ->prepend_policy); + if (r == ADDR_POLICY_REJECTED) + return 0; + } if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) { /* can't exit from this router */ return 0; @@ -172,6 +187,13 @@ circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob, const uint8_t purpose = ENTRY_TO_CONN(conn)->purpose; int a_bits, b_bits; + /* If one of the circuits was allowed to live due to relaxing its timeout, + * it is definitely worse (it's probably a much slower path). */ + if (oa->relaxed_timeout && !ob->relaxed_timeout) + return 0; /* ob is better. It's not relaxed. */ + if (!oa->relaxed_timeout && ob->relaxed_timeout) + return 1; /* oa is better. It's not relaxed. */ + switch (purpose) { case CIRCUIT_PURPOSE_C_GENERAL: /* if it's used but less dirty it's best; @@ -183,7 +205,7 @@ circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob, return 1; } else { if (a->timestamp_dirty || - timercmp(&a->timestamp_created, &b->timestamp_created, >)) + timercmp(&a->timestamp_began, &b->timestamp_began, >)) return 1; if (ob->build_state->is_internal) /* XXX023 what the heck is this internal thing doing here. I @@ -269,17 +291,19 @@ circuit_get_best(const entry_connection_t *conn, if (!CIRCUIT_IS_ORIGIN(circ)) continue; origin_circ = TO_ORIGIN_CIRCUIT(circ); - if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose, - need_uptime,need_internal,now.tv_sec)) - continue; + /* Log an info message if we're going to launch a new intro circ in + * parallel */ if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT && - !must_be_open && circ->state != CIRCUIT_STATE_OPEN && - tv_mdiff(&now, &circ->timestamp_created) > circ_times.timeout_ms) { - intro_going_on_but_too_old = 1; - continue; + !must_be_open && origin_circ->hs_circ_has_timed_out) { + intro_going_on_but_too_old = 1; + continue; } + if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose, + need_uptime,need_internal,now.tv_sec)) + continue; + /* now this is an acceptable circ to hand back. but that doesn't * mean it's the *best* circ to hand back. try to decide. */ @@ -356,13 +380,38 @@ circuit_expire_building(void) * circuit_build_times_get_initial_timeout() if we haven't computed * custom timeouts yet */ struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff, - cannibalize_cutoff, close_cutoff, extremely_old_cutoff, - hs_extremely_old_cutoff; + close_cutoff, extremely_old_cutoff, hs_extremely_old_cutoff, + cannibalized_cutoff, c_intro_cutoff, s_intro_cutoff, stream_cutoff; const or_options_t *options = get_options(); struct timeval now; cpath_build_state_t *build_state; + int any_opened_circs = 0; tor_gettimeofday(&now); + + /* Check to see if we have any opened circuits. If we don't, + * we want to be more lenient with timeouts, in case the + * user has relocated and/or changed network connections. + * See bug #3443. */ + while (next_circ) { + if (!CIRCUIT_IS_ORIGIN(next_circ) || /* didn't originate here */ + next_circ->marked_for_close) { /* don't mess with marked circs */ + next_circ = next_circ->next; + continue; + } + + if (TO_ORIGIN_CIRCUIT(next_circ)->has_opened && + next_circ->state == CIRCUIT_STATE_OPEN && + TO_ORIGIN_CIRCUIT(next_circ)->build_state && + TO_ORIGIN_CIRCUIT(next_circ)->build_state->desired_path_len + == DEFAULT_ROUTE_LEN) { + any_opened_circs = 1; + break; + } + next_circ = next_circ->next; + } + next_circ = global_circuitlist; + #define SET_CUTOFF(target, msec) do { \ long ms = tor_lround(msec); \ struct timeval diff; \ @@ -371,10 +420,60 @@ circuit_expire_building(void) timersub(&now, &diff, &target); \ } while (0) + /** + * Because circuit build timeout is calculated only based on 3 hop + * general purpose circuit construction, we need to scale the timeout + * to make it properly apply to longer circuits, and circuits of + * certain usage types. The following diagram illustrates how we + * derive the scaling below. In short, we calculate the number + * of times our telescoping-based circuit construction causes cells + * to traverse each link for the circuit purpose types in question, + * and then assume each link is equivalent. + * + * OP --a--> A --b--> B --c--> C + * OP --a--> A --b--> B --c--> C --d--> D + * + * Let h = a = b = c = d + * + * Three hops (general_cutoff) + * RTTs = 3a + 2b + c + * RTTs = 6h + * Cannibalized: + * RTTs = a+b+c+d + * RTTs = 4h + * Four hops: + * RTTs = 4a + 3b + 2c + d + * RTTs = 10h + * Client INTRODUCE1+ACK: // XXX: correct? + * RTTs = 5a + 4b + 3c + 2d + * RTTs = 14h + * Server intro: + * RTTs = 4a + 3b + 2c + * RTTs = 9h + */ SET_CUTOFF(general_cutoff, circ_times.timeout_ms); SET_CUTOFF(begindir_cutoff, circ_times.timeout_ms); - SET_CUTOFF(fourhop_cutoff, circ_times.timeout_ms * (4/3.0)); - SET_CUTOFF(cannibalize_cutoff, circ_times.timeout_ms / 2.0); + + /* > 3hop circs seem to have a 1.0 second delay on their cannibalized + * 4th hop. */ + SET_CUTOFF(fourhop_cutoff, circ_times.timeout_ms * (10/6.0) + 1000); + + /* CIRCUIT_PURPOSE_C_ESTABLISH_REND behaves more like a RELAY cell. + * Use the stream cutoff (more or less). */ + SET_CUTOFF(stream_cutoff, MAX(options->CircuitStreamTimeout,15)*1000 + 1000); + + /* Be lenient with cannibalized circs. They already survived the official + * CBT, and they're usually not performance-critical. */ + SET_CUTOFF(cannibalized_cutoff, + MAX(circ_times.close_ms*(4/6.0), + options->CircuitStreamTimeout * 1000) + 1000); + + /* Intro circs have an extra round trip (and are also 4 hops long) */ + SET_CUTOFF(c_intro_cutoff, circ_times.timeout_ms * (14/6.0) + 1000); + + /* Server intro circs have an extra round trip */ + SET_CUTOFF(s_intro_cutoff, circ_times.timeout_ms * (9/6.0) + 1000); + SET_CUTOFF(close_cutoff, circ_times.close_ms); SET_CUTOFF(extremely_old_cutoff, circ_times.close_ms*2 + 1000); @@ -387,28 +486,95 @@ circuit_expire_building(void) 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 */ + victim->marked_for_close) /* don't mess with marked circs */ + continue; + + /* If we haven't yet started the first hop, it means we don't have + * any orconns available, and thus have not started counting time yet + * for this circuit. See circuit_deliver_create_cell() and uses of + * timestamp_began. + * + * Continue to wait in this case. The ORConn should timeout + * independently and kill us then. + */ + if (TO_ORIGIN_CIRCUIT(victim)->cpath->state == CPATH_STATE_CLOSED) { continue; + } 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_MEASURE_TIMEOUT) cutoff = close_cutoff; + else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING || + victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) + cutoff = c_intro_cutoff; + else if (victim->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) + cutoff = s_intro_cutoff; + else if (victim->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND) + cutoff = stream_cutoff; + else if (victim->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + cutoff = close_cutoff; + else if (TO_ORIGIN_CIRCUIT(victim)->has_opened && + victim->state != CIRCUIT_STATE_OPEN) + cutoff = cannibalized_cutoff; + else if (build_state && build_state->desired_path_len >= 4) + cutoff = fourhop_cutoff; else cutoff = general_cutoff; if (TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out) cutoff = hs_extremely_old_cutoff; - if (timercmp(&victim->timestamp_created, &cutoff, >)) + if (timercmp(&victim->timestamp_began, &cutoff, >)) continue; /* it's still young, leave it alone */ + /* We need to double-check the opened state here because + * we don't want to consider opened 1-hop dircon circuits for + * deciding when to relax the timeout, but we *do* want to relax + * those circuits too if nothing else is opened *and* they still + * aren't either. */ + if (!any_opened_circs && victim->state != CIRCUIT_STATE_OPEN) { + /* It's still young enough that we wouldn't close it, right? */ + if (timercmp(&victim->timestamp_began, &close_cutoff, >)) { + if (!TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout) { + int first_hop_succeeded = TO_ORIGIN_CIRCUIT(victim)->cpath->state + == CPATH_STATE_OPEN; + log_info(LD_CIRC, + "No circuits are opened. Relaxing timeout for circuit %d " + "(a %s %d-hop circuit in state %s with channel state %s). " + "%d guards are live.", + TO_ORIGIN_CIRCUIT(victim)->global_identifier, + circuit_purpose_to_string(victim->purpose), + TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len, + circuit_state_to_string(victim->state), + channel_state_to_string(victim->n_chan->state), + num_live_entry_guards(0)); + + /* We count the timeout here for CBT, because technically this + * was a timeout, and the timeout value needs to reset if we + * see enough of them. Note this means we also need to avoid + * double-counting below, too. */ + circuit_build_times_count_timeout(&circ_times, first_hop_succeeded); + TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout = 1; + } + continue; + } else { + static ratelim_t relax_timeout_limit = RATELIM_INIT(3600); + log_fn_ratelim(&relax_timeout_limit, LOG_NOTICE, LD_CIRC, + "No circuits are opened. Relaxed timeout for circuit %d " + "(a %s %d-hop circuit in state %s with channel state %s) to " + "%ldms. However, it appears the circuit has timed out " + "anyway. %d guards are live.", + TO_ORIGIN_CIRCUIT(victim)->global_identifier, + circuit_purpose_to_string(victim->purpose), + TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len, + circuit_state_to_string(victim->state), + channel_state_to_string(victim->n_chan->state), + (long)circ_times.close_ms, num_live_entry_guards(0)); + } + } + #if 0 /* some debug logs, to help track bugs */ if (victim->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING && @@ -436,8 +602,6 @@ circuit_expire_building(void) default: /* most open circuits can be left alone. */ continue; /* yes, continue inside a switch refers to the nearest * enclosing loop. C is smart. */ - case CIRCUIT_PURPOSE_C_ESTABLISH_REND: - case CIRCUIT_PURPOSE_C_INTRODUCING: case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: break; /* too old, need to die */ case CIRCUIT_PURPOSE_C_REND_READY: @@ -449,6 +613,19 @@ circuit_expire_building(void) victim->timestamp_dirty > cutoff.tv_sec) continue; break; + case CIRCUIT_PURPOSE_PATH_BIAS_TESTING: + /* Open path bias testing circuits are given a long + * time to complete the test, but not forever */ + TO_ORIGIN_CIRCUIT(victim)->path_state = PATH_STATE_USE_FAILED; + break; + case CIRCUIT_PURPOSE_C_INTRODUCING: + /* We keep old introducing circuits around for + * a while in parallel, and they can end up "opened". + * We decide below if we're going to mark them timed + * out and eventually close them. + */ + break; + case CIRCUIT_PURPOSE_C_ESTABLISH_REND: case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: /* rend and intro circs become dirty each time they @@ -485,9 +662,12 @@ circuit_expire_building(void) /* 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); + * have a timeout. We also want to avoid double-counting + * already "relaxed" circuits, which are counted above. */ + if (!TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout) { + circuit_build_times_count_timeout(&circ_times, + first_hop_succeeded); + } continue; } @@ -496,11 +676,11 @@ circuit_expire_building(void) * it off at, we probably had a suspend event along this codepath, * and we should discard the value. */ - if (timercmp(&victim->timestamp_created, &extremely_old_cutoff, <)) { + if (timercmp(&victim->timestamp_began, &extremely_old_cutoff, <)) { log_notice(LD_CIRC, "Extremely large value for circuit build timeout: %lds. " "Assuming clock jump. Purpose %d (%s)", - (long)(now.tv_sec - victim->timestamp_created.tv_sec), + (long)(now.tv_sec - victim->timestamp_began.tv_sec), victim->purpose, circuit_purpose_to_string(victim->purpose)); } else if (circuit_build_times_count_close(&circ_times, @@ -534,12 +714,15 @@ circuit_expire_building(void) if (TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath == NULL) break; + /* fallthrough! */ + case CIRCUIT_PURPOSE_C_INTRODUCING: + /* connection_ap_handshake_attach_circuit() will relaunch for us */ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: /* If we have reached this line, we want to spare the circ for now. */ - log_info(LD_CIRC,"Marking circ %d (state %d:%s, purpose %d) " + log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) " "as timed-out HS circ", - victim->n_circ_id, + (unsigned)victim->n_circ_id, victim->state, circuit_state_to_string(victim->state), victim->purpose); TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1; @@ -555,9 +738,9 @@ circuit_expire_building(void) if (!(options->CloseHSServiceRendCircuitsImmediatelyOnTimeout) && !(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out) && victim->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) { - log_info(LD_CIRC,"Marking circ %d (state %d:%s, purpose %d) " + log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) " "as timed-out HS circ; relaunching rendezvous attempt.", - victim->n_circ_id, + (unsigned)victim->n_circ_id, victim->state, circuit_state_to_string(victim->state), victim->purpose); TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1; @@ -565,22 +748,33 @@ circuit_expire_building(void) continue; } - if (victim->n_conn) - log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)", - victim->n_conn->_base.address, victim->n_conn->_base.port, - victim->n_circ_id, + if (victim->n_chan) + log_info(LD_CIRC, + "Abandoning circ %u %s:%d (state %d,%d:%s, purpose %d, " + "len %d)", TO_ORIGIN_CIRCUIT(victim)->global_identifier, + channel_get_canonical_remote_descr(victim->n_chan), + (unsigned)victim->n_circ_id, + TO_ORIGIN_CIRCUIT(victim)->has_opened, victim->state, circuit_state_to_string(victim->state), - victim->purpose); + victim->purpose, + TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len); else - log_info(LD_CIRC,"Abandoning circ %d (state %d:%s, purpose %d)", - victim->n_circ_id, victim->state, - circuit_state_to_string(victim->state), victim->purpose); + log_info(LD_CIRC, + "Abandoning circ %u %d (state %d,%d:%s, purpose %d, len %d)", + TO_ORIGIN_CIRCUIT(victim)->global_identifier, + (unsigned)victim->n_circ_id, + TO_ORIGIN_CIRCUIT(victim)->has_opened, + victim->state, + circuit_state_to_string(victim->state), victim->purpose, + TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len); circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim)); 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); + + pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim)); } } @@ -620,7 +814,8 @@ circuit_stream_is_being_handled(entry_connection_t *conn, const node_t *exitnode; int num=0; time_t now = time(NULL); - int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts, + int need_uptime = smartlist_contains_int_as_string( + get_options()->LongLivedPorts, conn ? conn->socks_request->port : port); for (circ=global_circuitlist;circ;circ = circ->next) { @@ -629,9 +824,12 @@ circuit_stream_is_being_handled(entry_connection_t *conn, circ->purpose == CIRCUIT_PURPOSE_C_GENERAL && (!circ->timestamp_dirty || circ->timestamp_dirty + get_options()->MaxCircuitDirtiness > now)) { - cpath_build_state_t *build_state = TO_ORIGIN_CIRCUIT(circ)->build_state; + origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); + cpath_build_state_t *build_state = origin_circ->build_state; if (build_state->is_internal || build_state->onehop_tunnel) continue; + if (origin_circ->unusable_for_new_conns) + continue; exitnode = build_state_get_exit_node(build_state); if (exitnode && (!need_uptime || build_state->need_uptime)) { @@ -673,6 +871,7 @@ circuit_predict_and_launch_new(void) /* First, count how many of each type of circuit we have already. */ for (circ=global_circuitlist;circ;circ = circ->next) { cpath_build_state_t *build_state; + origin_circuit_t *origin_circ; if (!CIRCUIT_IS_ORIGIN(circ)) continue; if (circ->marked_for_close) @@ -681,7 +880,10 @@ circuit_predict_and_launch_new(void) continue; /* only count clean circs */ if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL) continue; /* only pay attention to general-purpose circs */ - build_state = TO_ORIGIN_CIRCUIT(circ)->build_state; + origin_circ = TO_ORIGIN_CIRCUIT(circ); + if (origin_circ->unusable_for_new_conns) + continue; + build_state = origin_circ->build_state; if (build_state->onehop_tunnel) continue; num++; @@ -787,7 +989,7 @@ circuit_build_needed_circs(time_t now) circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL); if (get_options()->RunTesting && circ && - circ->timestamp_created.tv_sec + TESTING_CIRCUIT_INTERVAL < now) { + circ->timestamp_began.tv_sec + TESTING_CIRCUIT_INTERVAL < now) { log_fn(LOG_INFO,"Creating a new testing circuit."); circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0); } @@ -808,7 +1010,7 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) tor_assert(circ); tor_assert(conn); - if (conn->_base.type == CONN_TYPE_AP) { + if (conn->base_.type == CONN_TYPE_AP) { entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); entry_conn->may_use_optimistic_data = 0; } @@ -901,13 +1103,17 @@ circuit_expire_old_circuits_clientside(void) circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now.tv_sec && !TO_ORIGIN_CIRCUIT(circ)->p_streams /* nothing attached */ ) { - log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %ld sec ago, " + log_debug(LD_CIRC, "Closing n_circ_id %u (dirty %ld sec ago, " "purpose %d)", - circ->n_circ_id, (long)(now.tv_sec - circ->timestamp_dirty), + (unsigned)circ->n_circ_id, + (long)(now.tv_sec - circ->timestamp_dirty), circ->purpose); - circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); + /* Don't do this magic for testing circuits. Their death is governed + * by circuit_expire_building */ + if (circ->purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } else if (!circ->timestamp_dirty && circ->state == CIRCUIT_STATE_OPEN) { - if (timercmp(&circ->timestamp_created, &cutoff, <)) { + if (timercmp(&circ->timestamp_began, &cutoff, <)) { if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL || circ->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT || circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -917,7 +1123,7 @@ circuit_expire_old_circuits_clientside(void) circ->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) { log_debug(LD_CIRC, "Closing circuit that has been unused for %ld msec.", - tv_mdiff(&circ->timestamp_created, &now)); + tv_mdiff(&circ->timestamp_began, &now)); 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 @@ -931,7 +1137,7 @@ circuit_expire_old_circuits_clientside(void) "Ancient non-dirty circuit %d is still around after " "%ld milliseconds. Purpose: %d (%s)", TO_ORIGIN_CIRCUIT(circ)->global_identifier, - tv_mdiff(&circ->timestamp_created, &now), + tv_mdiff(&circ->timestamp_began, &now), circ->purpose, circuit_purpose_to_string(circ->purpose)); TO_ORIGIN_CIRCUIT(circ)->is_ancient = 1; @@ -977,13 +1183,13 @@ circuit_expire_old_circuits_serverside(time_t now) /* If the circuit has been idle for too long, and there are no streams * on it, and it ends here, and it used a create_fast, mark it for close. */ - if (or_circ->is_first_hop && !circ->n_conn && + if (or_circ->is_first_hop && !circ->n_chan && !or_circ->n_streams && !or_circ->resolving_streams && - or_circ->p_conn && - or_circ->p_conn->timestamp_last_added_nonpadding <= cutoff) { - log_info(LD_CIRC, "Closing circ_id %d (empty %d secs ago)", - or_circ->p_circ_id, - (int)(now - or_circ->p_conn->timestamp_last_added_nonpadding)); + or_circ->p_chan && + channel_when_last_xmit(or_circ->p_chan) <= cutoff) { + log_info(LD_CIRC, "Closing circ_id %u (empty %d secs ago)", + (unsigned)or_circ->p_circ_id, + (int)(now - channel_when_last_xmit(or_circ->p_chan))); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } } @@ -1125,7 +1331,7 @@ static int circuit_try_clearing_isolation_state(origin_circuit_t *circ) { if (/* The circuit may have become non-open if it was cannibalized.*/ - circ->_base.state == CIRCUIT_STATE_OPEN && + circ->base_.state == CIRCUIT_STATE_OPEN && /* If !isolation_values_set, there is nothing to clear. */ circ->isolation_values_set && /* It's not legal to clear a circuit's isolation info if it's ever had @@ -1163,6 +1369,7 @@ circuit_try_attaching_streams(origin_circuit_t *circ) void circuit_build_failed(origin_circuit_t *circ) { + channel_t *n_chan = NULL; /* we should examine circ and see if it failed because of * the last hop or an earlier hop. then use this info below. */ @@ -1179,11 +1386,12 @@ circuit_build_failed(origin_circuit_t *circ) /* We failed at the first hop. If there's an OR connection * 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; + const char *n_chan_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) { + if (circ->base_.n_chan) { + n_chan = circ->base_.n_chan; + + if (n_chan->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 @@ -1195,22 +1403,22 @@ circuit_build_failed(origin_circuit_t *circ) } 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; + "(%s). I'm going to try to rotate to a better connection.", + channel_get_canonical_remote_descr(n_chan)); + n_chan->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 && !already_marked) { - entry_guard_register_connect_status(n_conn_id, 0, 1, time(NULL)); + if (n_chan_id && !already_marked) { + entry_guard_register_connect_status(n_chan_id, 0, 1, time(NULL)); /* if there are any one-hop streams waiting on this circuit, fail * them now so they can retry elsewhere. */ - connection_ap_fail_onehop(n_conn_id, circ->build_state); + connection_ap_fail_onehop(n_chan_id, circ->build_state); } } - switch (circ->_base.purpose) { + switch (circ->base_.purpose) { case CIRCUIT_PURPOSE_C_GENERAL: /* If we never built the circuit, note it as a failure. */ circuit_increment_failure_count(); @@ -1225,7 +1433,7 @@ circuit_build_failed(origin_circuit_t *circ) break; case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: /* at Bob, waiting for introductions */ - if (circ->_base.state != CIRCUIT_STATE_OPEN) { + if (circ->base_.state != CIRCUIT_STATE_OPEN) { circuit_increment_failure_count(); } /* no need to care here, because bob will rebuild intro @@ -1309,21 +1517,46 @@ circuit_launch_by_extend_info(uint8_t purpose, * internal circs rather than exit circs? -RD */ circ = circuit_find_to_cannibalize(purpose, extend_info, flags); if (circ) { - uint8_t old_purpose = circ->_base.purpose; - struct timeval old_timestamp_created = circ->_base.timestamp_created; + uint8_t old_purpose = circ->base_.purpose; + struct timeval old_timestamp_began = circ->base_.timestamp_began; log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d (%s)", build_state_get_exit_nickname(circ->build_state), purpose, circuit_purpose_to_string(purpose)); + if ((purpose == CIRCUIT_PURPOSE_S_CONNECT_REND || + purpose == CIRCUIT_PURPOSE_C_INTRODUCING) && + circ->path_state == PATH_STATE_BUILD_SUCCEEDED) { + /* Path bias: Cannibalized rends pre-emptively count as a + * successfully built but unused closed circuit. We don't + * wait until the extend (or the close) because the rend + * point could be malicious. + * + * Same deal goes for client side introductions. Clients + * can be manipulated to connect repeatedly to them + * (especially web clients). + * + * If we decide to probe the initial portion of these circs, + * (up to the adversary's final hop), we need to remove this, + * or somehow mark the circuit with a special path state. + */ + + /* This must be called before the purpose change */ + pathbias_check_close(circ, END_CIRC_REASON_FINISHED); + } + circuit_change_purpose(TO_CIRCUIT(circ), purpose); - /* reset the birth date of this circ, else expire_building + /* Reset the start date of this circ, else expire_building * will see it and think it's been trying to build since it - * began. */ - tor_gettimeofday(&circ->_base.timestamp_created); + * began. + * + * Technically, the code should reset this when the + * create cell is finally sent, but we're close enough + * here. */ + tor_gettimeofday(&circ->base_.timestamp_began); control_event_circuit_cannibalized(circ, old_purpose, - &old_timestamp_created); + &old_timestamp_began); switch (purpose) { case CIRCUIT_PURPOSE_C_ESTABLISH_REND: @@ -1412,7 +1645,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, want_onehop = conn->want_onehop; need_uptime = !conn->want_onehop && !conn->use_begindir && - smartlist_string_num_isin(options->LongLivedPorts, + smartlist_contains_int_as_string(options->LongLivedPorts, conn->socks_request->port); if (desired_circuit_purpose != CIRCUIT_PURPOSE_C_GENERAL) @@ -1513,8 +1746,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, if ((m = rate_limit_log(&delay_limit, approx_time()))) { log_notice(LD_APP, "We'd like to launch a circuit to handle a " "connection, but we already have %d general-purpose client " - "circuits pending. Waiting until some finish.", - n_pending); + "circuits pending. Waiting until some finish.%s", + n_pending, m); tor_free(m); } return 0; @@ -1570,9 +1803,9 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, escaped_safe_str_client(conn->socks_request->address)); return -1; } - extend_info = extend_info_alloc(conn->chosen_exit_name+1, - digest, NULL, &addr, - conn->socks_request->port); + extend_info = extend_info_new(conn->chosen_exit_name+1, + digest, NULL, NULL, &addr, + conn->socks_request->port); } else { /* We will need an onion key for the router, and we * don't have one. Refuse or relax requirements. */ @@ -1634,8 +1867,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, if (circ) { /* write the service_id into circ */ circ->rend_data = rend_data_dup(ENTRY_TO_EDGE_CONN(conn)->rend_data); - if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND && - circ->_base.state == CIRCUIT_STATE_OPEN) + if (circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND && + circ->base_.state == CIRCUIT_STATE_OPEN) rend_client_rendcirc_has_opened(circ); } } @@ -1697,8 +1930,8 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, const node_t *exitnode; /* add it into the linked list of streams on this circuit */ - log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.", - circ->_base.n_circ_id); + log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %u.", + (unsigned)circ->base_.n_circ_id); /* reset it, so we can measure circ timeouts */ ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL); ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams; @@ -1734,7 +1967,7 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, exitnode->rs) { /* Okay; we know what exit node this is. */ if (optimistic_data_enabled() && - circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL && + circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL && exitnode->rs->version_supports_optimistic_data) apconn->may_use_optimistic_data = 1; else @@ -1820,12 +2053,14 @@ connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn, base_conn->state == AP_CONN_STATE_CONTROLLER_WAIT); tor_assert(conn->socks_request); tor_assert(circ); - tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN); + tor_assert(circ->base_.state == CIRCUIT_STATE_OPEN); base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; - if (!circ->_base.timestamp_dirty) - circ->_base.timestamp_dirty = time(NULL); + if (!circ->base_.timestamp_dirty) + circ->base_.timestamp_dirty = time(NULL); + + pathbias_count_use_attempt(circ); link_apconn_to_circ(conn, circ, cpath); tor_assert(conn->socks_request); @@ -1920,8 +2155,8 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) return retval; log_debug(LD_APP|LD_CIRC, - "Attaching apconn to circ %d (stream %d sec old).", - circ->_base.n_circ_id, conn_age); + "Attaching apconn to circ %u (stream %d sec old).", + (unsigned)circ->base_.n_circ_id, conn_age); /* print the circ's path, so people can figure out which circs are * sucking. */ circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ); @@ -1946,25 +2181,30 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) log_info(LD_REND, "rend joined circ %d already here. attaching. " "(stream %d sec old)", - rendcirc->_base.n_circ_id, conn_age); + (unsigned)rendcirc->base_.n_circ_id, conn_age); /* Mark rendezvous circuits as 'newly dirty' every time you use * them, since the process of rebuilding a rendezvous circ is so * expensive. There is a tradeoff between linkability and * feasibility, at this point. */ - rendcirc->_base.timestamp_dirty = time(NULL); + rendcirc->base_.timestamp_dirty = time(NULL); + + /* We've also attempted to use them. If they fail, we need to + * probe them for path bias */ + pathbias_count_use_attempt(rendcirc); + link_apconn_to_circ(conn, rendcirc, NULL); if (connection_ap_handshake_send_begin(conn) < 0) return 0; /* already marked, let them fade away */ return 1; } - if (rendcirc && (rendcirc->_base.purpose == + if (rendcirc && (rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)) { log_info(LD_REND, - "pending-join circ %d already here, with intro ack. " + "pending-join circ %u already here, with intro ack. " "Stalling. (stream %d sec old)", - rendcirc->_base.n_circ_id, conn_age); + (unsigned)rendcirc->base_.n_circ_id, conn_age); return 0; } @@ -1975,51 +2215,40 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) if (retval > 0) { /* one has already sent the intro. keep waiting. */ - circuit_t *c = NULL; tor_assert(introcirc); - log_info(LD_REND, "Intro circ %d present and awaiting ack (rend %d). " + log_info(LD_REND, "Intro circ %u present and awaiting ack (rend %u). " "Stalling. (stream %d sec old)", - introcirc->_base.n_circ_id, - rendcirc ? rendcirc->_base.n_circ_id : 0, + (unsigned)introcirc->base_.n_circ_id, + rendcirc ? (unsigned)rendcirc->base_.n_circ_id : 0, conn_age); - /* abort parallel intro circs, if any */ - for (c = global_circuitlist; c; c = c->next) { - if (c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING && - !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { - origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c); - if (oc->rend_data && - !rend_cmp_service_ids( - ENTRY_TO_EDGE_CONN(conn)->rend_data->onion_address, - oc->rend_data->onion_address)) { - log_info(LD_REND|LD_CIRC, "Closing introduction circuit that we " - "built in parallel."); - circuit_mark_for_close(c, END_CIRC_REASON_TIMEOUT); - } - } - } return 0; } /* now rendcirc and introcirc are each either undefined or not finished */ if (rendcirc && introcirc && - rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY) { + rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY) { log_info(LD_REND, - "ready rend circ %d already here (no intro-ack yet on " - "intro %d). (stream %d sec old)", - rendcirc->_base.n_circ_id, - introcirc->_base.n_circ_id, conn_age); - - tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); - if (introcirc->_base.state == CIRCUIT_STATE_OPEN) { - log_info(LD_REND,"found open intro circ %d (rend %d); sending " + "ready rend circ %u already here (no intro-ack yet on " + "intro %u). (stream %d sec old)", + (unsigned)rendcirc->base_.n_circ_id, + (unsigned)introcirc->base_.n_circ_id, conn_age); + + tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); + if (introcirc->base_.state == CIRCUIT_STATE_OPEN) { + log_info(LD_REND,"found open intro circ %u (rend %u); sending " "introduction. (stream %d sec old)", - introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id, + (unsigned)introcirc->base_.n_circ_id, + (unsigned)rendcirc->base_.n_circ_id, conn_age); switch (rend_client_send_introduction(introcirc, rendcirc)) { case 0: /* success */ - rendcirc->_base.timestamp_dirty = time(NULL); - introcirc->_base.timestamp_dirty = time(NULL); + rendcirc->base_.timestamp_dirty = time(NULL); + introcirc->base_.timestamp_dirty = time(NULL); + + pathbias_count_use_attempt(introcirc); + pathbias_count_use_attempt(rendcirc); + assert_circuit_ok(TO_CIRCUIT(rendcirc)); assert_circuit_ok(TO_CIRCUIT(introcirc)); return 0; @@ -2034,10 +2263,10 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) } } - log_info(LD_REND, "Intro (%d) and rend (%d) circs are not both ready. " + log_info(LD_REND, "Intro (%u) and rend (%u) circs are not both ready. " "Stalling conn. (%d sec old)", - introcirc ? introcirc->_base.n_circ_id : 0, - rendcirc ? rendcirc->_base.n_circ_id : 0, conn_age); + introcirc ? (unsigned)introcirc->base_.n_circ_id : 0, + rendcirc ? (unsigned)rendcirc->base_.n_circ_id : 0, conn_age); return 0; } } @@ -2078,3 +2307,23 @@ circuit_change_purpose(circuit_t *circ, uint8_t new_purpose) } } +/** Mark <b>circ</b> so that no more connections can be attached to it. */ +void +mark_circuit_unusable_for_new_conns(origin_circuit_t *circ) +{ + const or_options_t *options = get_options(); + tor_assert(circ); + + /* XXXX025 This is a kludge; we're only keeping it around in case there's + * something that doesn't check unusable_for_new_conns, and to avoid + * deeper refactoring of our expiration logic. */ + if (! circ->base_.timestamp_dirty) + circ->base_.timestamp_dirty = approx_time(); + if (options->MaxCircuitDirtiness >= circ->base_.timestamp_dirty) + circ->base_.timestamp_dirty = 1; /* prevent underflow */ + else + circ->base_.timestamp_dirty -= options->MaxCircuitDirtiness; + + circ->unusable_for_new_conns = 1; +} + diff --git a/src/or/circuituse.h b/src/or/circuituse.h index be2bd7ec51..11e5a64163 100644 --- a/src/or/circuituse.h +++ b/src/or/circuituse.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for circuituse.c. **/ -#ifndef _TOR_CIRCUITUSE_H -#define _TOR_CIRCUITUSE_H +#ifndef TOR_CIRCUITUSE_H +#define TOR_CIRCUITUSE_H void circuit_expire_building(void); void circuit_remove_handled_ports(smartlist_t *needed_ports); @@ -55,6 +55,7 @@ void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose); int hostname_in_track_host_exits(const or_options_t *options, const char *address); +void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ); #endif diff --git a/src/or/command.c b/src/or/command.c index 61e1e13a71..699b02fb47 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,10 +12,12 @@ /* In-points to command.c: * * - command_process_cell(), called from - * connection_or_process_cells_from_inbuf() in connection_or.c + * incoming cell handlers of channel_t instances; + * callbacks registered in command_setup_channel(), + * called when channels are created in circuitbuild.c */ - #include "or.h" +#include "channel.h" #include "circuitbuild.h" #include "circuitlist.h" #include "command.h" @@ -27,12 +29,11 @@ #include "hibernate.h" #include "nodelist.h" #include "onion.h" +#include "rephist.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; /** How many CELL_CREATE cells have we received, ever? */ uint64_t stats_n_create_cells_processed = 0; /** How many CELL_CREATED cells have we received, ever? */ @@ -41,38 +42,16 @@ uint64_t stats_n_created_cells_processed = 0; uint64_t stats_n_relay_cells_processed = 0; /** How many CELL_DESTROY cells have we received, ever? */ uint64_t stats_n_destroy_cells_processed = 0; -/** How many CELL_VERSIONS cells have we received, ever? */ -uint64_t stats_n_versions_cells_processed = 0; -/** How many CELL_NETINFO cells have we received, ever? */ -uint64_t stats_n_netinfo_cells_processed = 0; -/** How many CELL_VPADDING cells have we received, ever? */ -uint64_t stats_n_vpadding_cells_processed = 0; -/** How many CELL_CERTS cells have we received, ever? */ -uint64_t stats_n_certs_cells_processed = 0; -/** How many CELL_AUTH_CHALLENGE cells have we received, ever? */ -uint64_t stats_n_auth_challenge_cells_processed = 0; -/** How many CELL_AUTHENTICATE cells have we received, ever? */ -uint64_t stats_n_authenticate_cells_processed = 0; -/** How many CELL_AUTHORIZE cells have we received, ever? */ -uint64_t stats_n_authorize_cells_processed = 0; +/* Handle an incoming channel */ +static void command_handle_incoming_channel(channel_listener_t *listener, + channel_t *chan); /* These are the main functions for processing cells */ -static void command_process_create_cell(cell_t *cell, or_connection_t *conn); -static void command_process_created_cell(cell_t *cell, or_connection_t *conn); -static void command_process_relay_cell(cell_t *cell, or_connection_t *conn); -static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn); -static void command_process_versions_cell(var_cell_t *cell, - or_connection_t *conn); -static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn); -static void command_process_certs_cell(var_cell_t *cell, - or_connection_t *conn); -static void command_process_auth_challenge_cell(var_cell_t *cell, - or_connection_t *conn); -static void command_process_authenticate_cell(var_cell_t *cell, - or_connection_t *conn); -static int enter_v3_handshake_with_cell(var_cell_t *cell, - or_connection_t *conn); +static void command_process_create_cell(cell_t *cell, channel_t *chan); +static void command_process_created_cell(cell_t *cell, channel_t *chan); +static void command_process_relay_cell(cell_t *cell, channel_t *chan); +static void command_process_destroy_cell(cell_t *cell, channel_t *chan); #ifdef KEEP_TIMING_STATS /** This is a wrapper function around the actual function that processes the @@ -80,15 +59,15 @@ static int enter_v3_handshake_with_cell(var_cell_t *cell, * by the number of microseconds used by the call to <b>*func(cell, conn)</b>. */ static void -command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time, - void (*func)(cell_t *, or_connection_t *)) +command_time_process_cell(cell_t *cell, channel_t *chan, int *time, + void (*func)(cell_t *, channel_t *)) { struct timeval start, end; long time_passed; tor_gettimeofday(&start); - (*func)(cell, conn); + (*func)(cell, chan); tor_gettimeofday(&end); time_passed = tv_udiff(&start, &end) ; @@ -104,15 +83,14 @@ command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time, } #endif -/** Process a <b>cell</b> that was just received on <b>conn</b>. Keep internal +/** Process a <b>cell</b> that was just received on <b>chan</b>. Keep internal * statistics about how many of each cell we've processed so far * this second, and the total number of microseconds it took to * process each type of cell. */ void -command_process_cell(cell_t *cell, or_connection_t *conn) +command_process_cell(channel_t *chan, cell_t *cell) { - int handshaking = (conn->_base.state != OR_CONN_STATE_OPEN); #ifdef KEEP_TIMING_STATS /* how many of each cell have we seen so far this second? needs better * name. */ @@ -152,263 +130,130 @@ command_process_cell(cell_t *cell, or_connection_t *conn) #define PROCESS_CELL(tp, cl, cn) command_process_ ## tp ## _cell(cl, cn) #endif - if (conn->_base.marked_for_close) - return; - - /* Reject all but VERSIONS and NETINFO when handshaking. */ - /* (VERSIONS should actually be impossible; it's variable-length.) */ - if (handshaking && cell->command != CELL_VERSIONS && - cell->command != CELL_NETINFO) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received unexpected cell command %d in state %s; closing the " - "connection.", - (int)cell->command, - conn_state_to_string(CONN_TYPE_OR,conn->_base.state)); - connection_mark_for_close(TO_CONN(conn)); - return; - } - - if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) - or_handshake_state_record_cell(conn->handshake_state, cell, 1); - switch (cell->command) { - case CELL_PADDING: - ++stats_n_padding_cells_processed; - /* do nothing */ - break; case CELL_CREATE: case CELL_CREATE_FAST: + case CELL_CREATE2: ++stats_n_create_cells_processed; - PROCESS_CELL(create, cell, conn); + PROCESS_CELL(create, cell, chan); break; case CELL_CREATED: case CELL_CREATED_FAST: + case CELL_CREATED2: ++stats_n_created_cells_processed; - PROCESS_CELL(created, cell, conn); + PROCESS_CELL(created, cell, chan); break; case CELL_RELAY: case CELL_RELAY_EARLY: ++stats_n_relay_cells_processed; - PROCESS_CELL(relay, cell, conn); + PROCESS_CELL(relay, cell, chan); break; case CELL_DESTROY: ++stats_n_destroy_cells_processed; - PROCESS_CELL(destroy, cell, conn); - break; - case CELL_VERSIONS: - tor_fragile_assert(); - break; - case CELL_NETINFO: - ++stats_n_netinfo_cells_processed; - PROCESS_CELL(netinfo, cell, conn); + PROCESS_CELL(destroy, cell, chan); break; default: log_fn(LOG_INFO, LD_PROTOCOL, - "Cell of unknown type (%d) received. Dropping.", cell->command); + "Cell of unknown or unexpected type (%d) received. " + "Dropping.", + cell->command); break; } } -/** Return true if <b>command</b> is a cell command that's allowed to start a - * V3 handshake. */ -static int -command_allowed_before_handshake(uint8_t command) -{ - switch (command) { - case CELL_VERSIONS: - case CELL_VPADDING: - case CELL_AUTHORIZE: - return 1; - default: - return 0; - } -} - -/** Process a <b>cell</b> that was just received on <b>conn</b>. Keep internal - * statistics about how many of each cell we've processed so far - * this second, and the total number of microseconds it took to - * process each type of cell. +/** Process an incoming var_cell from a channel; in the current protocol all + * the var_cells are handshake-related and handled below the channel layer, + * so this just logs a warning and drops the cell. */ + void -command_process_var_cell(var_cell_t *cell, or_connection_t *conn) +command_process_var_cell(channel_t *chan, var_cell_t *var_cell) { -#ifdef KEEP_TIMING_STATS - /* how many of each cell have we seen so far this second? needs better - * name. */ - static int num_versions=0, num_certs=0; - - time_t now = time(NULL); - - if (now > current_second) { /* the second has rolled over */ - /* print stats */ - log_info(LD_OR, - "At end of second: %d versions (%d ms), %d certs (%d ms)", - num_versions, versions_time/1000, - num_certs, certs_time/1000); - - num_versions = num_certs = 0; - versions_time = certs_time = 0; - - /* remember which second it is, for next time */ - current_second = now; - } -#endif + tor_assert(chan); + tor_assert(var_cell); - if (conn->_base.marked_for_close) - return; - - switch (conn->_base.state) - { - case OR_CONN_STATE_OR_HANDSHAKING_V2: - if (cell->command != CELL_VERSIONS) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received a cell with command %d in state %s; " - "closing the connection.", - (int)cell->command, - conn_state_to_string(CONN_TYPE_OR,conn->_base.state)); - connection_mark_for_close(TO_CONN(conn)); - return; - } - break; - case OR_CONN_STATE_TLS_HANDSHAKING: - /* If we're using bufferevents, it's entirely possible for us to - * notice "hey, data arrived!" before we notice "hey, the handshake - * finished!" And we need to be accepting both at once to handle both - * the v2 and v3 handshakes. */ - - /* fall through */ - case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: - if (! command_allowed_before_handshake(cell->command)) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received a cell with command %d in state %s; " - "closing the connection.", - (int)cell->command, - conn_state_to_string(CONN_TYPE_OR,conn->_base.state)); - connection_mark_for_close(TO_CONN(conn)); - return; - } else { - if (enter_v3_handshake_with_cell(cell, conn)<0) - return; - } - break; - case OR_CONN_STATE_OR_HANDSHAKING_V3: - if (cell->command != CELL_AUTHENTICATE) - or_handshake_state_record_var_cell(conn->handshake_state, cell, 1); - break; /* Everything is allowed */ - case OR_CONN_STATE_OPEN: - if (conn->link_proto < 3) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received a variable-length cell with command %d in state %s " - "with link protocol %d; ignoring it.", - (int)cell->command, - conn_state_to_string(CONN_TYPE_OR,conn->_base.state), - (int)conn->link_proto); - return; - } - break; - default: - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received var-length cell with command %d in unexpected state " - "%s [%d]; ignoring it.", - (int)cell->command, - conn_state_to_string(CONN_TYPE_OR,conn->_base.state), - (int)conn->_base.state); - return; - } - - switch (cell->command) { - case CELL_VERSIONS: - ++stats_n_versions_cells_processed; - PROCESS_CELL(versions, cell, conn); - break; - case CELL_VPADDING: - ++stats_n_vpadding_cells_processed; - /* Do nothing */ - break; - case CELL_CERTS: - ++stats_n_certs_cells_processed; - PROCESS_CELL(certs, cell, conn); - break; - case CELL_AUTH_CHALLENGE: - ++stats_n_auth_challenge_cells_processed; - PROCESS_CELL(auth_challenge, cell, conn); - break; - case CELL_AUTHENTICATE: - ++stats_n_authenticate_cells_processed; - PROCESS_CELL(authenticate, cell, conn); - break; - case CELL_AUTHORIZE: - ++stats_n_authorize_cells_processed; - /* Ignored so far. */ - break; - default: - log_fn(LOG_INFO, LD_PROTOCOL, - "Variable-length cell of unknown type (%d) received.", - cell->command); - break; - } + log_info(LD_PROTOCOL, + "Received unexpected var_cell above the channel layer of type %d" + "; dropping it.", + var_cell->command); } -/** Process a 'create' <b>cell</b> that just arrived from <b>conn</b>. Make a +/** Process a 'create' <b>cell</b> that just arrived from <b>chan</b>. Make a * new circuit with the p_circ_id specified in cell. Put the circuit in state * onionskin_pending, and pass the onionskin to the cpuworker. Circ will get * picked up again when the cpuworker finishes decrypting it. */ static void -command_process_create_cell(cell_t *cell, or_connection_t *conn) +command_process_create_cell(cell_t *cell, channel_t *chan) { or_circuit_t *circ; const or_options_t *options = get_options(); int id_is_high; + create_cell_t *create_cell; + + tor_assert(cell); + tor_assert(chan); + + log_debug(LD_OR, + "Got a CREATE cell for circ_id %u on channel " U64_FORMAT + " (%p)", + (unsigned)cell->circ_id, + U64_PRINTF_ARG(chan->global_identifier), chan); if (we_are_hibernating()) { log_info(LD_OR, "Received create cell but we're shutting down. Sending back " "destroy."); - connection_or_send_destroy(cell->circ_id, conn, + channel_send_destroy(cell->circ_id, chan, END_CIRC_REASON_HIBERNATING); return; } if (!server_mode(options) || - (!public_server_mode(options) && conn->is_outgoing)) { + (!public_server_mode(options) && channel_is_outgoing(chan))) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received create cell (type %d) from %s:%d, but we're connected " + "Received create cell (type %d) from %s, but we're connected " "to it as a client. " "Sending back a destroy.", - (int)cell->command, conn->_base.address, conn->_base.port); - connection_or_send_destroy(cell->circ_id, conn, - END_CIRC_REASON_TORPROTOCOL); + (int)cell->command, channel_get_canonical_remote_descr(chan)); + channel_send_destroy(cell->circ_id, chan, + END_CIRC_REASON_TORPROTOCOL); return; } if (cell->circ_id == 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received a create cell (type %d) from %s:%d with zero circID; " - " ignoring.", (int)cell->command, conn->_base.address, - conn->_base.port); + "Received a create cell (type %d) from %s with zero circID; " + " ignoring.", (int)cell->command, + channel_get_actual_remote_descr(chan)); return; } /* If the high bit of the circuit ID is not as expected, close the * circ. */ - id_is_high = cell->circ_id & (1<<15); - if ((id_is_high && conn->circ_id_type == CIRC_ID_TYPE_HIGHER) || - (!id_is_high && conn->circ_id_type == CIRC_ID_TYPE_LOWER)) { + if (chan->wide_circ_ids) + id_is_high = cell->circ_id & (1u<<31); + else + id_is_high = cell->circ_id & (1u<<15); + if ((id_is_high && + chan->circ_id_type == CIRC_ID_TYPE_HIGHER) || + (!id_is_high && + chan->circ_id_type == CIRC_ID_TYPE_LOWER)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received create cell with unexpected circ_id %d. Closing.", - cell->circ_id); - connection_or_send_destroy(cell->circ_id, conn, - END_CIRC_REASON_TORPROTOCOL); + "Received create cell with unexpected circ_id %u. Closing.", + (unsigned)cell->circ_id); + channel_send_destroy(cell->circ_id, chan, + END_CIRC_REASON_TORPROTOCOL); return; } - if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) { - const node_t *node = node_get_by_id(conn->identity_digest); + if (circuit_id_in_use_on_channel(cell->circ_id, chan)) { + const node_t *node = node_get_by_id(chan->identity_digest); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received CREATE cell (circID %d) for known circ. " + "Received CREATE cell (circID %u) for known circ. " "Dropping (age %d).", - cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created)); + (unsigned)cell->circ_id, + (int)(time(NULL) - channel_when_created(chan))); if (node) { char *p = esc_for_log(node_get_platform(node)); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, @@ -419,23 +264,24 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) return; } - circ = or_circuit_new(cell->circ_id, conn); - circ->_base.purpose = CIRCUIT_PURPOSE_OR; + circ = or_circuit_new(cell->circ_id, chan); + circ->base_.purpose = CIRCUIT_PURPOSE_OR; circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING); - if (cell->command == CELL_CREATE) { - char *onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN); - memcpy(onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN); + create_cell = tor_malloc_zero(sizeof(create_cell_t)); + if (create_cell_parse(create_cell, cell) < 0) { + tor_free(create_cell); + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Bogus/unrecognized create cell; closing."); + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); + return; + } + if (create_cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST) { /* hand it off to the cpuworkers, and then return. */ - if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) { -#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); - } + if (connection_or_digest_is_known_relay(chan->identity_digest)) + rep_hist_note_circuit_handshake_requested(create_cell->handshake_type); + if (assign_onionskin_to_cpuworker(NULL, circ, create_cell) < 0) { + log_debug(LD_GENERAL,"Failed to hand off onionskin. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT); return; } @@ -443,30 +289,44 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) } else { /* This is a CREATE_FAST cell; we can handle it immediately without using * a CPU worker. */ - char keys[CPATH_KEY_MATERIAL_LEN]; - char reply[DIGEST_LEN*2]; - - tor_assert(cell->command == CELL_CREATE_FAST); + uint8_t keys[CPATH_KEY_MATERIAL_LEN]; + uint8_t rend_circ_nonce[DIGEST_LEN]; + int len; + created_cell_t created_cell; /* Make sure we never try to use the OR connection on which we * received this cell to satisfy an EXTEND request, */ - conn->is_connection_with_client = 1; - - if (fast_server_handshake(cell->payload, (uint8_t*)reply, - (uint8_t*)keys, sizeof(keys))<0) { + channel_mark_client(chan); + + memset(&created_cell, 0, sizeof(created_cell)); + len = onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_FAST, + create_cell->onionskin, + create_cell->handshake_len, + NULL, + created_cell.reply, + keys, CPATH_KEY_MATERIAL_LEN, + rend_circ_nonce); + tor_free(create_cell); + if (len < 0) { log_warn(LD_OR,"Failed to generate key material. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); + tor_free(create_cell); return; } - if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) { + created_cell.cell_type = CELL_CREATED_FAST; + created_cell.handshake_len = len; + + if (onionskin_answer(circ, &created_cell, + (const char *)keys, rend_circ_nonce)<0) { log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return; } + memwipe(keys, 0, sizeof(keys)); } } -/** Process a 'created' <b>cell</b> that just arrived from <b>conn</b>. +/** Process a 'created' <b>cell</b> that just arrived from <b>chan</b>. * Find the circuit * that it's intended for. If we're not the origin of the circuit, package * the 'created' cell in an 'extended' relay cell and pass it back. If we @@ -475,16 +335,17 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) * extend to the next hop in the circuit if necessary. */ static void -command_process_created_cell(cell_t *cell, or_connection_t *conn) +command_process_created_cell(cell_t *cell, channel_t *chan) { circuit_t *circ; + extended_cell_t extended_cell; - circ = circuit_get_by_circid_orconn(cell->circ_id, conn); + circ = circuit_get_by_circid_channel(cell->circ_id, chan); if (!circ) { log_info(LD_OR, - "(circID %d) unknown circ (probably got a destroy earlier). " - "Dropping.", cell->circ_id); + "(circID %u) unknown circ (probably got a destroy earlier). " + "Dropping.", (unsigned)cell->circ_id); return; } @@ -495,12 +356,18 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn) return; } + if (created_cell_parse(&extended_cell.created_cell, cell) < 0) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, "Unparseable created cell."); + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); + return; + } + if (CIRCUIT_IS_ORIGIN(circ)) { /* we're the OP. Handshake this. */ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); int err_reason = 0; log_debug(LD_OR,"at OP. Finishing handshake."); - if ((err_reason = circuit_finish_handshake(origin_circ, cell->command, - cell->payload)) < 0) { + if ((err_reason = circuit_finish_handshake(origin_circ, + &extended_cell.created_cell)) < 0) { log_warn(LD_OR,"circuit_finish_handshake failed."); circuit_mark_for_close(circ, -err_reason); return; @@ -513,11 +380,24 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn) return; } } else { /* pack it into an extended relay cell, and send it. */ + uint8_t command=0; + uint16_t len=0; + uint8_t payload[RELAY_PAYLOAD_SIZE]; log_debug(LD_OR, "Converting created cell to extended relay cell, sending."); - relay_send_command_from_edge(0, circ, RELAY_COMMAND_EXTENDED, - (char*)cell->payload, ONIONSKIN_REPLY_LEN, - NULL); + memset(payload, 0, sizeof(payload)); + if (extended_cell.created_cell.cell_type == CELL_CREATED2) + extended_cell.cell_type = RELAY_COMMAND_EXTENDED2; + else + extended_cell.cell_type = RELAY_COMMAND_EXTENDED; + if (extended_cell_format(&command, &len, payload, &extended_cell) < 0) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, "Can't format extended cell."); + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); + return; + } + + relay_send_command_from_edge(0, circ, command, + (const char*)payload, len, NULL); } } @@ -526,17 +406,18 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn) * circuit_receive_relay_cell() for actual processing. */ static void -command_process_relay_cell(cell_t *cell, or_connection_t *conn) +command_process_relay_cell(cell_t *cell, channel_t *chan) { circuit_t *circ; int reason, direction; - circ = circuit_get_by_circid_orconn(cell->circ_id, conn); + circ = circuit_get_by_circid_channel(cell->circ_id, chan); if (!circ) { log_debug(LD_OR, - "unknown circuit %d on connection from %s:%d. Dropping.", - cell->circ_id, conn->_base.address, conn->_base.port); + "unknown circuit %u on connection from %s. Dropping.", + (unsigned)cell->circ_id, + channel_get_canonical_remote_descr(chan)); return; } @@ -549,7 +430,7 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn) if (CIRCUIT_IS_ORIGIN(circ)) { /* if we're a relay and treating connections with recent local * traffic better, then this is one of them. */ - conn->client_used = time(NULL); + channel_timestamp_client(chan); } if (!CIRCUIT_IS_ORIGIN(circ) && @@ -570,10 +451,10 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn) 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." + "Received too many RELAY_EARLY cells on circ %u from %s." " Closing circuit.", - cell->circ_id, safe_str(conn->_base.address), - conn->_base.port); + (unsigned)cell->circ_id, + safe_str(channel_get_canonical_remote_descr(chan))); circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); return; } @@ -590,7 +471,7 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn) } /** Process a 'destroy' <b>cell</b> that just arrived from - * <b>conn</b>. Find the circ that it refers to (if any). + * <b>chan</b>. Find the circ that it refers to (if any). * * If the circ is in state * onionskin_pending, then call onion_pending_remove() to remove it @@ -603,28 +484,29 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn) * and passes the destroy cell onward if necessary). */ static void -command_process_destroy_cell(cell_t *cell, or_connection_t *conn) +command_process_destroy_cell(cell_t *cell, channel_t *chan) { circuit_t *circ; int reason; - circ = circuit_get_by_circid_orconn(cell->circ_id, conn); + circ = circuit_get_by_circid_channel(cell->circ_id, chan); if (!circ) { - log_info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.", - cell->circ_id, conn->_base.address, conn->_base.port); + log_info(LD_OR,"unknown circuit %u on connection from %s. Dropping.", + (unsigned)cell->circ_id, + channel_get_canonical_remote_descr(chan)); return; } - log_debug(LD_OR,"Received for circID %d.",cell->circ_id); + log_debug(LD_OR,"Received for circID %u.",(unsigned)cell->circ_id); reason = (uint8_t)cell->payload[0]; if (!CIRCUIT_IS_ORIGIN(circ) && cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) { /* the destroy came from behind */ - circuit_set_p_circid_orconn(TO_OR_CIRCUIT(circ), 0, NULL); + circuit_set_p_circid_chan(TO_OR_CIRCUIT(circ), 0, NULL); circuit_mark_for_close(circ, reason|END_CIRC_REASON_FLAG_REMOTE); } else { /* the destroy came from ahead */ - circuit_set_n_circid_orconn(circ, 0, NULL); + circuit_set_n_circid_chan(circ, 0, NULL); if (CIRCUIT_IS_ORIGIN(circ)) { circuit_mark_for_close(circ, reason|END_CIRC_REASON_FLAG_REMOTE); } else { @@ -637,740 +519,43 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn) } } -/** Called when we as a server receive an appropriate cell while waiting - * either for a cell or a TLS handshake. Set the connection's state to - * "handshaking_v3', initializes the or_handshake_state field as needed, - * and add the cell to the hash of incoming cells.) - * - * Return 0 on success; return -1 and mark the connection on failure. +/** Callback to handle a new channel; call command_setup_channel() to give + * it the right cell handlers. */ -static int -enter_v3_handshake_with_cell(var_cell_t *cell, or_connection_t *conn) -{ - const int started_here = connection_or_nonopen_was_started_here(conn); - - tor_assert(conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING || - conn->_base.state == OR_CONN_STATE_TLS_SERVER_RENEGOTIATING); - - if (started_here) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Received a cell while TLS-handshaking, not in " - "OR_HANDSHAKING_V3, on a connection we originated."); - } - connection_or_block_renegotiation(conn); - conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V3; - if (connection_init_or_handshake_state(conn, started_here) < 0) { - connection_mark_for_close(TO_CONN(conn)); - return -1; - } - or_handshake_state_record_var_cell(conn->handshake_state, cell, 1); - return 0; -} - -/** Process a 'versions' cell. The current link protocol version must be 0 - * to indicate that no version has yet been negotiated. We compare the - * versions in the cell to the list of versions we support, pick the - * highest version we have in common, and continue the negotiation from - * there. - */ -static void -command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) -{ - int highest_supported_version = 0; - const uint8_t *cp, *end; - const int started_here = connection_or_nonopen_was_started_here(conn); - if (conn->link_proto != 0 || - (conn->handshake_state && conn->handshake_state->received_versions)) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Received a VERSIONS cell on a connection with its version " - "already set to %d; dropping", (int) conn->link_proto); - return; - } - switch (conn->_base.state) - { - case OR_CONN_STATE_OR_HANDSHAKING_V2: - case OR_CONN_STATE_OR_HANDSHAKING_V3: - break; - case OR_CONN_STATE_TLS_HANDSHAKING: - case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: - default: - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "VERSIONS cell while in unexpected state"); - return; - } - - tor_assert(conn->handshake_state); - end = cell->payload + cell->payload_len; - for (cp = cell->payload; cp+1 < end; ++cp) { - uint16_t v = ntohs(get_uint16(cp)); - if (is_or_protocol_version_known(v) && v > highest_supported_version) - highest_supported_version = v; - } - if (!highest_supported_version) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Couldn't find a version in common between my version list and the " - "list in the VERSIONS cell; closing connection."); - connection_mark_for_close(TO_CONN(conn)); - return; - } else if (highest_supported_version == 1) { - /* Negotiating version 1 makes no sense, since version 1 has no VERSIONS - * cells. */ - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Used version negotiation protocol to negotiate a v1 connection. " - "That's crazily non-compliant. Closing connection."); - connection_mark_for_close(TO_CONN(conn)); - return; - } else if (highest_supported_version < 3 && - conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Negotiated link protocol 2 or lower after doing a v3 TLS " - "handshake. Closing connection."); - connection_mark_for_close(TO_CONN(conn)); - return; - } else if (highest_supported_version != 2 && - conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V2) { - /* XXXX This should eventually be a log_protocol_warn */ - log_fn(LOG_WARN, LD_OR, - "Negotiated link with non-2 protocol after doing a v2 TLS " - "handshake with %s. Closing connection.", - fmt_addr(&conn->_base.addr)); - connection_mark_for_close(TO_CONN(conn)); - return; - } - - conn->link_proto = highest_supported_version; - conn->handshake_state->received_versions = 1; - - if (conn->link_proto == 2) { - log_info(LD_OR, "Negotiated version %d with %s:%d; sending NETINFO.", - highest_supported_version, - safe_str_client(conn->_base.address), - conn->_base.port); - - if (connection_or_send_netinfo(conn) < 0) { - connection_mark_for_close(TO_CONN(conn)); - return; - } - } else { - const int send_versions = !started_here; - /* If we want to authenticate, send a CERTS cell */ - const int send_certs = !started_here || public_server_mode(get_options()); - /* If we're a host that got a connection, ask for authentication. */ - const int send_chall = !started_here; - /* If our certs cell will authenticate us, we can send a netinfo cell - * right now. */ - const int send_netinfo = !started_here; - const int send_any = - send_versions || send_certs || send_chall || send_netinfo; - tor_assert(conn->link_proto >= 3); - - log_info(LD_OR, "Negotiated version %d with %s:%d; %s%s%s%s%s", - highest_supported_version, - safe_str_client(conn->_base.address), - conn->_base.port, - send_any ? "Sending cells:" : "Waiting for CERTS cell", - send_versions ? " VERSIONS" : "", - send_certs ? " CERTS" : "", - send_chall ? " AUTH_CHALLENGE" : "", - send_netinfo ? " NETINFO" : ""); - -#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE - if (1) { - connection_mark_for_close(TO_CONN(conn)); - return; - } -#endif - - if (send_versions) { - if (connection_or_send_versions(conn, 1) < 0) { - log_warn(LD_OR, "Couldn't send versions cell"); - connection_mark_for_close(TO_CONN(conn)); - return; - } - } - if (send_certs) { - if (connection_or_send_certs_cell(conn) < 0) { - log_warn(LD_OR, "Couldn't send certs cell"); - connection_mark_for_close(TO_CONN(conn)); - return; - } - } - if (send_chall) { - if (connection_or_send_auth_challenge_cell(conn) < 0) { - log_warn(LD_OR, "Couldn't send auth_challenge cell"); - connection_mark_for_close(TO_CONN(conn)); - return; - } - } - if (send_netinfo) { - if (connection_or_send_netinfo(conn) < 0) { - log_warn(LD_OR, "Couldn't send netinfo cell"); - connection_mark_for_close(TO_CONN(conn)); - return; - } - } - } -} -/** Process a 'netinfo' cell: read and act on its contents, and set the - * connection state to "open". */ static void -command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) +command_handle_incoming_channel(channel_listener_t *listener, channel_t *chan) { - time_t timestamp; - uint8_t my_addr_type; - uint8_t my_addr_len; - const uint8_t *my_addr_ptr; - const uint8_t *cp, *end; - uint8_t n_other_addrs; - time_t now = time(NULL); - - long apparent_skew = 0; - uint32_t my_apparent_addr = 0; - - if (conn->link_proto < 2) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Received a NETINFO cell on %s connection; dropping.", - conn->link_proto == 0 ? "non-versioned" : "a v1"); - return; - } - if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V2 && - conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Received a NETINFO cell on non-handshaking connection; dropping."); - return; - } - tor_assert(conn->handshake_state && - conn->handshake_state->received_versions); - - if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) { - tor_assert(conn->link_proto >= 3); - if (conn->handshake_state->started_here) { - if (!conn->handshake_state->authenticated) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got a NETINFO cell from server, " - "but no authentication. Closing the connection."); - connection_mark_for_close(TO_CONN(conn)); - return; - } - } else { - /* we're the server. If the client never authenticated, we have - some housekeeping to do.*/ - if (!conn->handshake_state->authenticated) { - tor_assert(tor_digest_is_zero( - (const char*)conn->handshake_state->authenticated_peer_id)); - connection_or_set_circid_type(conn, NULL); - - connection_or_init_conn_from_address(conn, - &conn->_base.addr, - conn->_base.port, - (const char*)conn->handshake_state->authenticated_peer_id, - 0); - } - } - } - - /* Decode the cell. */ - timestamp = ntohl(get_uint32(cell->payload)); - if (labs(now - conn->handshake_state->sent_versions_at) < 180) { - apparent_skew = now - timestamp; - } - - my_addr_type = (uint8_t) cell->payload[4]; - my_addr_len = (uint8_t) cell->payload[5]; - my_addr_ptr = (uint8_t*) cell->payload + 6; - end = cell->payload + CELL_PAYLOAD_SIZE; - cp = cell->payload + 6 + my_addr_len; - if (cp >= end) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Addresses too long in netinfo cell; closing connection."); - connection_mark_for_close(TO_CONN(conn)); - return; - } else if (my_addr_type == RESOLVED_TYPE_IPV4 && my_addr_len == 4) { - my_apparent_addr = ntohl(get_uint32(my_addr_ptr)); - } - - n_other_addrs = (uint8_t) *cp++; - while (n_other_addrs && cp < end-2) { - /* Consider all the other addresses; if any matches, this connection is - * "canonical." */ - tor_addr_t addr; - const uint8_t *next = - decode_address_from_payload(&addr, cp, (int)(end-cp)); - if (next == NULL) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Bad address in netinfo cell; closing connection."); - connection_mark_for_close(TO_CONN(conn)); - return; - } - if (tor_addr_eq(&addr, &conn->real_addr)) { - conn->is_canonical = 1; - break; - } - cp = next; - --n_other_addrs; - } - - /* Act on apparent skew. */ - /** Warn when we get a netinfo skew with at least this value. */ -#define NETINFO_NOTICE_SKEW 3600 - if (labs(apparent_skew) > NETINFO_NOTICE_SKEW && - router_get_by_id_digest(conn->identity_digest)) { - char dbuf[64]; - int severity; - /*XXXX be smarter about when everybody says we are skewed. */ - if (router_digest_is_trusted_dir(conn->identity_digest)) - severity = LOG_WARN; - else - severity = LOG_INFO; - format_time_interval(dbuf, sizeof(dbuf), apparent_skew); - log_fn(severity, LD_GENERAL, "Received NETINFO cell with skewed time from " - "server at %s:%d. It seems that our clock is %s by %s, or " - "that theirs is %s. Tor requires an accurate clock to work: " - "please check your time and date settings.", - conn->_base.address, (int)conn->_base.port, - apparent_skew>0 ? "ahead" : "behind", dbuf, - apparent_skew>0 ? "behind" : "ahead"); - if (severity == LOG_WARN) /* only tell the controller if an authority */ - control_event_general_status(LOG_WARN, - "CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d", - apparent_skew, - conn->_base.address, conn->_base.port); - } - - /* XXX maybe act on my_apparent_addr, if the source is sufficiently - * trustworthy. */ - (void)my_apparent_addr; - - if (! conn->handshake_state->sent_netinfo) { - /* If we were prepared to authenticate, but we never got an AUTH_CHALLENGE - * cell, then we would not previously have sent a NETINFO cell. Do so - * now. */ - if (connection_or_send_netinfo(conn) < 0) { - connection_mark_for_close(TO_CONN(conn)); - return; - } - } + tor_assert(listener); + tor_assert(chan); - if (connection_or_set_state_open(conn)<0) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got good NETINFO cell from %s:%d; but " - "was unable to make the OR connection become open.", - safe_str_client(conn->_base.address), - conn->_base.port); - connection_mark_for_close(TO_CONN(conn)); - } else { - log_info(LD_OR, "Got good NETINFO cell from %s:%d; OR connection is now " - "open, using protocol version %d. Its ID digest is %s", - safe_str_client(conn->_base.address), - conn->_base.port, (int)conn->link_proto, - hex_str(conn->identity_digest, DIGEST_LEN)); - } - assert_connection_ok(TO_CONN(conn),time(NULL)); + command_setup_channel(chan); } -/** Process a CERTS cell from an OR connection. - * - * If the other side should not have sent us a CERTS cell, or the cell is - * malformed, or it is supposed to authenticate the TLS key but it doesn't, - * then mark the connection. - * - * If the cell has a good cert chain and we're doing a v3 handshake, then - * store the certificates in or_handshake_state. If this is the client side - * of the connection, we then authenticate the server or mark the connection. - * If it's the server side, wait for an AUTHENTICATE cell. +/** Given a channel, install the right handlers to process incoming + * cells on it. */ -static void -command_process_certs_cell(var_cell_t *cell, or_connection_t *conn) -{ -#define ERR(s) \ - do { \ - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ - "Received a bad CERTS cell from %s:%d: %s", \ - safe_str(conn->_base.address), conn->_base.port, (s)); \ - connection_mark_for_close(TO_CONN(conn)); \ - goto err; \ - } while (0) - - tor_cert_t *link_cert = NULL; - tor_cert_t *id_cert = NULL; - tor_cert_t *auth_cert = NULL; - - uint8_t *ptr; - int n_certs, i; - int send_netinfo = 0; - - if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) - ERR("We're not doing a v3 handshake!"); - if (conn->link_proto < 3) - ERR("We're not using link protocol >= 3"); - if (conn->handshake_state->received_certs_cell) - ERR("We already got one"); - if (conn->handshake_state->authenticated) { - /* Should be unreachable, but let's make sure. */ - ERR("We're already authenticated!"); - } - if (cell->payload_len < 1) - ERR("It had no body"); - if (cell->circ_id) - ERR("It had a nonzero circuit ID"); - - n_certs = cell->payload[0]; - ptr = cell->payload + 1; - for (i = 0; i < n_certs; ++i) { - uint8_t cert_type; - uint16_t cert_len; - if (ptr + 3 > cell->payload + cell->payload_len) { - goto truncated; - } - cert_type = *ptr; - cert_len = ntohs(get_uint16(ptr+1)); - if (ptr + 3 + cert_len > cell->payload + cell->payload_len) { - goto truncated; - } - if (cert_type == OR_CERT_TYPE_TLS_LINK || - cert_type == OR_CERT_TYPE_ID_1024 || - cert_type == OR_CERT_TYPE_AUTH_1024) { - tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len); - if (!cert) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received undecodable certificate in CERTS cell from %s:%d", - safe_str(conn->_base.address), conn->_base.port); - } else { - if (cert_type == OR_CERT_TYPE_TLS_LINK) { - if (link_cert) { - tor_cert_free(cert); - ERR("Too many TLS_LINK certificates"); - } - link_cert = cert; - } else if (cert_type == OR_CERT_TYPE_ID_1024) { - if (id_cert) { - tor_cert_free(cert); - ERR("Too many ID_1024 certificates"); - } - id_cert = cert; - } else if (cert_type == OR_CERT_TYPE_AUTH_1024) { - if (auth_cert) { - tor_cert_free(cert); - ERR("Too many AUTH_1024 certificates"); - } - auth_cert = cert; - } else { - tor_cert_free(cert); - } - } - } - ptr += 3 + cert_len; - continue; - - truncated: - ERR("It ends in the middle of a certificate"); - } - - if (conn->handshake_state->started_here) { - int severity; - if (! (id_cert && link_cert)) - ERR("The certs we wanted were missing"); - /* Okay. We should be able to check the certificates now. */ - if (! tor_tls_cert_matches_key(conn->tls, link_cert)) { - ERR("The link certificate didn't match the TLS public key"); - } - /* Note that this warns more loudly about time and validity if we were - * _trying_ to connect to an authority, not necessarily if we _did_ connect - * to one. */ - if (router_digest_is_trusted_dir(conn->identity_digest)) - severity = LOG_WARN; - else - severity = LOG_PROTOCOL_WARN; - - if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0)) - ERR("The link certificate was not valid"); - if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1)) - ERR("The ID certificate was not valid"); - - conn->handshake_state->authenticated = 1; - { - const digests_t *id_digests = tor_cert_get_id_digests(id_cert); - crypto_pk_t *identity_rcvd; - if (!id_digests) - ERR("Couldn't compute digests for key in ID cert"); - - identity_rcvd = tor_tls_cert_get_key(id_cert); - if (!identity_rcvd) - ERR("Internal error: Couldn't get RSA key from ID cert."); - memcpy(conn->handshake_state->authenticated_peer_id, - id_digests->d[DIGEST_SHA1], DIGEST_LEN); - connection_or_set_circid_type(conn, identity_rcvd); - crypto_pk_free(identity_rcvd); - } - if (connection_or_client_learned_peer_id(conn, - conn->handshake_state->authenticated_peer_id) < 0) - ERR("Problem setting or checking peer id"); - - log_info(LD_OR, "Got some good certificates from %s:%d: Authenticated it.", - safe_str(conn->_base.address), conn->_base.port); - - conn->handshake_state->id_cert = id_cert; - id_cert = NULL; - - if (!public_server_mode(get_options())) { - /* If we initiated the connection and we are not a public server, we - * aren't planning to authenticate at all. At this point we know who we - * are talking to, so we can just send a netinfo now. */ - send_netinfo = 1; - } - } else { - if (! (id_cert && auth_cert)) - ERR("The certs we wanted were missing"); - - /* Remember these certificates so we can check an AUTHENTICATE cell */ - if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, 1)) - ERR("The authentication certificate was not valid"); - if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1)) - ERR("The ID certificate was not valid"); - - log_info(LD_OR, "Got some good certificates from %s:%d: " - "Waiting for AUTHENTICATE.", - safe_str(conn->_base.address), conn->_base.port); - /* XXXX check more stuff? */ - - conn->handshake_state->id_cert = id_cert; - conn->handshake_state->auth_cert = auth_cert; - id_cert = auth_cert = NULL; - } - - conn->handshake_state->received_certs_cell = 1; - - if (send_netinfo) { - if (connection_or_send_netinfo(conn) < 0) { - log_warn(LD_OR, "Couldn't send netinfo cell"); - connection_mark_for_close(TO_CONN(conn)); - goto err; - } - } - - err: - tor_cert_free(id_cert); - tor_cert_free(link_cert); - tor_cert_free(auth_cert); -#undef ERR -} - -/** Process an AUTH_CHALLENGE cell from an OR connection. - * - * If we weren't supposed to get one (for example, because we're not the - * originator of the connection), or it's ill-formed, or we aren't doing a v3 - * handshake, mark the connection. If the cell is well-formed but we don't - * want to authenticate, just drop it. If the cell is well-formed *and* we - * want to authenticate, send an AUTHENTICATE cell and then a NETINFO cell. */ -static void -command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn) +void +command_setup_channel(channel_t *chan) { - int n_types, i, use_type = -1; - uint8_t *cp; - -#define ERR(s) \ - do { \ - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ - "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \ - safe_str(conn->_base.address), conn->_base.port, (s)); \ - connection_mark_for_close(TO_CONN(conn)); \ - return; \ - } while (0) - - if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) - ERR("We're not currently doing a v3 handshake"); - if (conn->link_proto < 3) - ERR("We're not using link protocol >= 3"); - if (! conn->handshake_state->started_here) - ERR("We didn't originate this connection"); - if (conn->handshake_state->received_auth_challenge) - ERR("We already received one"); - if (! conn->handshake_state->received_certs_cell) - ERR("We haven't gotten a CERTS cell yet"); - if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2) - ERR("It was too short"); - if (cell->circ_id) - ERR("It had a nonzero circuit ID"); - - n_types = ntohs(get_uint16(cell->payload + OR_AUTH_CHALLENGE_LEN)); - if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2 + 2*n_types) - ERR("It looks truncated"); - - /* Now see if there is an authentication type we can use */ - cp=cell->payload+OR_AUTH_CHALLENGE_LEN+2; - for (i=0; i < n_types; ++i, cp += 2) { - uint16_t authtype = ntohs(get_uint16(cp)); - if (authtype == AUTHTYPE_RSA_SHA256_TLSSECRET) - use_type = authtype; - } - - conn->handshake_state->received_auth_challenge = 1; + tor_assert(chan); - if (! public_server_mode(get_options())) { - /* If we're not a public server then we don't want to authenticate on a - connection we originated, and we already sent a NETINFO cell when we - got the CERTS cell. We have nothing more to do. */ - return; - } - - if (use_type >= 0) { - log_info(LD_OR, "Got an AUTH_CHALLENGE cell from %s:%d: Sending " - "authentication", - safe_str(conn->_base.address), conn->_base.port); - - if (connection_or_send_authenticate_cell(conn, use_type) < 0) { - log_warn(LD_OR, "Couldn't send authenticate cell"); - connection_mark_for_close(TO_CONN(conn)); - return; - } - } else { - log_info(LD_OR, "Got an AUTH_CHALLENGE cell from %s:%d, but we don't " - "know any of its authentication types. Not authenticating.", - safe_str(conn->_base.address), conn->_base.port); - } - - if (connection_or_send_netinfo(conn) < 0) { - log_warn(LD_OR, "Couldn't send netinfo cell"); - connection_mark_for_close(TO_CONN(conn)); - return; - } - -#undef ERR + channel_set_cell_handlers(chan, + command_process_cell, + command_process_var_cell); } -/** Process an AUTHENTICATE cell from an OR connection. - * - * If it's ill-formed or we weren't supposed to get one or we're not doing a - * v3 handshake, then mark the connection. If it does not authenticate the - * other side of the connection successfully (because it isn't signed right, - * we didn't get a CERTS cell, etc) mark the connection. Otherwise, accept - * the identity of the router on the other side of the connection. +/** Given a listener, install the right handler to process incoming + * channels on it. */ -static void -command_process_authenticate_cell(var_cell_t *cell, or_connection_t *conn) -{ - uint8_t expected[V3_AUTH_FIXED_PART_LEN]; - const uint8_t *auth; - int authlen; - -#define ERR(s) \ - do { \ - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ - "Received a bad AUTHENTICATE cell from %s:%d: %s", \ - safe_str(conn->_base.address), conn->_base.port, (s)); \ - connection_mark_for_close(TO_CONN(conn)); \ - return; \ - } while (0) - - if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) - ERR("We're not doing a v3 handshake"); - if (conn->link_proto < 3) - ERR("We're not using link protocol >= 3"); - if (conn->handshake_state->started_here) - ERR("We originated this connection"); - if (conn->handshake_state->received_authenticate) - ERR("We already got one!"); - if (conn->handshake_state->authenticated) { - /* Should be impossible given other checks */ - ERR("The peer is already authenticated"); - } - if (! conn->handshake_state->received_certs_cell) - ERR("We never got a certs cell"); - if (conn->handshake_state->auth_cert == NULL) - ERR("We never got an authentication certificate"); - if (conn->handshake_state->id_cert == NULL) - ERR("We never got an identity certificate"); - if (cell->payload_len < 4) - ERR("Cell was way too short"); - - auth = cell->payload; - { - uint16_t type = ntohs(get_uint16(auth)); - uint16_t len = ntohs(get_uint16(auth+2)); - if (4 + len > cell->payload_len) - ERR("Authenticator was truncated"); - - if (type != AUTHTYPE_RSA_SHA256_TLSSECRET) - ERR("Authenticator type was not recognized"); - - auth += 4; - authlen = len; - } - - if (authlen < V3_AUTH_BODY_LEN + 1) - ERR("Authenticator was too short"); - - if (connection_or_compute_authenticate_cell_body( - conn, expected, sizeof(expected), NULL, 1) < 0) - ERR("Couldn't compute expected AUTHENTICATE cell body"); - if (tor_memneq(expected, auth, sizeof(expected))) - ERR("Some field in the AUTHENTICATE cell body was not as expected"); - - { - crypto_pk_t *pk = tor_tls_cert_get_key( - conn->handshake_state->auth_cert); - char d[DIGEST256_LEN]; - char *signed_data; - size_t keysize; - int signed_len; - - if (!pk) - ERR("Internal error: couldn't get RSA key from AUTH cert."); - crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256); - - keysize = crypto_pk_keysize(pk); - signed_data = tor_malloc(keysize); - signed_len = crypto_pk_public_checksig(pk, signed_data, keysize, - (char*)auth + V3_AUTH_BODY_LEN, - authlen - V3_AUTH_BODY_LEN); - crypto_pk_free(pk); - if (signed_len < 0) { - tor_free(signed_data); - ERR("Signature wasn't valid"); - } - if (signed_len < DIGEST256_LEN) { - tor_free(signed_data); - ERR("Not enough data was signed"); - } - /* Note that we deliberately allow *more* than DIGEST256_LEN bytes here, - * in case they're later used to hold a SHA3 digest or something. */ - if (tor_memneq(signed_data, d, DIGEST256_LEN)) { - tor_free(signed_data); - ERR("Signature did not match data to be signed."); - } - tor_free(signed_data); - } - - /* Okay, we are authenticated. */ - conn->handshake_state->received_authenticate = 1; - conn->handshake_state->authenticated = 1; - conn->handshake_state->digest_received_data = 0; - { - crypto_pk_t *identity_rcvd = - tor_tls_cert_get_key(conn->handshake_state->id_cert); - const digests_t *id_digests = - tor_cert_get_id_digests(conn->handshake_state->id_cert); - - /* This must exist; we checked key type when reading the cert. */ - tor_assert(id_digests); - - memcpy(conn->handshake_state->authenticated_peer_id, - id_digests->d[DIGEST_SHA1], DIGEST_LEN); - - connection_or_set_circid_type(conn, identity_rcvd); - crypto_pk_free(identity_rcvd); - - connection_or_init_conn_from_address(conn, - &conn->_base.addr, - conn->_base.port, - (const char*)conn->handshake_state->authenticated_peer_id, - 0); - - log_info(LD_OR, "Got an AUTHENTICATE cell from %s:%d: Looks good.", - safe_str(conn->_base.address), conn->_base.port); - } +void +command_setup_listener(channel_listener_t *listener) +{ + tor_assert(listener); + tor_assert(listener->state == CHANNEL_LISTENER_STATE_LISTENING); -#undef ERR + channel_listener_set_listener_fn(listener, command_handle_incoming_channel); } diff --git a/src/or/command.h b/src/or/command.h index 078ccc9f5d..913f46a5cd 100644 --- a/src/or/command.h +++ b/src/or/command.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,11 +9,15 @@ * \brief Header file for command.c. **/ -#ifndef _TOR_COMMAND_H -#define _TOR_COMMAND_H +#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); +#include "channel.h" + +void command_process_cell(channel_t *chan, cell_t *cell); +void command_process_var_cell(channel_t *chan, var_cell_t *cell); +void command_setup_channel(channel_t *chan); +void command_setup_listener(channel_listener_t *chan_l); extern uint64_t stats_n_padding_cells_processed; extern uint64_t stats_n_create_cells_processed; diff --git a/src/or/config.c b/src/or/config.c index f6db98e667..09fdc0c493 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1,7 +1,7 @@ -/* Copyright (c) 2001 Matej Pfajfar. + /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,21 +12,28 @@ #define CONFIG_PRIVATE #include "or.h" +#include "addressmap.h" +#include "channel.h" #include "circuitbuild.h" #include "circuitlist.h" +#include "circuitmux.h" +#include "circuitmux_ewma.h" #include "config.h" #include "connection.h" #include "connection_edge.h" #include "connection_or.h" #include "control.h" +#include "confparse.h" #include "cpuworker.h" #include "dirserv.h" #include "dirvote.h" #include "dns.h" +#include "entrynodes.h" #include "geoip.h" #include "hibernate.h" #include "main.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "relay.h" #include "rendclient.h" @@ -35,6 +42,8 @@ #include "router.h" #include "util.h" #include "routerlist.h" +#include "routerset.h" +#include "statefile.h" #include "transports.h" #ifdef _WIN32 #include <shlobj.h> @@ -45,51 +54,9 @@ /* From main.c */ extern int quiet_level; -/** Enumeration of types which option values can take */ -typedef enum config_type_t { - CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */ - CONFIG_TYPE_FILENAME, /**< A filename: some prefixes get expanded. */ - CONFIG_TYPE_UINT, /**< A non-negative integer less than MAX_INT */ - CONFIG_TYPE_INT, /**< Any integer. */ - CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or - * "auto". */ - CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/ - CONFIG_TYPE_MSEC_INTERVAL,/**< A number of milliseconds, with optional - * units */ - CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/ - CONFIG_TYPE_DOUBLE, /**< A floating-point value */ - CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */ - CONFIG_TYPE_AUTOBOOL, /**< A boolean+auto value, expressed 0 for false, - * 1 for true, and -1 for auto */ - CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to GMT. */ - CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and - * optional whitespace. */ - CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */ - CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines, - * mixed with other keywords. */ - CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize - * context-sensitive config lines when fetching. - */ - CONFIG_TYPE_ROUTERSET, /**< A list of router names, addrs, and fps, - * parsed into a routerset_t. */ - CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */ -} config_type_t; - -/** An abbreviation for a configuration option allowed on the command line. */ -typedef struct config_abbrev_t { - const char *abbreviated; - const char *full; - int commandline_only; - int warn; -} config_abbrev_t; - -/* Handy macro for declaring "In the config file or on the command line, - * you can abbreviate <b>tok</b>s as <b>tok</b>". */ -#define PLURAL(tok) { #tok, #tok "s", 0, 0 } - /** A list of abbreviations and aliases to map command-line options, obsolete * option names, or alternative option names, to their current values. */ -static config_abbrev_t _option_abbrevs[] = { +static config_abbrev_t option_abbrevs_[] = { PLURAL(AuthDirBadDirCC), PLURAL(AuthDirBadExitCC), PLURAL(AuthDirInvalidCC), @@ -114,6 +81,7 @@ static config_abbrev_t _option_abbrevs[] = { { "BandwidthRateBytes", "BandwidthRate", 0, 0}, { "BandwidthBurstBytes", "BandwidthBurst", 0, 0}, { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0}, + { "DirServer", "DirAuthority", 0, 0}, /* XXXX024 later, make this warn? */ { "MaxConn", "ConnLimit", 0, 1}, { "ORBindAddress", "ORListenAddress", 0, 0}, { "DirBindAddress", "DirListenAddress", 0, 0}, @@ -130,31 +98,11 @@ static config_abbrev_t _option_abbrevs[] = { { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0}, { "StrictEntryNodes", "StrictNodes", 0, 1}, { "StrictExitNodes", "StrictNodes", 0, 1}, + { "VirtualAddrNetwork", "VirtualAddrNetworkIPv4", 0, 0}, + { "_UseFilteringSSLBufferevents", "UseFilteringSSLBufferevents", 0, 1}, { NULL, NULL, 0, 0}, }; -/** A list of state-file "abbreviations," for compatibility. */ -static config_abbrev_t _state_abbrevs[] = { - { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 }, - { "HelperNode", "EntryGuard", 0, 0 }, - { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 }, - { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 }, - { "EntryNode", "EntryGuard", 0, 0 }, - { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 }, - { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 }, - { NULL, NULL, 0, 0}, -}; -#undef PLURAL - -/** A variable allowed in the configuration file or on the command line. */ -typedef struct config_var_t { - const char *name; /**< The full keyword (case insensitive). */ - config_type_t type; /**< How to interpret the type and turn it into a - * value. */ - off_t var_offset; /**< Offset of the corresponding member of or_options_t. */ - const char *initvalue; /**< String (or null) describing initial value. */ -} config_var_t; - /** An entry for config_vars: "The option <b>name</b> has type * CONFIG_TYPE_<b>conftype</b>, and corresponds to * or_options_t.<b>member</b>" @@ -175,7 +123,7 @@ typedef struct config_var_t { * abbreviations, order is significant, since the first matching option will * be chosen first. */ -static config_var_t _option_vars[] = { +static config_var_t option_vars_[] = { OBSOLETE("AccountingMaxKB"), V(AccountingMax, MEMUNIT, "0 bytes"), V(AccountingStart, STRING, NULL), @@ -204,12 +152,13 @@ static config_var_t _option_vars[] = { V(AuthDirListBadExits, BOOL, "0"), V(AuthDirMaxServersPerAddr, UINT, "2"), V(AuthDirMaxServersPerAuthAddr,UINT, "5"), + V(AuthDirHasIPv6Connectivity, BOOL, "0"), VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"), V(AutomapHostsOnResolve, BOOL, "0"), V(AutomapHostsSuffixes, CSV, ".onion,.exit"), V(AvoidDiskWrites, BOOL, "0"), - V(BandwidthBurst, MEMUNIT, "10 MB"), - V(BandwidthRate, MEMUNIT, "5 MB"), + V(BandwidthBurst, MEMUNIT, "1 GB"), + V(BandwidthRate, MEMUNIT, "1 GB"), V(BridgeAuthoritativeDir, BOOL, "0"), VAR("Bridge", LINELIST, Bridges, NULL), V(BridgePassword, STRING, NULL), @@ -223,8 +172,10 @@ static config_var_t _option_vars[] = { V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/ V(ClientDNSRejectInternalAddresses, BOOL,"1"), V(ClientOnly, BOOL, "0"), + V(ClientPreferIPv6ORPort, BOOL, "0"), V(ClientRejectInternalAddresses, BOOL, "1"), V(ClientTransportPlugin, LINELIST, NULL), + V(ClientUseIPv6, BOOL, "0"), V(ConsensusParams, STRING, NULL), V(ConnLimit, UINT, "1000"), V(ConnDirectionStatistics, BOOL, "0"), @@ -257,10 +208,12 @@ static config_var_t _option_vars[] = { OBSOLETE("DirRecordUsageRetainIPs"), OBSOLETE("DirRecordUsageSaveInterval"), V(DirReqStatistics, BOOL, "1"), - VAR("DirServer", LINELIST, DirServers, NULL), + VAR("DirAuthority", LINELIST, DirAuthorities, NULL), + V(DirAuthorityFallbackRate, DOUBLE, "1.0"), V(DisableAllSwap, BOOL, "0"), V(DisableDebuggerAttachment, BOOL, "1"), V(DisableIOCP, BOOL, "1"), + V(DisableV2DirectoryInfo_, BOOL, "0"), V(DynamicDHGroups, BOOL, "0"), VPORT(DNSPort, LINELIST, NULL), V(DNSListenAddress, LINELIST, NULL), @@ -278,13 +231,9 @@ static config_var_t _option_vars[] = { V(ExitPortStatistics, BOOL, "0"), V(ExtendAllowPrivateAddresses, BOOL, "0"), V(ExtraInfoStatistics, BOOL, "1"), + V(FallbackDir, LINELIST, NULL), -#if defined (WINCE) - V(FallbackNetworkstatusFile, FILENAME, "fallback-consensus"), -#else - V(FallbackNetworkstatusFile, FILENAME, - SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "fallback-consensus"), -#endif + OBSOLETE("FallbackNetworkstatusFile"), V(FascistFirewall, BOOL, "0"), V(FirewallPorts, CSV, ""), V(FastFirstHopPK, BOOL, "1"), @@ -294,14 +243,19 @@ static config_var_t _option_vars[] = { V(FetchHidServDescriptors, BOOL, "1"), V(FetchUselessDescriptors, BOOL, "0"), V(FetchV2Networkstatus, BOOL, "0"), + V(GeoIPExcludeUnknown, AUTOBOOL, "auto"), #ifdef _WIN32 V(GeoIPFile, FILENAME, "<default>"), + V(GeoIPv6File, FILENAME, "<default>"), #else V(GeoIPFile, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"), + V(GeoIPv6File, FILENAME, + SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"), #endif OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"), OBSOLETE("Group"), + V(GuardLifetime, INTERVAL, "0 minutes"), V(HardwareAccel, BOOL, "0"), V(HeartbeatPeriod, INTERVAL, "6 hours"), V(AccelName, STRING, NULL), @@ -324,7 +278,9 @@ static config_var_t _option_vars[] = { V(HTTPProxyAuthenticator, STRING, NULL), V(HTTPSProxy, STRING, NULL), V(HTTPSProxyAuthenticator, STRING, NULL), + V(IPv6Exit, BOOL, "0"), VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL), + V(ServerTransportListenAddr, LINELIST, NULL), V(Socks4Proxy, STRING, NULL), V(Socks5Proxy, STRING, NULL), V(Socks5ProxyUsername, STRING, NULL), @@ -344,7 +300,9 @@ static config_var_t _option_vars[] = { V(MaxCircuitDirtiness, INTERVAL, "10 minutes"), V(MaxClientCircuitsPending, UINT, "32"), V(MaxMemInCellQueues, MEMUNIT, "8 GB"), - V(MaxOnionsPending, UINT, "100"), + OBSOLETE("MaxOnionsPending"), + V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"), + V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"), OBSOLETE("MonthlyAccountingStart"), V(MyFamily, STRING, NULL), V(NewCircuitPeriod, INTERVAL, "30 seconds"), @@ -356,22 +314,36 @@ static config_var_t _option_vars[] = { OBSOLETE("NoPublish"), VAR("NodeFamily", LINELIST, NodeFamilies, NULL), V(NumCPUs, UINT, "0"), + V(NumDirectoryGuards, UINT, "0"), V(NumEntryGuards, UINT, "3"), V(ORListenAddress, LINELIST, NULL), VPORT(ORPort, LINELIST, NULL), - V(OutboundBindAddress, STRING, NULL), + V(OutboundBindAddress, LINELIST, NULL), + OBSOLETE("PathBiasDisableRate"), V(PathBiasCircThreshold, INT, "-1"), V(PathBiasNoticeRate, DOUBLE, "-1"), - V(PathBiasDisableRate, DOUBLE, "-1"), + V(PathBiasWarnRate, DOUBLE, "-1"), + V(PathBiasExtremeRate, DOUBLE, "-1"), V(PathBiasScaleThreshold, INT, "-1"), - V(PathBiasScaleFactor, INT, "-1"), + OBSOLETE("PathBiasScaleFactor"), + OBSOLETE("PathBiasMultFactor"), + V(PathBiasDropGuards, AUTOBOOL, "0"), + OBSOLETE("PathBiasUseCloseCounts"), + V(PathBiasUseThreshold, INT, "-1"), + V(PathBiasNoticeUseRate, DOUBLE, "-1"), + V(PathBiasExtremeUseRate, DOUBLE, "-1"), + V(PathBiasScaleUseThreshold, INT, "-1"), + + V(PathsNeededToBuildCircuits, DOUBLE, "-1"), OBSOLETE("PathlenCoinWeight"), V(PerConnBWBurst, MEMUNIT, "0"), V(PerConnBWRate, MEMUNIT, "0"), V(PidFile, STRING, NULL), V(TestingTorNetwork, BOOL, "0"), + V(TestingMinExitFlagThreshold, MEMUNIT, "0"), + V(TestingMinFastFlagThreshold, MEMUNIT, "0"), V(OptimisticData, AUTOBOOL, "auto"), V(PortForwarding, BOOL, "0"), V(PortForwardingHelper, FILENAME, "tor-fw-helper"), @@ -413,13 +385,16 @@ static config_var_t _option_vars[] = { V(SocksPolicy, LINELIST, NULL), VPORT(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), + V(SSLKeyLifetime, INTERVAL, "0"), OBSOLETE("StatusFetchPeriod"), V(StrictNodes, BOOL, "0"), + V(Support022HiddenServices, AUTOBOOL, "auto"), OBSOLETE("SysLog"), V(TestSocks, BOOL, "0"), OBSOLETE("TestVia"), V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), V(Tor2webMode, BOOL, "0"), + V(TLSECGroup, STRING, NULL), V(TrackHostExits, CSV, NULL), V(TrackHostExitsExpire, INTERVAL, "30 minutes"), OBSOLETE("TrafficShaping"), @@ -429,7 +404,9 @@ static config_var_t _option_vars[] = { V(UpdateBridgesFromAuthority, BOOL, "0"), V(UseBridges, BOOL, "0"), V(UseEntryGuards, BOOL, "1"), + V(UseEntryGuardsAsDirGuards, BOOL, "1"), V(UseMicrodescriptors, AUTOBOOL, "auto"), + V(UseNTorHandshake, AUTOBOOL, "auto"), V(User, STRING, NULL), V(UserspaceIOCPBuffers, BOOL, "0"), VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"), @@ -445,9 +422,10 @@ static config_var_t _option_vars[] = { V(V3AuthUseLegacyKey, BOOL, "0"), V(V3BandwidthsFile, FILENAME, NULL), VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"), - V(VirtualAddrNetwork, STRING, "127.192.0.0/10"), + V(VirtualAddrNetworkIPv4, STRING, "127.192.0.0/10"), + V(VirtualAddrNetworkIPv6, STRING, "[FE80::]/10"), V(WarnPlaintextPorts, CSV, "23,109,110,143"), - V(_UseFilteringSSLBufferevents, BOOL, "0"), + V(UseFilteringSSLBufferevents, BOOL, "0"), VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"), VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"), VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"), @@ -457,7 +435,7 @@ static config_var_t _option_vars[] = { VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL), V(MinUptimeHidServDirectoryV2, INTERVAL, "25 hours"), V(VoteOnHidServDirectoriesV2, BOOL, "1"), - V(_UsingTestNetworkDefaults, BOOL, "0"), + VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "0"), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; @@ -485,127 +463,18 @@ static const config_var_t testing_tor_network_defaults[] = { V(TestingAuthDirTimeToLearnReachability, INTERVAL, "0 minutes"), V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"), V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"), - V(_UsingTestNetworkDefaults, BOOL, "1"), + VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "1"), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; -#undef VAR - -#define VAR(name,conftype,member,initvalue) \ - { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), \ - initvalue } - -/** Array of "state" variables saved to the ~/.tor/state file. */ -static config_var_t _state_vars[] = { - /* Remember to document these in state-contents.txt ! */ - - V(AccountingBytesReadInInterval, MEMUNIT, NULL), - V(AccountingBytesWrittenInInterval, MEMUNIT, NULL), - 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), - VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL), - VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL), - VAR("EntryGuardPathBias", LINELIST_S, EntryGuards, NULL), - V(EntryGuards, LINELIST_V, NULL), - - VAR("TransportProxy", LINELIST_S, TransportProxies, NULL), - V(TransportProxies, LINELIST_V, NULL), - - V(BWHistoryReadEnds, ISOTIME, NULL), - V(BWHistoryReadInterval, UINT, "900"), - V(BWHistoryReadValues, CSV, ""), - V(BWHistoryReadMaxima, CSV, ""), - V(BWHistoryWriteEnds, ISOTIME, NULL), - V(BWHistoryWriteInterval, UINT, "900"), - V(BWHistoryWriteValues, CSV, ""), - V(BWHistoryWriteMaxima, CSV, ""), - V(BWHistoryDirReadEnds, ISOTIME, NULL), - V(BWHistoryDirReadInterval, UINT, "900"), - V(BWHistoryDirReadValues, CSV, ""), - V(BWHistoryDirReadMaxima, CSV, ""), - V(BWHistoryDirWriteEnds, ISOTIME, NULL), - V(BWHistoryDirWriteInterval, UINT, "900"), - V(BWHistoryDirWriteValues, CSV, ""), - V(BWHistoryDirWriteMaxima, 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 } -}; #undef VAR #undef V #undef OBSOLETE -/** Represents an English description of a configuration variable; used when - * generating configuration file comments. */ -typedef struct config_var_description_t { - const char *name; - const char *description; -} config_var_description_t; - -/** Type of a callback to validate whether a given configuration is - * well-formed and consistent. See options_trial_assign() for documentation - * of arguments. */ -typedef int (*validate_fn_t)(void*,void*,int,char**); - -/** Information on the keys, value types, key-to-struct-member mappings, - * variable descriptions, validation functions, and abbreviations for a - * configuration or storage format. */ -typedef struct { - size_t size; /**< Size of the struct that everything gets parsed into. */ - uint32_t magic; /**< Required 'magic value' to make sure we have a struct - * of the right type. */ - off_t magic_offset; /**< Offset of the magic value within the struct. */ - config_abbrev_t *abbrevs; /**< List of abbreviations that we expand when - * parsing this format. */ - 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. */ - /** If present, extra is a LINELIST variable for unrecognized - * lines. Otherwise, unrecognized lines are an error. */ - config_var_t *extra; -} config_format_t; - -/** Macro: assert that <b>cfg</b> has the right magic field for format - * <b>fmt</b>. */ -#define CHECK(fmt, cfg) STMT_BEGIN \ - tor_assert(fmt && cfg); \ - tor_assert((fmt)->magic == \ - *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset)); \ - STMT_END - #ifdef _WIN32 static char *get_windows_conf_root(void); #endif -static void config_line_append(config_line_t **lst, - const char *key, const char *val); -static void option_clear(const config_format_t *fmt, or_options_t *options, - const config_var_t *var); -static void option_reset(const config_format_t *fmt, or_options_t *options, - const config_var_t *var, int use_defaults); -static void config_free(const config_format_t *fmt, void *options); -static int config_lines_eq(config_line_t *a, config_line_t *b); -static int config_count_key(const config_line_t *a, const char *key); -static int option_is_same(const config_format_t *fmt, - const or_options_t *o1, const or_options_t *o2, - const char *name); -static or_options_t *options_dup(const config_format_t *fmt, - const or_options_t *old); static int options_validate(or_options_t *old_options, or_options_t *options, int from_setconf, char **msg); @@ -624,9 +493,13 @@ static int parse_bridge_line(const char *line, int validate_only); static int parse_client_transport_line(const char *line, int validate_only); static int parse_server_transport_line(const char *line, int validate_only); -static int parse_dir_server_line(const char *line, +static char *get_bindaddr_from_transport_listen_line(const char *line, + const char *transport); +static int parse_dir_authority_line(const char *line, dirinfo_type_t required_type, int validate_only); +static int parse_dir_fallback_line(const char *line, + int validate_only); static void port_cfg_free(port_cfg_t *port); static int parse_ports(or_options_t *options, int validate_only, char **msg_out, int *n_ports_out); @@ -636,20 +509,14 @@ static int check_server_ports(const smartlist_t *ports, static int validate_data_directory(or_options_t *options); static int write_configuration_file(const char *fname, const or_options_t *options); -static config_line_t *get_assigned_option(const config_format_t *fmt, - const void *options, const char *key, - int escape_val); -static void config_init(const config_format_t *fmt, void *options); -static int or_state_validate(or_state_t *old_options, or_state_t *options, - int from_setconf, char **msg); -static int or_state_load(void); static int options_init_logs(or_options_t *options, int validate_only); -static uint64_t config_parse_memunit(const char *s, int *ok); -static int config_parse_msec_interval(const char *s, int *ok); -static int config_parse_interval(const char *s, int *ok); static void init_libevent(const or_options_t *options); static int opt_streq(const char *s1, const char *s2); +static int parse_outbound_addresses(or_options_t *options, int validate_only, + char **msg); +static void config_maybe_load_geoip_files_(const or_options_t *options, + const or_options_t *old_options); /** Magic value for or_options_t. */ #define OR_OPTIONS_MAGIC 9090909 @@ -658,33 +525,13 @@ static int opt_streq(const char *s1, const char *s2); static config_format_t options_format = { sizeof(or_options_t), OR_OPTIONS_MAGIC, - STRUCT_OFFSET(or_options_t, _magic), - _option_abbrevs, - _option_vars, + STRUCT_OFFSET(or_options_t, magic_), + option_abbrevs_, + option_vars_, (validate_fn_t)options_validate, NULL }; -/** Magic value for or_state_t. */ -#define OR_STATE_MAGIC 0x57A73f57 - -/** "Extra" variable in the state that receives lines we can't parse. This - * lets us preserve options from versions of Tor newer than us. */ -static config_var_t state_extra_var = { - "__extra", CONFIG_TYPE_LINELIST, STRUCT_OFFSET(or_state_t, ExtraLines), NULL -}; - -/** Configuration format for or_state_t. */ -static const config_format_t state_format = { - sizeof(or_state_t), - OR_STATE_MAGIC, - STRUCT_OFFSET(or_state_t, _magic), - _state_abbrevs, - _state_vars, - (validate_fn_t)or_state_validate, - &state_extra_var, -}; - /* * Functions to read and write the global options pointer. */ @@ -698,8 +545,6 @@ static or_options_t *global_default_options = NULL; static char *torrc_fname = NULL; /** Name of the most recently read torrc-defaults file.*/ static char *torrc_defaults_fname; -/** Persistent serialized state. */ -static or_state_t *global_state = NULL; /** Configuration Options set by command line. */ static config_line_t *global_cmdline_options = NULL; /** Contents of most recently read DirPortFrontPage file. */ @@ -714,16 +559,6 @@ get_dirportfrontpage(void) return global_dirfrontpagecontents; } -/** Allocate an empty configuration object of a given format type. */ -static void * -config_alloc(const config_format_t *fmt) -{ - void *opts = tor_malloc_zero(fmt->size); - *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic; - CHECK(fmt, opts); - return opts; -} - /** Return the currently configured options. */ or_options_t * get_options_mutable(void) @@ -774,21 +609,26 @@ set_options(or_options_t *new_val, char **msg) var->type == CONFIG_TYPE_OBSOLETE) { continue; } - if (!option_is_same(&options_format, new_val, old_options, var_name)) { - line = get_assigned_option(&options_format, new_val, var_name, 1); + if (!config_is_same(&options_format, new_val, old_options, var_name)) { + line = config_get_assigned_option(&options_format, new_val, + var_name, 1); if (line) { - for (; line; line = line->next) { + config_line_t *next; + for (; line; line = next) { + next = line->next; smartlist_add(elements, line->key); smartlist_add(elements, line->value); + tor_free(line); } } else { - smartlist_add(elements, (char*)options_format.vars[i].name); + smartlist_add(elements, tor_strdup(options_format.vars[i].name)); smartlist_add(elements, NULL); } } } control_event_conf_changed(elements); + SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); smartlist_free(elements); } @@ -844,13 +684,13 @@ or_options_free(or_options_t *options) if (!options) return; - routerset_free(options->_ExcludeExitNodesUnion); + routerset_free(options->ExcludeExitNodesUnion_); if (options->NodeFamilySets) { SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *, rs, routerset_free(rs)); smartlist_free(options->NodeFamilySets); } - tor_free(options->_BridgePassword_AuthDigest); + tor_free(options->BridgePassword_AuthDigest_); config_free(&options_format, options); } @@ -864,15 +704,12 @@ config_free_all(void) or_options_free(global_default_options); global_default_options = NULL; - config_free(&state_format, global_state); - global_state = NULL; - config_free_lines(global_cmdline_options); global_cmdline_options = NULL; if (configured_ports) { SMARTLIST_FOREACH(configured_ports, - port_cfg_t *, p, tor_free(p)); + port_cfg_t *, p, port_cfg_free(p)); smartlist_free(configured_ports); configured_ports = NULL; } @@ -881,6 +718,9 @@ config_free_all(void) tor_free(torrc_defaults_fname); tor_free(the_tor_version); tor_free(global_dirfrontpagecontents); + + tor_free(the_short_tor_version); + tor_free(the_tor_version); } /** Make <b>address</b> -- a piece of information related to our operation as @@ -893,7 +733,7 @@ const char * safe_str_client(const char *address) { tor_assert(address); - if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL) + if (get_options()->SafeLogging_ == SAFELOG_SCRUB_ALL) return "[scrubbed]"; else return address; @@ -910,7 +750,7 @@ const char * safe_str(const char *address) { tor_assert(address); - if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE) + if (get_options()->SafeLogging_ != SAFELOG_SCRUB_NONE) return "[scrubbed]"; else return address; @@ -922,7 +762,7 @@ safe_str(const char *address) const char * escaped_safe_str_client(const char *address) { - if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL) + if (get_options()->SafeLogging_ == SAFELOG_SCRUB_ALL) return "[scrubbed]"; else return escaped(address); @@ -934,7 +774,7 @@ escaped_safe_str_client(const char *address) const char * escaped_safe_str(const char *address) { - if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE) + if (get_options()->SafeLogging_ != SAFELOG_SCRUB_NONE) return "[scrubbed]"; else return escaped(address); @@ -946,7 +786,7 @@ static void add_default_trusted_dir_authorities(dirinfo_type_t type) { int i; - const char *dirservers[] = { + const char *authorities[] = { "moria1 orport=9101 no-v2 " "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 " "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31", @@ -975,10 +815,27 @@ add_default_trusted_dir_authorities(dirinfo_type_t type) "154.35.32.5:80 CF6D 0AAF B385 BE71 B8E1 11FC 5CFF 4B47 9237 33BC", NULL }; - for (i=0; dirservers[i]; i++) { - if (parse_dir_server_line(dirservers[i], type, 0)<0) { - log_err(LD_BUG, "Couldn't parse internal dirserver line %s", - dirservers[i]); + for (i=0; authorities[i]; i++) { + if (parse_dir_authority_line(authorities[i], type, 0)<0) { + log_err(LD_BUG, "Couldn't parse internal DirAuthority line %s", + authorities[i]); + } + } +} + +/** Add the default fallback directory servers into the fallback directory + * server list. */ +static void +add_default_fallback_dir_servers(void) +{ + int i; + const char *fallback[] = { + NULL + }; + for (i=0; fallback[i]; i++) { + if (parse_dir_fallback_line(fallback[i], 0)<0) { + log_err(LD_BUG, "Couldn't parse internal FallbackDir line %s", + fallback[i]); } } } @@ -988,28 +845,29 @@ add_default_trusted_dir_authorities(dirinfo_type_t type) * user if we changed any dangerous ones. */ static int -validate_dir_authorities(or_options_t *options, or_options_t *old_options) +validate_dir_servers(or_options_t *options, or_options_t *old_options) { config_line_t *cl; - if (options->DirServers && + if (options->DirAuthorities && (options->AlternateDirAuthority || options->AlternateBridgeAuthority || options->AlternateHSAuthority)) { log_warn(LD_CONFIG, - "You cannot set both DirServers and Alternate*Authority."); + "You cannot set both DirAuthority and Alternate*Authority."); return -1; } /* do we want to complain to the user about being partitionable? */ - if ((options->DirServers && + if ((options->DirAuthorities && (!old_options || - !config_lines_eq(options->DirServers, old_options->DirServers))) || + !config_lines_eq(options->DirAuthorities, + old_options->DirAuthorities))) || (options->AlternateDirAuthority && (!old_options || !config_lines_eq(options->AlternateDirAuthority, old_options->AlternateDirAuthority)))) { log_warn(LD_CONFIG, - "You have used DirServer or AlternateDirAuthority to " + "You have used DirAuthority or AlternateDirAuthority to " "specify alternate directory authorities in " "your configuration. This is potentially dangerous: it can " "make you look different from all other Tor users, and hurt " @@ -1020,17 +878,20 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options) /* Now go through the four ways you can configure an alternate * set of directory authorities, and make sure none are broken. */ - for (cl = options->DirServers; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0) + for (cl = options->DirAuthorities; cl; cl = cl->next) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0) return -1; for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0) return -1; for (cl = options->AlternateDirAuthority; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0) return -1; for (cl = options->AlternateHSAuthority; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0) + return -1; + for (cl = options->FallbackDir; cl; cl = cl->next) + if (parse_dir_fallback_line(cl->value, 1)<0) return -1; return 0; } @@ -1039,13 +900,15 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options) * as appropriate. */ static int -consider_adding_dir_authorities(const or_options_t *options, - const or_options_t *old_options) +consider_adding_dir_servers(const or_options_t *options, + const or_options_t *old_options) { config_line_t *cl; int need_to_update = - !smartlist_len(router_get_trusted_dir_servers()) || !old_options || - !config_lines_eq(options->DirServers, old_options->DirServers) || + !smartlist_len(router_get_trusted_dir_servers()) || + !smartlist_len(router_get_fallback_dir_servers()) || !old_options || + !config_lines_eq(options->DirAuthorities, old_options->DirAuthorities) || + !config_lines_eq(options->FallbackDir, old_options->FallbackDir) || !config_lines_eq(options->AlternateBridgeAuthority, old_options->AlternateBridgeAuthority) || !config_lines_eq(options->AlternateDirAuthority, @@ -1057,9 +920,9 @@ consider_adding_dir_authorities(const or_options_t *options, return 0; /* all done */ /* Start from a clean slate. */ - clear_trusted_dir_servers(); + clear_dir_servers(); - if (!options->DirServers) { + if (!options->DirAuthorities) { /* then we may want some of the defaults */ dirinfo_type_t type = NO_DIRINFO; if (!options->AlternateBridgeAuthority) @@ -1071,18 +934,23 @@ consider_adding_dir_authorities(const or_options_t *options, type |= HIDSERV_DIRINFO; add_default_trusted_dir_authorities(type); } + if (!options->FallbackDir) + add_default_fallback_dir_servers(); - for (cl = options->DirServers; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0) + for (cl = options->DirAuthorities; cl; cl = cl->next) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) return -1; for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) return -1; for (cl = options->AlternateDirAuthority; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) return -1; for (cl = options->AlternateHSAuthority; cl; cl = cl->next) - if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0) + if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) + return -1; + for (cl = options->FallbackDir; cl; cl = cl->next) + if (parse_dir_fallback_line(cl->value, 0)<0) return -1; return 0; } @@ -1131,7 +999,7 @@ options_act_reversible(const or_options_t *old_options, char **msg) int n_ports=0; /* We need to set the connection limit before we can open the listeners. */ if (set_max_file_descriptors((unsigned)options->ConnLimit, - &options->_ConnLimit) < 0) { + &options->ConnLimit_) < 0) { *msg = tor_strdup("Problem with ConnLimit value. See logs for details."); goto rollback; } @@ -1237,7 +1105,7 @@ options_act_reversible(const or_options_t *old_options, char **msg) mark_logs_temp(); /* Close current logs once new logs are open. */ logs_marked = 1; - if (options_init_logs(options, 0)<0) { /* Configure the log(s) */ + if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */ *msg = tor_strdup("Failed to init Log options. See logs for details."); goto rollback; } @@ -1272,7 +1140,7 @@ options_act_reversible(const or_options_t *old_options, char **msg) if (set_conn_limit && old_options) set_max_file_descriptors((unsigned)old_options->ConnLimit, - &options->_ConnLimit); + &options->ConnLimit_); SMARTLIST_FOREACH(new_listeners, connection_t *, conn, { @@ -1354,6 +1222,9 @@ options_transition_requires_fresh_tls_context(const or_options_t *old_options, return 1; } + if (!opt_streq(old_options->TLSECGroup, new_options->TLSECGroup)) + return 1; + return 0; } @@ -1372,9 +1243,10 @@ options_act(const or_options_t *old_options) config_line_t *cl; or_options_t *options = get_options_mutable(); int running_tor = options->command == CMD_RUN_TOR; - char *msg; + char *msg=NULL; const int transition_affects_workers = old_options && options_transition_affects_workers(old_options, options); + int old_ewma_enabled; /* disable ptrace and later, other basic debugging techniques */ { @@ -1405,11 +1277,11 @@ options_act(const or_options_t *old_options) return -1; } - if (consider_adding_dir_authorities(options, old_options) < 0) + if (consider_adding_dir_servers(options, old_options) < 0) return -1; #ifdef NON_ANONYMOUS_MODE_ENABLED - log(LOG_WARN, LD_GENERAL, "This copy of Tor was compiled to run in a " + log_warn(LD_GENERAL, "This copy of Tor was compiled to run in a " "non-anonymous mode. It will provide NO ANONYMITY."); #endif @@ -1455,7 +1327,7 @@ options_act(const or_options_t *old_options) } /* Load state */ - if (! global_state && running_tor) { + if (! or_state_loaded() && running_tor) { if (or_state_load()) return -1; rep_hist_load_mtbf_data(time(NULL)); @@ -1541,7 +1413,8 @@ options_act(const or_options_t *old_options) /* Register addressmap directives */ config_register_addressmaps(options); - parse_virtual_addr_network(options->VirtualAddrNetwork, 0, &msg); + parse_virtual_addr_network(options->VirtualAddrNetworkIPv4, AF_INET,0,NULL); + parse_virtual_addr_network(options->VirtualAddrNetworkIPv6, AF_INET6,0,NULL); /* Update address policies. */ if (policies_parse_from_options(options) < 0) { @@ -1558,7 +1431,7 @@ options_act(const or_options_t *old_options) monitor_owning_controller_process(options->OwningControllerProcess); /* reload keys as needed for rendezvous services. */ - if (rend_service_load_keys()<0) { + if (rend_service_load_all_keys()<0) { log_warn(LD_GENERAL,"Error loading rendezvous service keys"); return -1; } @@ -1582,8 +1455,16 @@ options_act(const or_options_t *old_options) connection_bucket_init(); #endif + old_ewma_enabled = cell_ewma_enabled(); /* Change the cell EWMA settings */ cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus()); + /* If we just enabled ewma, set the cmux policy on all active channels */ + if (cell_ewma_enabled() && !old_ewma_enabled) { + channel_set_cmux_policy_everywhere(&ewma_policy); + } else if (!cell_ewma_enabled() && old_ewma_enabled) { + /* Turn it off everywhere */ + channel_set_cmux_policy_everywhere(NULL); + } /* Update the BridgePassword's hashed version as needed. We store this as a * digest so that we can do side-channel-proof comparisons on it. @@ -1596,13 +1477,19 @@ options_act(const or_options_t *old_options) "BridgePassword."); return -1; } - options->_BridgePassword_AuthDigest = tor_malloc(DIGEST256_LEN); - crypto_digest256(options->_BridgePassword_AuthDigest, + options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN); + crypto_digest256(options->BridgePassword_AuthDigest_, http_authenticator, strlen(http_authenticator), DIGEST_SHA256); tor_free(http_authenticator); } + if (parse_outbound_addresses(options, 0, &msg) < 0) { + log_warn(LD_BUG, "Failed parsing oubound bind addresses: %s", msg); + tor_free(msg); + return -1; + } + /* Check for transitions that need action. */ if (old_options) { int revise_trackexithosts = 0; @@ -1622,7 +1509,7 @@ options_act(const or_options_t *old_options) "preferred or excluded node lists. " "Abandoning previous circuits."); circuit_mark_all_unused_circs(); - circuit_expire_all_dirty_circs(); + circuit_mark_all_dirty_circs_as_unusable(); revise_trackexithosts = 1; } @@ -1640,8 +1527,10 @@ options_act(const or_options_t *old_options) if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes, options->AutomapHostsSuffixes)) revise_automap_entries = 1; - else if (!opt_streq(old_options->VirtualAddrNetwork, - options->VirtualAddrNetwork)) + else if (!opt_streq(old_options->VirtualAddrNetworkIPv4, + options->VirtualAddrNetworkIPv4) || + !opt_streq(old_options->VirtualAddrNetworkIPv6, + options->VirtualAddrNetworkIPv6)) revise_automap_entries = 1; } @@ -1696,23 +1585,18 @@ options_act(const or_options_t *old_options) connection_or_update_token_buckets(get_connection_array(), options); } - /* Maybe load geoip file */ - if (options->GeoIPFile && - ((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile)) - || !geoip_is_loaded())) { - /* XXXX Don't use this "<default>" junk; make our filename options - * understand prefixes somehow. -NM */ - /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */ - char *actual_fname = tor_strdup(options->GeoIPFile); -#ifdef _WIN32 - if (!strcmp(actual_fname, "<default>")) { - const char *conf_root = get_windows_conf_root(); - tor_free(actual_fname); - tor_asprintf(&actual_fname, "%s\\geoip", conf_root); - } -#endif - geoip_load_file(actual_fname, options); - tor_free(actual_fname); + config_maybe_load_geoip_files_(options, old_options); + + if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { + /* ExcludeUnknown is true or "auto" */ + const int is_auto = options->GeoIPExcludeUnknown == -1; + int changed; + + changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto); + changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto); + + if (changed) + routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto); } if (options->CellStatistics || options->DirReqStatistics || @@ -1737,7 +1621,7 @@ options_act(const or_options_t *old_options) } if ((!old_options || !old_options->DirReqStatistics) && options->DirReqStatistics) { - if (geoip_is_loaded()) { + if (geoip_is_loaded(AF_INET)) { geoip_dirreq_stats_init(now); print_notice = 1; } else { @@ -1752,7 +1636,7 @@ options_act(const or_options_t *old_options) } if ((!old_options || !old_options->EntryStatistics) && options->EntryStatistics && !should_record_bridge_info(options)) { - if (geoip_is_loaded()) { + if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) { geoip_entry_stats_init(now); print_notice = 1; } else { @@ -1848,42 +1732,6 @@ options_act(const or_options_t *old_options) return 0; } -/* - * Functions to parse config options - */ - -/** If <b>option</b> is an official abbreviation for a longer option, - * return the longer option. Otherwise return <b>option</b>. - * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only - * apply abbreviations that work for the config file and the command line. - * If <b>warn_obsolete</b> is set, warn about deprecated names. */ -static const char * -expand_abbrev(const config_format_t *fmt, const char *option, int command_line, - int warn_obsolete) -{ - int i; - if (! fmt->abbrevs) - return option; - for (i=0; fmt->abbrevs[i].abbreviated; ++i) { - /* Abbreviations are case insensitive. */ - if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) && - (command_line || !fmt->abbrevs[i].commandline_only)) { - if (warn_obsolete && fmt->abbrevs[i].warn) { - log_warn(LD_CONFIG, - "The configuration option '%s' is deprecated; " - "use '%s' instead.", - fmt->abbrevs[i].abbreviated, - 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; -} - /** Helper: Read a list of configuration options from the command line. * If successful, put them in *<b>result</b> and return 0, and return * -1 and leave *<b>result</b> alone. */ @@ -1943,11 +1791,11 @@ config_get_commandlines(int argc, char **argv, config_line_t **result) return -1; } - (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1)); + (*new)->key = tor_strdup(config_expand_abbrev(&options_format, s, 1, 1)); (*new)->value = want_arg ? tor_strdup(argv[i+1]) : tor_strdup(""); (*new)->command = command; (*new)->next = NULL; - log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'", + log_debug(LD_CONFIG, "command line: parsed keyword '%s', value '%s'", (*new)->key, (*new)->value); new = &((*new)->next); @@ -1957,444 +1805,6 @@ config_get_commandlines(int argc, char **argv, config_line_t **result) return 0; } -/** Helper: allocate a new configuration option mapping 'key' to 'val', - * append it to *<b>lst</b>. */ -static void -config_line_append(config_line_t **lst, - const char *key, - const char *val) -{ - config_line_t *newline; - - newline = tor_malloc_zero(sizeof(config_line_t)); - newline->key = tor_strdup(key); - newline->value = tor_strdup(val); - newline->next = NULL; - while (*lst) - lst = &((*lst)->next); - - (*lst) = newline; -} - -/** Helper: parse the config string and strdup into key/value - * strings. Set *result to the list, or NULL if parsing the string - * failed. Return 0 on success, -1 on failure. Warn and ignore any - * misformatted lines. - * - * If <b>extended</b> is set, then treat keys beginning with / and with + as - * indicating "clear" and "append" respectively. */ -int -config_get_lines(const char *string, config_line_t **result, int extended) -{ - config_line_t *list = NULL, **next; - char *k, *v; - - next = &list; - do { - k = v = NULL; - string = parse_config_line_from_str(string, &k, &v); - if (!string) { - config_free_lines(list); - tor_free(k); - tor_free(v); - return -1; - } - if (k && v) { - unsigned command = CONFIG_LINE_NORMAL; - if (extended) { - if (k[0] == '+') { - char *k_new = tor_strdup(k+1); - tor_free(k); - k = k_new; - command = CONFIG_LINE_APPEND; - } else if (k[0] == '/') { - char *k_new = tor_strdup(k+1); - tor_free(k); - k = k_new; - tor_free(v); - v = tor_strdup(""); - command = CONFIG_LINE_CLEAR; - } - } - /* This list can get long, so we keep a pointer to the end of it - * rather than using config_line_append over and over and getting - * n^2 performance. */ - *next = tor_malloc_zero(sizeof(config_line_t)); - (*next)->key = k; - (*next)->value = v; - (*next)->next = NULL; - (*next)->command = command; - next = &((*next)->next); - } else { - tor_free(k); - tor_free(v); - } - } while (*string); - - *result = list; - return 0; -} - -/** - * Free all the configuration lines on the linked list <b>front</b>. - */ -void -config_free_lines(config_line_t *front) -{ - config_line_t *tmp; - - while (front) { - tmp = front; - front = tmp->next; - - tor_free(tmp->key); - tor_free(tmp->value); - tor_free(tmp); - } -} - -/** As config_find_option, but return a non-const pointer. */ -static config_var_t * -config_find_option_mutable(config_format_t *fmt, const char *key) -{ - int i; - size_t keylen = strlen(key); - if (!keylen) - return NULL; /* if they say "--" on the command line, it's not an option */ - /* First, check for an exact (case-insensitive) match */ - for (i=0; fmt->vars[i].name; ++i) { - if (!strcasecmp(key, fmt->vars[i].name)) { - return &fmt->vars[i]; - } - } - /* If none, check for an abbreviated match */ - for (i=0; fmt->vars[i].name; ++i) { - if (!strncasecmp(key, fmt->vars[i].name, keylen)) { - log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. " - "Please use '%s' instead", - key, fmt->vars[i].name); - return &fmt->vars[i]; - } - } - /* Okay, unrecognized option */ - return NULL; -} - -/** If <b>key</b> is a configuration option, return the corresponding const - * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation, - * warn, and return the corresponding const config_var_t. Otherwise return - * NULL. - */ -static const config_var_t * -config_find_option(const config_format_t *fmt, const char *key) -{ - return config_find_option_mutable((config_format_t*)fmt, key); -} - -/** Return the number of option entries in <b>fmt</b>. */ -static int -config_count_options(const config_format_t *fmt) -{ - int i; - for (i=0; fmt->vars[i].name; ++i) - ; - return i; -} - -/* - * Functions to assign config options. - */ - -/** <b>c</b>-\>key is known to be a real key. Update <b>options</b> - * with <b>c</b>-\>value and return 0, or return -1 if bad value. - * - * Called from config_assign_line() and option_reset(). - */ -static int -config_assign_value(const config_format_t *fmt, or_options_t *options, - config_line_t *c, char **msg) -{ - int i, ok; - const config_var_t *var; - void *lvalue; - - CHECK(fmt, options); - - var = config_find_option(fmt, c->key); - tor_assert(var); - - lvalue = STRUCT_VAR_P(options, var->var_offset); - - switch (var->type) { - - case CONFIG_TYPE_PORT: - if (!strcasecmp(c->value, "auto")) { - *(int *)lvalue = CFG_AUTO_PORT; - break; - } - /* fall through */ - case CONFIG_TYPE_INT: - case CONFIG_TYPE_UINT: - i = (int)tor_parse_long(c->value, 10, - var->type==CONFIG_TYPE_INT ? INT_MIN : 0, - var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX, - &ok, NULL); - if (!ok) { - tor_asprintf(msg, - "Int keyword '%s %s' is malformed or out of bounds.", - c->key, c->value); - return -1; - } - *(int *)lvalue = i; - break; - - case CONFIG_TYPE_INTERVAL: { - i = config_parse_interval(c->value, &ok); - if (!ok) { - tor_asprintf(msg, - "Interval '%s %s' is malformed or out of bounds.", - c->key, c->value); - return -1; - } - *(int *)lvalue = i; - break; - } - - case CONFIG_TYPE_MSEC_INTERVAL: { - i = config_parse_msec_interval(c->value, &ok); - if (!ok) { - tor_asprintf(msg, - "Msec interval '%s %s' is malformed or out of bounds.", - c->key, c->value); - return -1; - } - *(int *)lvalue = i; - break; - } - - case CONFIG_TYPE_MEMUNIT: { - uint64_t u64 = config_parse_memunit(c->value, &ok); - if (!ok) { - tor_asprintf(msg, - "Value '%s %s' is malformed or out of bounds.", - c->key, c->value); - return -1; - } - *(uint64_t *)lvalue = u64; - break; - } - - case CONFIG_TYPE_BOOL: - i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL); - if (!ok) { - tor_asprintf(msg, - "Boolean '%s %s' expects 0 or 1.", - c->key, c->value); - return -1; - } - *(int *)lvalue = i; - break; - - case CONFIG_TYPE_AUTOBOOL: - if (!strcmp(c->value, "auto")) - *(int *)lvalue = -1; - else if (!strcmp(c->value, "0")) - *(int *)lvalue = 0; - else if (!strcmp(c->value, "1")) - *(int *)lvalue = 1; - else { - tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.", - c->key, c->value); - return -1; - } - break; - - case CONFIG_TYPE_STRING: - case CONFIG_TYPE_FILENAME: - tor_free(*(char **)lvalue); - *(char **)lvalue = tor_strdup(c->value); - break; - - case CONFIG_TYPE_DOUBLE: - *(double *)lvalue = atof(c->value); - break; - - case CONFIG_TYPE_ISOTIME: - if (parse_iso_time(c->value, (time_t *)lvalue)) { - tor_asprintf(msg, - "Invalid time '%s' for keyword '%s'", c->value, c->key); - return -1; - } - break; - - case CONFIG_TYPE_ROUTERSET: - if (*(routerset_t**)lvalue) { - routerset_free(*(routerset_t**)lvalue); - } - *(routerset_t**)lvalue = routerset_new(); - if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) { - tor_asprintf(msg, "Invalid exit list '%s' for option '%s'", - c->value, c->key); - return -1; - } - break; - - case CONFIG_TYPE_CSV: - if (*(smartlist_t**)lvalue) { - SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp)); - smartlist_clear(*(smartlist_t**)lvalue); - } else { - *(smartlist_t**)lvalue = smartlist_new(); - } - - smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - break; - - case CONFIG_TYPE_LINELIST: - case CONFIG_TYPE_LINELIST_S: - { - config_line_t *lastval = *(config_line_t**)lvalue; - if (lastval && lastval->fragile) { - if (c->command != CONFIG_LINE_APPEND) { - config_free_lines(lastval); - *(config_line_t**)lvalue = NULL; - } else { - lastval->fragile = 0; - } - } - - config_line_append((config_line_t**)lvalue, c->key, c->value); - } - break; - case CONFIG_TYPE_OBSOLETE: - log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key); - break; - case CONFIG_TYPE_LINELIST_V: - tor_asprintf(msg, - "You may not provide a value for virtual option '%s'", c->key); - return -1; - default: - tor_assert(0); - break; - } - return 0; -} - -/** Mark every linelist in <b>options</b> "fragile", so that fresh assignments - * to it will replace old ones. */ -static void -config_mark_lists_fragile(const config_format_t *fmt, or_options_t *options) -{ - int i; - tor_assert(fmt); - tor_assert(options); - - for (i = 0; fmt->vars[i].name; ++i) { - const config_var_t *var = &fmt->vars[i]; - config_line_t *list; - if (var->type != CONFIG_TYPE_LINELIST && - var->type != CONFIG_TYPE_LINELIST_V) - continue; - - list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset); - if (list) - list->fragile = 1; - } -} - -/** If <b>c</b> is a syntactically valid configuration line, update - * <b>options</b> with its value and return 0. Otherwise return -1 for bad - * key, -2 for bad value. - * - * If <b>clear_first</b> is set, clear the value first. Then if - * <b>use_defaults</b> is set, set the value to the default. - * - * Called from config_assign(). - */ -static int -config_assign_line(const config_format_t *fmt, or_options_t *options, - config_line_t *c, int use_defaults, - int clear_first, bitarray_t *options_seen, char **msg) -{ - const config_var_t *var; - - CHECK(fmt, options); - - var = config_find_option(fmt, c->key); - if (!var) { - if (fmt->extra) { - void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset); - log_info(LD_CONFIG, - "Found unrecognized option '%s'; saving it.", c->key); - config_line_append((config_line_t**)lvalue, c->key, c->value); - return 0; - } else { - tor_asprintf(msg, - "Unknown option '%s'. Failing.", c->key); - return -1; - } - } - - /* Put keyword into canonical case. */ - if (strcmp(var->name, c->key)) { - tor_free(c->key); - c->key = tor_strdup(var->name); - } - - if (!strlen(c->value)) { - /* reset or clear it, then return */ - if (!clear_first) { - if ((var->type == CONFIG_TYPE_LINELIST || - var->type == CONFIG_TYPE_LINELIST_S) && - c->command != CONFIG_LINE_CLEAR) { - /* We got an empty linelist from the torrc or command line. - As a special case, call this an error. Warn and ignore. */ - log_warn(LD_CONFIG, - "Linelist option '%s' has no value. Skipping.", c->key); - } else { /* not already cleared */ - option_reset(fmt, options, var, use_defaults); - } - } - return 0; - } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) { - option_reset(fmt, options, var, use_defaults); - } - - if (options_seen && (var->type != CONFIG_TYPE_LINELIST && - 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; -} - -/** Restore the option named <b>key</b> in options to its default value. - * Called from config_assign(). */ -static void -config_reset_line(const config_format_t *fmt, or_options_t *options, - const char *key, int use_defaults) -{ - const config_var_t *var; - - CHECK(fmt, options); - - var = config_find_option(fmt, key); - if (!var) - return; /* give error on next pass. */ - - option_reset(fmt, options, var, use_defaults); -} - /** Return true iff key is a valid configuration option. */ int option_is_recognized(const char *key) @@ -2417,287 +1827,7 @@ option_get_canonical_name(const char *key) config_line_t * option_get_assignment(const or_options_t *options, const char *key) { - return get_assigned_option(&options_format, options, key, 1); -} - -/** Return true iff value needs to be quoted and escaped to be used in - * a configuration file. */ -static int -config_value_needs_escape(const char *value) -{ - if (*value == '\"') - return 1; - while (*value) { - switch (*value) - { - case '\r': - case '\n': - case '#': - /* Note: quotes and backspaces need special handling when we are using - * quotes, not otherwise, so they don't trigger escaping on their - * own. */ - return 1; - default: - if (!TOR_ISPRINT(*value)) - return 1; - } - ++value; - } - return 0; -} - -/** Return a newly allocated deep copy of the lines in <b>inp</b>. */ -static config_line_t * -config_lines_dup(const config_line_t *inp) -{ - config_line_t *result = NULL; - config_line_t **next_out = &result; - while (inp) { - *next_out = tor_malloc_zero(sizeof(config_line_t)); - (*next_out)->key = tor_strdup(inp->key); - (*next_out)->value = tor_strdup(inp->value); - inp = inp->next; - next_out = &((*next_out)->next); - } - (*next_out) = NULL; - return result; -} - -/** Return newly allocated line or lines corresponding to <b>key</b> in the - * configuration <b>options</b>. If <b>escape_val</b> is true and a - * value needs to be quoted before it's put in a config file, quote and - * escape that value. Return NULL if no such key exists. */ -static config_line_t * -get_assigned_option(const config_format_t *fmt, const void *options, - const char *key, int escape_val) -{ - const config_var_t *var; - const void *value; - config_line_t *result; - tor_assert(options && key); - - CHECK(fmt, options); - - var = config_find_option(fmt, key); - if (!var) { - log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key); - return NULL; - } - value = STRUCT_VAR_P(options, var->var_offset); - - result = tor_malloc_zero(sizeof(config_line_t)); - result->key = tor_strdup(var->name); - switch (var->type) - { - case CONFIG_TYPE_STRING: - case CONFIG_TYPE_FILENAME: - if (*(char**)value) { - result->value = tor_strdup(*(char**)value); - } else { - tor_free(result->key); - tor_free(result); - return NULL; - } - break; - case CONFIG_TYPE_ISOTIME: - if (*(time_t*)value) { - result->value = tor_malloc(ISO_TIME_LEN+1); - format_iso_time(result->value, *(time_t*)value); - } else { - tor_free(result->key); - tor_free(result); - } - escape_val = 0; /* Can't need escape. */ - break; - case CONFIG_TYPE_PORT: - if (*(int*)value == CFG_AUTO_PORT) { - result->value = tor_strdup("auto"); - escape_val = 0; - break; - } - /* fall through */ - case CONFIG_TYPE_INTERVAL: - case CONFIG_TYPE_MSEC_INTERVAL: - case CONFIG_TYPE_UINT: - case CONFIG_TYPE_INT: - /* This means every or_options_t uint or bool element - * needs to be an int. Not, say, a uint16_t or char. */ - tor_asprintf(&result->value, "%d", *(int*)value); - escape_val = 0; /* Can't need escape. */ - break; - case CONFIG_TYPE_MEMUNIT: - tor_asprintf(&result->value, U64_FORMAT, - U64_PRINTF_ARG(*(uint64_t*)value)); - escape_val = 0; /* Can't need escape. */ - break; - case CONFIG_TYPE_DOUBLE: - tor_asprintf(&result->value, "%f", *(double*)value); - escape_val = 0; /* Can't need escape. */ - break; - - case CONFIG_TYPE_AUTOBOOL: - if (*(int*)value == -1) { - result->value = tor_strdup("auto"); - escape_val = 0; - break; - } - /* fall through */ - case CONFIG_TYPE_BOOL: - result->value = tor_strdup(*(int*)value ? "1" : "0"); - escape_val = 0; /* Can't need escape. */ - break; - case CONFIG_TYPE_ROUTERSET: - result->value = routerset_to_string(*(routerset_t**)value); - break; - case CONFIG_TYPE_CSV: - if (*(smartlist_t**)value) - result->value = - smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL); - else - result->value = tor_strdup(""); - break; - case CONFIG_TYPE_OBSOLETE: - log_fn(LOG_PROTOCOL_WARN, LD_CONFIG, - "You asked me for the value of an obsolete config option '%s'.", - key); - tor_free(result->key); - tor_free(result); - return NULL; - case CONFIG_TYPE_LINELIST_S: - log_warn(LD_CONFIG, - "Can't return context-sensitive '%s' on its own", key); - tor_free(result->key); - tor_free(result); - return NULL; - case CONFIG_TYPE_LINELIST: - case CONFIG_TYPE_LINELIST_V: - tor_free(result->key); - tor_free(result); - result = config_lines_dup(*(const config_line_t**)value); - break; - default: - tor_free(result->key); - tor_free(result); - log_warn(LD_BUG,"Unknown type %d for known key '%s'", - var->type, key); - return NULL; - } - - if (escape_val) { - config_line_t *line; - for (line = result; line; line = line->next) { - if (line->value && config_value_needs_escape(line->value)) { - char *newval = esc_for_log(line->value); - tor_free(line->value); - line->value = newval; - } - } - } - - return result; -} - -/** Iterate through the linked list of requested options <b>list</b>. - * For each item, convert as appropriate and assign to <b>options</b>. - * If an item is unrecognized, set *msg and return -1 immediately, - * else return 0 for success. - * - * If <b>clear_first</b>, interpret config options as replacing (not - * extending) their previous values. If <b>clear_first</b> is set, - * then <b>use_defaults</b> to decide if you set to defaults after - * clearing, or make the value 0 or NULL. - * - * Here are the use cases: - * 1. A non-empty AllowInvalid line in your torrc. Appends to current - * if linelist, replaces current if csv. - * 2. An empty AllowInvalid line in your torrc. Should clear it. - * 3. "RESETCONF AllowInvalid" sets it to default. - * 4. "SETCONF AllowInvalid" makes it NULL. - * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo". - * - * Use_defaults Clear_first - * 0 0 "append" - * 1 0 undefined, don't use - * 0 1 "set to null first" - * 1 1 "set to defaults first" - * Return 0 on success, -1 on bad key, -2 on bad value. - * - * As an additional special case, if a LINELIST config option has - * no value and clear_first is 0, then warn and ignore it. - */ - -/* -There are three call cases for config_assign() currently. - -Case one: Torrc entry -options_init_from_torrc() calls config_assign(0, 0) - calls config_assign_line(0, 0). - if value is empty, calls option_reset(0) and returns. - calls config_assign_value(), appends. - -Case two: setconf -options_trial_assign() calls config_assign(0, 1) - calls config_reset_line(0) - calls option_reset(0) - calls option_clear(). - calls config_assign_line(0, 1). - if value is empty, returns. - calls config_assign_value(), appends. - -Case three: resetconf -options_trial_assign() calls config_assign(1, 1) - calls config_reset_line(1) - calls option_reset(1) - calls option_clear(). - calls config_assign_value(default) - calls config_assign_line(1, 1). - returns. -*/ -static int -config_assign(const config_format_t *fmt, void *options, config_line_t *list, - int use_defaults, int clear_first, char **msg) -{ - config_line_t *p; - bitarray_t *options_seen; - const int n_options = config_count_options(fmt); - - CHECK(fmt, options); - - /* pass 1: normalize keys */ - for (p = list; p; p = p->next) { - const char *full = expand_abbrev(fmt, p->key, 0, 1); - if (strcmp(full,p->key)) { - tor_free(p->key); - p->key = tor_strdup(full); - } - } - - /* pass 2: if we're reading from a resetting source, clear all - * mentioned config options, and maybe set to their defaults. */ - if (clear_first) { - for (p = list; p; p = p->next) - 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, options_seen, msg))) { - bitarray_free(options_seen); - return r; - } - list = list->next; - } - bitarray_free(options_seen); - - /** Now we're done assigning a group of options to the configuration. - * Subsequent group assignments should _replace_ linelists, not extend - * them. */ - config_mark_lists_fragile(fmt, options); - - return 0; + return config_get_assigned_option(&options_format, options, key, 1); } /** Try assigning <b>list</b> to the global options. You do this by duping @@ -2714,7 +1844,7 @@ options_trial_assign(config_line_t *list, int use_defaults, int clear_first, char **msg) { int r; - or_options_t *trial_options = options_dup(&options_format, get_options()); + or_options_t *trial_options = config_dup(&options_format, get_options()); if ((r=config_assign(&options_format, trial_options, list, use_defaults, clear_first, msg)) < 0) { @@ -2741,90 +1871,6 @@ options_trial_assign(config_line_t *list, int use_defaults, return SETOPT_OK; } -/** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent. - * Called from option_reset() and config_free(). */ -static void -option_clear(const config_format_t *fmt, or_options_t *options, - const config_var_t *var) -{ - void *lvalue = STRUCT_VAR_P(options, var->var_offset); - (void)fmt; /* unused */ - switch (var->type) { - case CONFIG_TYPE_STRING: - case CONFIG_TYPE_FILENAME: - tor_free(*(char**)lvalue); - break; - case CONFIG_TYPE_DOUBLE: - *(double*)lvalue = 0.0; - break; - case CONFIG_TYPE_ISOTIME: - *(time_t*)lvalue = 0; - break; - case CONFIG_TYPE_INTERVAL: - case CONFIG_TYPE_MSEC_INTERVAL: - case CONFIG_TYPE_UINT: - case CONFIG_TYPE_INT: - case CONFIG_TYPE_PORT: - case CONFIG_TYPE_BOOL: - *(int*)lvalue = 0; - break; - case CONFIG_TYPE_AUTOBOOL: - *(int*)lvalue = -1; - break; - case CONFIG_TYPE_MEMUNIT: - *(uint64_t*)lvalue = 0; - break; - case CONFIG_TYPE_ROUTERSET: - if (*(routerset_t**)lvalue) { - routerset_free(*(routerset_t**)lvalue); - *(routerset_t**)lvalue = NULL; - } - break; - case CONFIG_TYPE_CSV: - if (*(smartlist_t**)lvalue) { - SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp)); - smartlist_free(*(smartlist_t **)lvalue); - *(smartlist_t **)lvalue = NULL; - } - break; - case CONFIG_TYPE_LINELIST: - case CONFIG_TYPE_LINELIST_S: - config_free_lines(*(config_line_t **)lvalue); - *(config_line_t **)lvalue = NULL; - break; - case CONFIG_TYPE_LINELIST_V: - /* handled by linelist_s. */ - break; - case CONFIG_TYPE_OBSOLETE: - break; - } -} - -/** Clear the option indexed by <b>var</b> in <b>options</b>. Then if - * <b>use_defaults</b>, set it to its default value. - * Called by config_init() and option_reset_line() and option_assign_line(). */ -static void -option_reset(const config_format_t *fmt, or_options_t *options, - const config_var_t *var, int use_defaults) -{ - config_line_t *c; - char *msg = NULL; - CHECK(fmt, options); - option_clear(fmt, options, var); /* clear it first */ - if (!use_defaults) - return; /* all done */ - if (var->initvalue) { - c = tor_malloc_zero(sizeof(config_line_t)); - c->key = tor_strdup(var->name); - c->value = tor_strdup(var->initvalue); - if (config_assign_value(fmt, options, c, &msg) < 0) { - log_warn(LD_BUG, "Failed to assign default: %s", msg); - tor_free(msg); /* if this happens it's a bug */ - } - config_free_lines(c); - } -} - /** Print a usage message for tor. */ static void print_usage(void) @@ -2832,7 +1878,7 @@ print_usage(void) printf( "Copyright (c) 2001-2004, Roger Dingledine\n" "Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n" -"Copyright (c) 2007-2012, The Tor Project, Inc.\n\n" +"Copyright (c) 2007-2013, The Tor Project, Inc.\n\n" "tor -f <torrc> [args]\n" "See man page for options, or https://www.torproject.org/ for " "documentation.\n"); @@ -2844,8 +1890,8 @@ list_torrc_options(void) { int i; smartlist_t *lines = smartlist_new(); - for (i = 0; _option_vars[i].name; ++i) { - const config_var_t *var = &_option_vars[i]; + for (i = 0; option_vars_[i].name; ++i) { + const config_var_t *var = &option_vars_[i]; if (var->type == CONFIG_TYPE_OBSOLETE || var->type == CONFIG_TYPE_LINELIST_V) continue; @@ -2856,21 +1902,41 @@ list_torrc_options(void) /** Last value actually set by resolve_my_address. */ static uint32_t last_resolved_addr = 0; + +/** Accessor for last_resolved_addr from outside this file. */ +uint32_t +get_last_resolved_addr(void) +{ + return last_resolved_addr; +} + /** - * Based on <b>options-\>Address</b>, guess our public IP address and put it - * (in host order) into *<b>addr_out</b>. If <b>hostname_out</b> is provided, - * set *<b>hostname_out</b> to a new string holding the hostname we used to - * get the address. Return 0 if all is well, or -1 if we can't find a suitable + * Use <b>options-\>Address</b> to guess our public IP address. + * + * Return 0 if all is well, or -1 if we can't find a suitable * public IP address. + * + * If we are returning 0: + * - Put our public IP address (in host order) into *<b>addr_out</b>. + * - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static + * string describing how we arrived at our answer. + * - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to + * get our address, set *<b>hostname_out</b> to a newly allocated string + * holding that hostname. (If we didn't get our address by resolving a + * hostname, set *<b>hostname_out</b> to NULL.) + * * XXXX ipv6 */ int resolve_my_address(int warn_severity, const or_options_t *options, - uint32_t *addr_out, char **hostname_out) + uint32_t *addr_out, + const char **method_out, char **hostname_out) { struct in_addr in; uint32_t addr; /* host order */ char hostname[256]; + const char *method_used; + const char *hostname_used; int explicit_ip=1; int explicit_hostname=1; int from_interface=0; @@ -2881,6 +1947,10 @@ resolve_my_address(int warn_severity, const or_options_t *options, tor_assert(addr_out); + /* + * Step one: Fill in 'hostname' to be our best guess. + */ + if (address && *address) { strlcpy(hostname, address, sizeof(hostname)); } else { /* then we need to guess our address */ @@ -2891,10 +1961,14 @@ resolve_my_address(int warn_severity, const or_options_t *options, log_fn(warn_severity, LD_NET,"Error obtaining local hostname"); return -1; } - log_debug(LD_CONFIG,"Guessed local host name as '%s'",hostname); + log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname); } - /* now we know hostname. resolve it and keep only the IP address */ + /* + * Step two: Now that we know 'hostname', parse it or resolve it. If + * it doesn't parse or resolve, look at the interface address. Set 'addr' + * to be our (host-order) 32-bit answer. + */ if (tor_inet_aton(hostname, &in) == 0) { /* then we have to resolve it */ @@ -2951,21 +2025,26 @@ resolve_my_address(int warn_severity, const or_options_t *options, * illformed */ } + /* + * Step three: Check whether 'addr' is an internal IP address, and error + * out if it is and we don't want that. + */ + addr_string = tor_dup_ip(addr); if (is_internal_IP(addr, 0)) { /* make sure we're ok with publishing an internal IP */ - if (!options->DirServers && !options->AlternateDirAuthority) { - /* if they are using the default dirservers, disallow internal IPs + if (!options->DirAuthorities && !options->AlternateDirAuthority) { + /* if they are using the default authorities, disallow internal IPs * always. */ log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private IP address '%s'. " - "Tor servers that use the default DirServers must have public " - "IP addresses.", hostname, addr_string); + "Tor servers that use the default DirAuthorities must have " + "public IP addresses.", hostname, addr_string); tor_free(addr_string); return -1; } if (!explicit_ip) { - /* even if they've set their own dirservers, require an explicit IP if + /* even if they've set their own authorities, require an explicit IP if * they're using an internal address. */ log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private " "IP address '%s'. Please set the Address config option to be " @@ -2975,37 +2054,65 @@ resolve_my_address(int warn_severity, const or_options_t *options, } } - log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr32(addr)); + /* + * Step four: We have a winner! 'addr' is our answer for sure, and + * 'addr_string' is its string form. Fill out the various fields to + * say how we decided it. + */ + + log_debug(LD_CONFIG, "Resolved Address to '%s'.", addr_string); + + if (explicit_ip) { + method_used = "CONFIGURED"; + hostname_used = NULL; + } else if (explicit_hostname) { + method_used = "RESOLVED"; + hostname_used = hostname; + } else if (from_interface) { + method_used = "INTERFACE"; + hostname_used = NULL; + } else { + method_used = "GETHOSTNAME"; + hostname_used = hostname; + } + *addr_out = addr; + if (method_out) + *method_out = method_used; + if (hostname_out) + *hostname_out = hostname_used ? tor_strdup(hostname_used) : NULL; + + /* + * Step five: Check if the answer has changed since last time (or if + * there was no last time), and if so call various functions to keep + * us up-to-date. + */ + if (last_resolved_addr && last_resolved_addr != *addr_out) { /* Leave this as a notice, regardless of the requested severity, * at least until dynamic IP address support becomes bulletproof. */ log_notice(LD_NET, - "Your IP address seems to have changed to %s. Updating.", - addr_string); + "Your IP address seems to have changed to %s " + "(METHOD=%s%s%s). Updating.", + addr_string, method_used, + hostname_used ? " HOSTNAME=" : "", + hostname_used ? hostname_used : ""); ip_address_changed(0); } + if (last_resolved_addr != *addr_out) { - const char *method; - const char *h = hostname; - if (explicit_ip) { - method = "CONFIGURED"; - h = NULL; - } else if (explicit_hostname) { - method = "RESOLVED"; - } else if (from_interface) { - method = "INTERFACE"; - h = NULL; - } else { - method = "GETHOSTNAME"; - } control_event_server_status(LOG_NOTICE, - "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s", - addr_string, method, h?"HOSTNAME=":"", h); + "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s", + addr_string, method_used, + hostname_used ? " HOSTNAME=" : "", + hostname_used ? hostname_used : ""); } last_resolved_addr = *addr_out; - if (hostname_out) - *hostname_out = tor_strdup(hostname); + + /* + * And finally, clean up and return success. + */ + tor_free(addr_string); return 0; } @@ -3039,112 +2146,11 @@ is_local_addr(const tor_addr_t *addr) return 0; } -/** Release storage held by <b>options</b>. */ -static void -config_free(const config_format_t *fmt, void *options) -{ - int i; - - if (!options) - return; - - tor_assert(fmt); - - for (i=0; fmt->vars[i].name; ++i) - option_clear(fmt, options, &(fmt->vars[i])); - if (fmt->extra) { - config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset); - config_free_lines(*linep); - *linep = NULL; - } - tor_free(options); -} - -/** Return true iff a and b contain identical keys and values in identical - * order. */ -static int -config_lines_eq(config_line_t *a, config_line_t *b) -{ - while (a && b) { - if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value)) - return 0; - a = a->next; - b = b->next; - } - if (a || b) - return 0; - return 1; -} - -/** Return the number of lines in <b>a</b> whose key is <b>key</b>. */ -static int -config_count_key(const config_line_t *a, const char *key) -{ - int n = 0; - while (a) { - if (!strcasecmp(a->key, key)) { - ++n; - } - a = a->next; - } - return n; -} - -/** Return true iff the option <b>name</b> has the same value in <b>o1</b> - * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options. - */ -static int -option_is_same(const config_format_t *fmt, - const or_options_t *o1, const or_options_t *o2, - const char *name) -{ - config_line_t *c1, *c2; - int r = 1; - CHECK(fmt, o1); - CHECK(fmt, o2); - - c1 = get_assigned_option(fmt, o1, name, 0); - c2 = get_assigned_option(fmt, o2, name, 0); - r = config_lines_eq(c1, c2); - config_free_lines(c1); - config_free_lines(c2); - return r; -} - -/** Copy storage held by <b>old</b> into a new or_options_t and return it. */ -static or_options_t * -options_dup(const config_format_t *fmt, const or_options_t *old) -{ - or_options_t *newopts; - int i; - config_line_t *line; - - newopts = config_alloc(fmt); - for (i=0; fmt->vars[i].name; ++i) { - if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S) - continue; - if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE) - continue; - line = get_assigned_option(fmt, old, fmt->vars[i].name, 0); - if (line) { - char *msg = NULL; - if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) { - log_err(LD_BUG, "Config_get_assigned_option() generated " - "something we couldn't config_assign(): %s", msg); - tor_free(msg); - tor_assert(0); - } - } - config_free_lines(line); - } - return newopts; -} - /** Return a new empty or_options_t. Used for testing. */ or_options_t * options_new(void) { - return config_alloc(&options_format); + return config_new(&options_format); } /** Set <b>options</b> to hold reasonable defaults for most options. @@ -3155,94 +2161,6 @@ options_init(or_options_t *options) config_init(&options_format, options); } -/** Set all vars in the configuration object <b>options</b> to their default - * values. */ -static void -config_init(const config_format_t *fmt, void *options) -{ - int i; - const config_var_t *var; - CHECK(fmt, options); - - for (i=0; fmt->vars[i].name; ++i) { - var = &fmt->vars[i]; - if (!var->initvalue) - continue; /* defaults to NULL or 0 */ - option_reset(fmt, options, var, 1); - } -} - -/** Allocate and return a new string holding the written-out values of the vars - * in 'options'. If 'minimal', do not write out any default-valued vars. - * Else, if comment_defaults, write default values as comments. - */ -static char * -config_dump(const config_format_t *fmt, const void *default_options, - const void *options, int minimal, - int comment_defaults) -{ - smartlist_t *elements; - const or_options_t *defaults = default_options; - void *defaults_tmp = NULL; - config_line_t *line, *assigned; - char *result; - int i; - char *msg = NULL; - - if (defaults == NULL) { - defaults = defaults_tmp = config_alloc(fmt); - config_init(fmt, defaults_tmp); - } - - /* XXX use a 1 here so we don't add a new log line while dumping */ - if (default_options == NULL) { - if (fmt->validate_fn(NULL, defaults_tmp, 1, &msg) < 0) { - log_err(LD_BUG, "Failed to validate default config."); - tor_free(msg); - tor_assert(0); - } - } - - elements = smartlist_new(); - for (i=0; fmt->vars[i].name; ++i) { - int comment_option = 0; - if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE || - fmt->vars[i].type == CONFIG_TYPE_LINELIST_S) - continue; - /* Don't save 'hidden' control variables. */ - if (!strcmpstart(fmt->vars[i].name, "__")) - continue; - if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name)) - continue; - else if (comment_defaults && - option_is_same(fmt, options, defaults, fmt->vars[i].name)) - comment_option = 1; - - line = assigned = get_assigned_option(fmt, options, fmt->vars[i].name, 1); - - for (; line; line = line->next) { - smartlist_add_asprintf(elements, "%s%s %s\n", - comment_option ? "# " : "", - line->key, line->value); - } - config_free_lines(assigned); - } - - if (fmt->extra) { - line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset); - for (; line; line = line->next) { - smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value); - } - } - - result = smartlist_join_strings(elements, "", 0, NULL); - SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); - smartlist_free(elements); - if (defaults_tmp) - config_free(fmt, defaults_tmp); - return result; -} - /** Return a string containing a possible configuration file that would give * the configuration in <b>options</b>. If <b>minimal</b> is true, do not * include options that are the same as Tor's defaults. @@ -3299,16 +2217,16 @@ ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) } /** Parse an authority type from <b>options</b>-\>PublishServerDescriptor - * and write it to <b>options</b>-\>_PublishServerDescriptor. Treat "1" + * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1" * as "v2,v3" unless BridgeRelay is 1, in which case treat it as "bridge". * Treat "0" as "". * Return 0 on success or -1 if not a recognized authority type (in which - * case the value of _PublishServerDescriptor is undefined). */ + * case the value of PublishServerDescriptor_ is undefined). */ static int compute_publishserverdescriptor(or_options_t *options) { smartlist_t *list = options->PublishServerDescriptor; - dirinfo_type_t *auth = &options->_PublishServerDescriptor; + dirinfo_type_t *auth = &options->PublishServerDescriptor_; *auth = NO_DIRINFO; if (!list) /* empty list, answer is none */ return 0; @@ -3349,6 +2267,10 @@ compute_publishserverdescriptor(or_options_t *options) * will generate too many circuits and potentially overload the network. */ #define MIN_MAX_CIRCUIT_DIRTINESS 10 +/** Highest allowable value for MaxCircuitDirtiness: prevents time_t + * overflows. */ +#define MAX_MAX_CIRCUIT_DIRTINESS (30*24*60*60) + /** 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 @@ -3386,7 +2308,7 @@ options_validate(or_options_t *old_options, or_options_t *options, int n_ports=0; #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END -#define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END +#define COMPLAIN(arg) STMT_BEGIN log_warn(LD_CONFIG, arg); STMT_END tor_assert(msg); *msg = NULL; @@ -3395,15 +2317,18 @@ options_validate(or_options_t *old_options, or_options_t *options, (!strcmpstart(uname, "Windows 95") || !strcmpstart(uname, "Windows 98") || !strcmpstart(uname, "Windows Me"))) { - log(LOG_WARN, LD_CONFIG, "Tor is running as a server, but you are " + log_warn(LD_CONFIG, "Tor is running as a server, but you are " "running %s; this probably won't work. See " - "https://wiki.torproject.org/TheOnionRouter/TorFAQ#ServerOS " + "https://www.torproject.org/docs/faq.html#BestOSForRelay " "for details.", uname); } if (parse_ports(options, 1, msg, &n_ports) < 0) return -1; + if (parse_outbound_addresses(options, 1, msg) < 0) + return -1; + if (validate_data_directory(options)<0) REJECT("Invalid DataDirectory"); @@ -3421,7 +2346,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (server_mode(options) && !options->ContactInfo) - log(LOG_NOTICE, LD_CONFIG, "Your ContactInfo config option is not set. " + log_notice(LD_CONFIG, "Your ContactInfo config option is not set. " "Please consider setting it, so we can contact you if your server is " "misconfigured or something else goes wrong."); @@ -3433,13 +2358,13 @@ options_validate(or_options_t *old_options, or_options_t *options, config_line_append(&options->Logs, "Log", "warn stdout"); } - if (options_init_logs(options, 1)<0) /* Validate the log(s) */ + if (options_init_logs(options, 1)<0) /* Validate the tor_log(s) */ REJECT("Failed to validate Log options. See logs for details."); if (authdir_mode(options)) { /* confirm that our address isn't broken, so we can complain now */ uint32_t tmp; - if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0) + if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0) REJECT("Failed to resolve/guess local address. See logs for details."); } @@ -3451,7 +2376,7 @@ options_validate(or_options_t *old_options, or_options_t *options, /* XXXX require that the only port not be DirPort? */ /* XXXX require that at least one port be listened-upon. */ if (n_ports == 0 && !options->RendConfigLines) - log(LOG_WARN, LD_CONFIG, + log_warn(LD_CONFIG, "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."); @@ -3467,10 +2392,14 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive."); } + if (options->DisableV2DirectoryInfo_ && ! authdir_mode(options)) { + REJECT("DisableV2DirectoryInfo_ set, but we aren't an authority."); + } + if (options->ExcludeExitNodes || options->ExcludeNodes) { - options->_ExcludeExitNodesUnion = routerset_new(); - routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeExitNodes); - routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes); + options->ExcludeExitNodesUnion_ = routerset_new(); + routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes); + routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeNodes); } if (options->NodeFamilies) { @@ -3485,6 +2414,12 @@ options_validate(or_options_t *old_options, or_options_t *options, } } + if (options->TLSECGroup && (strcasecmp(options->TLSECGroup, "P256") && + strcasecmp(options->TLSECGroup, "P224"))) { + COMPLAIN("Unrecognized TLSECGroup: Falling back to the default."); + tor_free(options->TLSECGroup); + } + 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 " @@ -3552,6 +2487,18 @@ options_validate(or_options_t *old_options, or_options_t *options, return -1; } + if (options->PathsNeededToBuildCircuits >= 0.0) { + if (options->PathsNeededToBuildCircuits < 0.25) { + log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too low. Increasing " + "to 0.25"); + options->PathsNeededToBuildCircuits = 0.25; + } else if (options->PathsNeededToBuildCircuits > 0.95) { + log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too high. Decreasing " + "to 0.95"); + options->PathsNeededToBuildCircuits = 0.95; + } + } + if (options->MaxClientCircuitsPending <= 0 || options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) { tor_asprintf(msg, @@ -3593,7 +2540,7 @@ options_validate(or_options_t *old_options, or_options_t *options, }); new_line->value = smartlist_join_strings(instead,",",0,NULL); /* These have been deprecated since 0.1.1.5-alpha-cvs */ - log(LOG_NOTICE, LD_CONFIG, + log_notice(LD_CONFIG, "Converting FascistFirewall and FirewallPorts " "config options to new format: \"ReachableAddresses %s\"", new_line->value); @@ -3608,7 +2555,7 @@ options_validate(or_options_t *old_options, or_options_t *options, new_line->key = tor_strdup("ReachableDirAddresses"); new_line->value = tor_strdup("*:80"); options->ReachableDirAddresses = new_line; - log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option " + log_notice(LD_CONFIG, "Converting FascistFirewall config option " "to new format: \"ReachableDirAddresses *:80\""); } if (!options->ReachableORAddresses) { @@ -3616,7 +2563,7 @@ options_validate(or_options_t *old_options, or_options_t *options, new_line->key = tor_strdup("ReachableORAddresses"); new_line->value = tor_strdup("*:443"); options->ReachableORAddresses = new_line; - log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option " + log_notice(LD_CONFIG, "Converting FascistFirewall config option " "to new format: \"ReachableORAddresses *:443\""); } } @@ -3665,29 +2612,30 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->UseBridges && options->EntryNodes) REJECT("You cannot set both UseBridges and EntryNodes."); - if (options->EntryNodes && !options->UseEntryGuards) - log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. " - "EntryNodes will be ignored."); + if (options->EntryNodes && !options->UseEntryGuards) { + REJECT("If EntryNodes is set, UseEntryGuards must be enabled."); + } - if (options->MaxMemInCellQueues < (500 << 20)) { - log_warn(LD_CONFIG, "MaxMemInCellQueues must be at least 500 MB for now. " + if (options->MaxMemInCellQueues < (256 << 20)) { + log_warn(LD_CONFIG, "MaxMemInCellQueues must be at least 256 MB for now. " "Ideally, have it as large as you can afford."); - options->MaxMemInCellQueues = (500 << 20); + options->MaxMemInCellQueues = (256 << 20); } - options->_AllowInvalid = 0; + options->AllowInvalid_ = 0; + if (options->AllowInvalidNodes) { SMARTLIST_FOREACH_BEGIN(options->AllowInvalidNodes, const char *, cp) { if (!strcasecmp(cp, "entry")) - options->_AllowInvalid |= ALLOW_INVALID_ENTRY; + options->AllowInvalid_ |= ALLOW_INVALID_ENTRY; else if (!strcasecmp(cp, "exit")) - options->_AllowInvalid |= ALLOW_INVALID_EXIT; + options->AllowInvalid_ |= ALLOW_INVALID_EXIT; else if (!strcasecmp(cp, "middle")) - options->_AllowInvalid |= ALLOW_INVALID_MIDDLE; + options->AllowInvalid_ |= ALLOW_INVALID_MIDDLE; else if (!strcasecmp(cp, "introduction")) - options->_AllowInvalid |= ALLOW_INVALID_INTRODUCTION; + options->AllowInvalid_ |= ALLOW_INVALID_INTRODUCTION; else if (!strcasecmp(cp, "rendezvous")) - options->_AllowInvalid |= ALLOW_INVALID_RENDEZVOUS; + options->AllowInvalid_ |= ALLOW_INVALID_RENDEZVOUS; else { tor_asprintf(msg, "Unrecognized value '%s' in AllowInvalidNodes", cp); @@ -3698,11 +2646,11 @@ options_validate(or_options_t *old_options, or_options_t *options, if (!options->SafeLogging || !strcasecmp(options->SafeLogging, "0")) { - options->_SafeLogging = SAFELOG_SCRUB_NONE; + options->SafeLogging_ = SAFELOG_SCRUB_NONE; } else if (!strcasecmp(options->SafeLogging, "relay")) { - options->_SafeLogging = SAFELOG_SCRUB_RELAY; + options->SafeLogging_ = SAFELOG_SCRUB_RELAY; } else if (!strcasecmp(options->SafeLogging, "1")) { - options->_SafeLogging = SAFELOG_SCRUB_ALL; + options->SafeLogging_ = SAFELOG_SCRUB_ALL; } else { tor_asprintf(msg, "Unrecognized value '%s' in SafeLogging", @@ -3716,8 +2664,8 @@ options_validate(or_options_t *old_options, or_options_t *options, } if ((options->BridgeRelay - || options->_PublishServerDescriptor & BRIDGE_DIRINFO) - && (options->_PublishServerDescriptor + || options->PublishServerDescriptor_ & BRIDGE_DIRINFO) + && (options->PublishServerDescriptor_ & (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) { REJECT("Bridges are not supposed to publish router descriptors to the " "directory authorities. Please correct your " @@ -3768,15 +2716,73 @@ options_validate(or_options_t *old_options, or_options_t *options, options->LearnCircuitBuildTimeout = 0; } - if (!(options->LearnCircuitBuildTimeout) && - options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) { + if (options->Tor2webMode && options->UseEntryGuards) { + /* tor2web mode clients do not (and should not) use entry guards + * in any meaningful way. Further, tor2web mode causes the hidden + * service client code to do things which break the path bias + * detector, and it's far easier to turn off entry guards (and + * thus the path bias detector with it) than to figure out how to + * make a piece of code which cannot possibly help tor2web mode + * users compatible with tor2web mode. + */ + log_notice(LD_CONFIG, + "Tor2WebMode is enabled; disabling UseEntryGuards."); + options->UseEntryGuards = 0; + } + + if (!(options->UseEntryGuards) && + (options->RendConfigLines != NULL)) { log_warn(LD_CONFIG, - "CircuitBuildTimeout is shorter (%d seconds) than recommended " - "(%d seconds), and LearnCircuitBuildTimeout is disabled. " + "UseEntryGuards is disabled, but you have configured one or more " + "hidden services on this Tor instance. Your hidden services " + "will be very easy to locate using a well-known attack -- see " + "http://freehaven.net/anonbib/#hs-attack06 for details."); + } + + if (!options->LearnCircuitBuildTimeout && options->CircuitBuildTimeout && + options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) { + log_warn(LD_CONFIG, + "CircuitBuildTimeout is shorter (%d seconds) than the recommended " + "minimum (%d seconds), and LearnCircuitBuildTimeout is disabled. " "If tor isn't working, raise this value or enable " "LearnCircuitBuildTimeout.", options->CircuitBuildTimeout, RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT ); + } else if (!options->LearnCircuitBuildTimeout && + !options->CircuitBuildTimeout) { + log_notice(LD_CONFIG, "You disabled LearnCircuitBuildTimeout, but didn't " + "a CircuitBuildTimeout. I'll pick a plausible default."); + } + + if (options->PathBiasNoticeRate > 1.0) { + tor_asprintf(msg, + "PathBiasNoticeRate is too high. " + "It must be between 0 and 1.0"); + return -1; + } + if (options->PathBiasWarnRate > 1.0) { + tor_asprintf(msg, + "PathBiasWarnRate is too high. " + "It must be between 0 and 1.0"); + return -1; + } + if (options->PathBiasExtremeRate > 1.0) { + tor_asprintf(msg, + "PathBiasExtremeRate is too high. " + "It must be between 0 and 1.0"); + return -1; + } + if (options->PathBiasNoticeUseRate > 1.0) { + tor_asprintf(msg, + "PathBiasNoticeUseRate is too high. " + "It must be between 0 and 1.0"); + return -1; + } + if (options->PathBiasExtremeUseRate > 1.0) { + tor_asprintf(msg, + "PathBiasExtremeUseRate is too high. " + "It must be between 0 and 1.0"); + return -1; } if (options->MaxCircuitDirtiness < MIN_MAX_CIRCUIT_DIRTINESS) { @@ -3785,6 +2791,12 @@ options_validate(or_options_t *old_options, or_options_t *options, options->MaxCircuitDirtiness = MIN_MAX_CIRCUIT_DIRTINESS; } + if (options->MaxCircuitDirtiness > MAX_MAX_CIRCUIT_DIRTINESS) { + log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too high; " + "setting to %d days.", MAX_MAX_CIRCUIT_DIRTINESS/86400); + options->MaxCircuitDirtiness = MAX_MAX_CIRCUIT_DIRTINESS; + } + if (options->CircuitStreamTimeout && options->CircuitStreamTimeout < MIN_CIRCUIT_STREAM_TIMEOUT) { log_warn(LD_CONFIG, "CircuitStreamTimeout option is too short; " @@ -4042,8 +3054,9 @@ options_validate(or_options_t *old_options, or_options_t *options, if (validate_addr_policies(options, msg) < 0) return -1; - if (validate_dir_authorities(options, old_options) < 0) - REJECT("Directory authority line did not parse. See logs for details."); + if (validate_dir_servers(options, old_options) < 0) + REJECT("Directory authority/fallback line did not parse. See logs " + "for details."); if (options->UseBridges && !options->Bridges) REJECT("If you set UseBridges, you must specify at least one bridge."); @@ -4073,7 +3086,23 @@ options_validate(or_options_t *old_options, or_options_t *options, log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified" " a ServerTransportPlugin line (%s). The ServerTransportPlugin " "line will be ignored.", - esc_for_log(options->ServerTransportPlugin->value)); + escaped(options->ServerTransportPlugin->value)); + } + + for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) { + /** If get_bindaddr_from_transport_listen_line() fails with + 'transport' being NULL, it means that something went wrong + while parsing the ServerTransportListenAddr line. */ + char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL); + if (!bindaddr) + REJECT("ServerTransportListenAddr did not parse. See logs for details."); + tor_free(bindaddr); + } + + if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) { + log_notice(LD_GENERAL, "You need at least a single managed-proxy to " + "specify a transport listen address. The " + "ServerTransportListenAddr line will be ignored."); } if (options->ConstrainedSockets) { @@ -4127,7 +3156,11 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("Failed to configure client authorization for hidden services. " "See logs for details."); - if (parse_virtual_addr_network(options->VirtualAddrNetwork, 1, NULL)<0) + if (parse_virtual_addr_network(options->VirtualAddrNetworkIPv4, + AF_INET, 1, msg)<0) + return -1; + if (parse_virtual_addr_network(options->VirtualAddrNetworkIPv6, + AF_INET6, 1, msg)<0) return -1; if (options->PreferTunneledDirConns && !options->TunnelDirConns) @@ -4149,15 +3182,15 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->TestingTorNetwork && - !(options->DirServers || + !(options->DirAuthorities || (options->AlternateDirAuthority && options->AlternateBridgeAuthority))) { REJECT("TestingTorNetwork may only be configured in combination with " - "a non-default set of DirServer or both of AlternateDirAuthority " - "and AlternateBridgeAuthority configured."); + "a non-default set of DirAuthority or both of " + "AlternateDirAuthority and AlternateBridgeAuthority configured."); } - if (options->AllowSingleHopExits && !options->DirServers) { + if (options->AllowSingleHopExits && !options->DirAuthorities) { 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 " @@ -4169,7 +3202,7 @@ options_validate(or_options_t *old_options, or_options_t *options, /* Keep changes to hard-coded values synchronous to man page and default * values table. */ if (options->TestingV3AuthInitialVotingInterval != 30*60 && - !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) { + !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { REJECT("TestingV3AuthInitialVotingInterval may only be changed in testing " "Tor networks!"); } else if (options->TestingV3AuthInitialVotingInterval < MIN_VOTE_INTERVAL) { @@ -4180,7 +3213,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->TestingV3AuthInitialVoteDelay != 5*60 && - !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) { + !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { REJECT("TestingV3AuthInitialVoteDelay may only be changed in testing " "Tor networks!"); @@ -4189,7 +3222,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->TestingV3AuthInitialDistDelay != 5*60 && - !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) { + !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { REJECT("TestingV3AuthInitialDistDelay may only be changed in testing " "Tor networks!"); } else if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS) { @@ -4204,7 +3237,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->TestingAuthDirTimeToLearnReachability != 30*60 && - !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) { + !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { REJECT("TestingAuthDirTimeToLearnReachability may only be changed in " "testing Tor networks!"); } else if (options->TestingAuthDirTimeToLearnReachability < 0) { @@ -4214,7 +3247,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->TestingEstimatedDescriptorPropagationTime != 10*60 && - !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) { + !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { REJECT("TestingEstimatedDescriptorPropagationTime may only be changed in " "testing Tor networks!"); } else if (options->TestingEstimatedDescriptorPropagationTime < 0) { @@ -4350,7 +3383,7 @@ options_transition_affects_workers(const or_options_t *old_options, !config_lines_eq(old_options->ORPort_lines, new_options->ORPort_lines) || old_options->ServerDNSSearchDomains != new_options->ServerDNSSearchDomains || - old_options->_SafeLogging != new_options->_SafeLogging || + old_options->SafeLogging_ != new_options->SafeLogging_ || old_options->ClientOnly != new_options->ClientOnly || public_server_mode(old_options) != public_server_mode(new_options) || !config_lines_eq(old_options->Logs, new_options->Logs) || @@ -4377,14 +3410,15 @@ options_transition_affects_descriptor(const or_options_t *old_options, !config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) || old_options->ExitPolicyRejectPrivate != new_options->ExitPolicyRejectPrivate || + old_options->IPv6Exit != new_options->IPv6Exit || !config_lines_eq(old_options->ORPort_lines, new_options->ORPort_lines) || !config_lines_eq(old_options->DirPort_lines, new_options->DirPort_lines) || old_options->ClientOnly != new_options->ClientOnly || old_options->DisableNetwork != new_options->DisableNetwork || - old_options->_PublishServerDescriptor != - new_options->_PublishServerDescriptor || + old_options->PublishServerDescriptor_ != + new_options->PublishServerDescriptor_ || get_effective_bwrate(old_options) != get_effective_bwrate(new_options) || get_effective_bwburst(old_options) != get_effective_bwburst(new_options) || @@ -4535,7 +3569,7 @@ find_torrc_filename(int argc, char **argv, for (i = 1; i < argc; ++i) { if (i < argc-1 && !strcmp(argv[i],fname_opt)) { if (fname) { - log(LOG_WARN, LD_CONFIG, "Duplicate %s options on command line.", + log_warn(LD_CONFIG, "Duplicate %s options on command line.", fname_opt); tor_free(fname); } @@ -4598,7 +3632,7 @@ load_torrc_from_disk(int argc, char **argv, int defaults_file) fname = find_torrc_filename(argc, argv, defaults_file, &using_default_torrc, &ignore_missing_torrc); tor_assert(fname); - log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname); + log_debug(LD_CONFIG, "Opening config file \"%s\"", fname); tor_free(*fname_var); *fname_var = fname; @@ -4608,18 +3642,18 @@ load_torrc_from_disk(int argc, char **argv, int defaults_file) !(cf = read_file_to_str(fname,0,NULL))) { if (using_default_torrc == 1 || ignore_missing_torrc) { if (!defaults_file) - log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, " + log_notice(LD_CONFIG, "Configuration file \"%s\" not present, " "using reasonable defaults.", fname); tor_free(fname); /* sets fname to NULL */ *fname_var = NULL; cf = tor_strdup(""); } else { - log(LOG_WARN, LD_CONFIG, + log_warn(LD_CONFIG, "Unable to open configuration file \"%s\".", fname); goto err; } } else { - log(LOG_NOTICE, LD_CONFIG, "Read configuration file \"%s\".", fname); + log_notice(LD_CONFIG, "Read configuration file \"%s\".", fname); } return cf; @@ -4695,6 +3729,7 @@ options_init_from_torrc(int argc, char **argv) } if (command == CMD_HASH_PASSWORD) { + cf_defaults = tor_strdup(""); cf = tor_strdup(""); } else { cf_defaults = load_torrc_from_disk(argc, argv, 1); @@ -4711,7 +3746,7 @@ options_init_from_torrc(int argc, char **argv) tor_free(cf); tor_free(cf_defaults); if (errmsg) { - log(LOG_WARN,LD_CONFIG,"%s", errmsg); + log_warn(LD_CONFIG,"%s", errmsg); tor_free(errmsg); } return retval < 0 ? -1 : 0; @@ -4741,7 +3776,7 @@ options_init_from_string(const char *cf_defaults, const char *cf, this is the first time we run*/ newoptions = tor_malloc_zero(sizeof(or_options_t)); - newoptions->_magic = OR_OPTIONS_MAGIC; + newoptions->magic_ = OR_OPTIONS_MAGIC; options_init(newoptions); newoptions->command = command; newoptions->command_arg = command_arg; @@ -4763,7 +3798,11 @@ options_init_from_string(const char *cf_defaults, const char *cf, goto err; } if (i==0) - newdefaultoptions = options_dup(&options_format, newoptions); + newdefaultoptions = config_dup(&options_format, newoptions); + } + + if (newdefaultoptions == NULL) { + newdefaultoptions = config_dup(&options_format, global_default_options); } /* Go through command-line variables too */ @@ -4801,7 +3840,7 @@ options_init_from_string(const char *cf_defaults, const char *cf, config_free(&options_format, newdefaultoptions); newdefaultoptions = NULL; newoptions = tor_malloc_zero(sizeof(or_options_t)); - newoptions->_magic = OR_OPTIONS_MAGIC; + newoptions->magic_ = OR_OPTIONS_MAGIC; options_init(newoptions); newoptions->command = command; newoptions->command_arg = command_arg; @@ -4824,7 +3863,7 @@ options_init_from_string(const char *cf_defaults, const char *cf, goto err; } if (i==0) - newdefaultoptions = options_dup(&options_format, newoptions); + newdefaultoptions = config_dup(&options_format, newoptions); } /* Assign command-line variables a second time too */ retval = config_assign(&options_format, newoptions, @@ -5158,8 +4197,8 @@ parse_bridge_line(const char *line, int validate_only) } if (!validate_only) { - log_debug(LD_DIR, "Bridge at %s:%d (transport: %s) (%s)", - fmt_addr(&addr), (int)port, + log_debug(LD_DIR, "Bridge at %s (transport: %s) (%s)", + fmt_addrport(&addr, port), transport_name ? transport_name : "no transport", fingerprint ? fingerprint : "no key listed"); bridge_add_from_config(&addr, port, @@ -5292,8 +4331,8 @@ parse_client_transport_line(const char *line, int validate_only) transport_add_from_config(&addr, port, smartlist_get(transport_list, 0), socks_ver); - log_info(LD_DIR, "Transport '%s' found at %s:%d", - transports, fmt_addr(&addr), (int)port); + log_info(LD_DIR, "Transport '%s' found at %s", + transports, fmt_addrport(&addr, port)); } } @@ -5314,6 +4353,80 @@ parse_client_transport_line(const char *line, int validate_only) return r; } +/** Given a ServerTransportListenAddr <b>line</b>, return its + * <address:port> string. Return NULL if the line was not + * well-formed. + * + * If <b>transport</b> is set, return NULL if the line is not + * referring to <b>transport</b>. + * + * The returned string is allocated on the heap and it's the + * responsibility of the caller to free it. */ +static char * +get_bindaddr_from_transport_listen_line(const char *line,const char *transport) +{ + smartlist_t *items = NULL; + const char *parsed_transport = NULL; + char *addrport = NULL; + tor_addr_t addr; + uint16_t port = 0; + + items = smartlist_new(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(items) < 2) { + log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line."); + goto err; + } + + parsed_transport = smartlist_get(items, 0); + addrport = tor_strdup(smartlist_get(items, 1)); + + /* If 'transport' is given, check if it matches the one on the line */ + if (transport && strcmp(transport, parsed_transport)) + goto err; + + /* Validate addrport */ + if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port)<0) { + log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr " + "address '%s'", addrport); + goto err; + } + + goto done; + + err: + tor_free(addrport); + addrport = NULL; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + + return addrport; +} + +/** Given the name of a pluggable transport in <b>transport</b>, check + * the configuration file to see if the user has explicitly asked for + * it to listen on a specific port. Return a <address:port> string if + * so, otherwise NULL. */ +char * +get_transport_bindaddr_from_config(const char *transport) +{ + config_line_t *cl; + const or_options_t *options = get_options(); + + for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) { + char *bindaddr = + get_bindaddr_from_transport_listen_line(cl->value, transport); + if (bindaddr) + return bindaddr; + } + + return NULL; +} + /** Read the contents of a ServerTransportPlugin line from * <b>line</b>. Return 0 if the line is well-formed, and -1 if it * isn't. @@ -5412,8 +4525,8 @@ parse_server_transport_line(const char *line, int validate_only) } if (!validate_only) { - log_info(LD_DIR, "Server transport '%s' at %s:%d.", - transports, fmt_addr(&addr), (int)port); + log_info(LD_DIR, "Server transport '%s' at %s.", + transports, fmt_addrport(&addr, port)); } } @@ -5434,15 +4547,15 @@ parse_server_transport_line(const char *line, int validate_only) return r; } -/** Read the contents of a DirServer line from <b>line</b>. If +/** Read the contents of a DirAuthority line from <b>line</b>. If * <b>validate_only</b> is 0, and the line is well-formed, and it * shares any bits with <b>required_type</b> or <b>required_type</b> * is 0, then add the dirserver described in the line (minus whatever * bits it's missing) as a valid authority. Return 0 on success, * or -1 if the line isn't well-formed or if we can't add it. */ static int -parse_dir_server_line(const char *line, dirinfo_type_t required_type, - int validate_only) +parse_dir_authority_line(const char *line, dirinfo_type_t required_type, + int validate_only) { smartlist_t *items = NULL; int r; @@ -5452,12 +4565,13 @@ parse_dir_server_line(const char *line, dirinfo_type_t required_type, char v3_digest[DIGEST_LEN]; dirinfo_type_t type = V2_DIRINFO; int is_not_hidserv_authority = 0, is_not_v2_authority = 0; + double weight = 1.0; items = smartlist_new(); smartlist_split_string(items, line, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); if (smartlist_len(items) < 1) { - log_warn(LD_CONFIG, "No arguments on DirServer line."); + log_warn(LD_CONFIG, "No arguments on DirAuthority line."); goto err; } @@ -5485,19 +4599,27 @@ parse_dir_server_line(const char *line, dirinfo_type_t required_type, char *portstring = flag + strlen("orport="); or_port = (uint16_t) tor_parse_long(portstring, 10, 1, 65535, &ok, NULL); if (!ok) - log_warn(LD_CONFIG, "Invalid orport '%s' on DirServer line.", + log_warn(LD_CONFIG, "Invalid orport '%s' on DirAuthority line.", portstring); + } else if (!strcmpstart(flag, "weight=")) { + int ok; + const char *wstring = flag + strlen("weight="); + weight = tor_parse_double(wstring, 0, UINT64_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_CONFIG, "Invalid weight '%s' on DirAuthority line.",flag); + weight=1.0; + } } else if (!strcasecmpstart(flag, "v3ident=")) { char *idstr = flag + strlen("v3ident="); if (strlen(idstr) != HEX_DIGEST_LEN || base16_decode(v3_digest, DIGEST_LEN, idstr, HEX_DIGEST_LEN)<0) { - log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line", + log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirAuthority line", flag); } else { type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO; } } else { - log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line", + log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirAuthority line", flag); } tor_free(flag); @@ -5509,24 +4631,24 @@ parse_dir_server_line(const char *line, dirinfo_type_t required_type, type &= ~V2_DIRINFO; if (smartlist_len(items) < 2) { - log_warn(LD_CONFIG, "Too few arguments to DirServer line."); + log_warn(LD_CONFIG, "Too few arguments to DirAuthority line."); goto err; } addrport = smartlist_get(items, 0); smartlist_del_keeporder(items, 0); if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) { - log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport); + log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'", addrport); goto err; } if (!dir_port) { - log_warn(LD_CONFIG, "Missing port in DirServer address '%s'",addrport); + log_warn(LD_CONFIG, "Missing port in DirAuthority address '%s'",addrport); goto err; } fingerprint = smartlist_join_strings(items, "", 0, NULL); if (strlen(fingerprint) != HEX_DIGEST_LEN) { - log_warn(LD_CONFIG, "Key digest for DirServer is wrong length %d.", - (int)strlen(fingerprint)); + log_warn(LD_CONFIG, "Key digest '%s' for DirAuthority is wrong length %d.", + fingerprint, (int)strlen(fingerprint)); goto err; } if (!strcmp(fingerprint, "E623F7625FBE0C87820F11EC5F6D5377ED816294")) { @@ -5538,19 +4660,21 @@ parse_dir_server_line(const char *line, dirinfo_type_t required_type, goto err; } if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) { - log_warn(LD_CONFIG, "Unable to decode DirServer key digest."); + log_warn(LD_CONFIG, "Unable to decode DirAuthority key digest."); goto err; } if (!validate_only && (!required_type || required_type & type)) { + dir_server_t *ds; if (required_type) type &= required_type; /* pare down what we think of them as an * authority for. */ log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type, address, (int)dir_port, (char*)smartlist_get(items,0)); - if (!add_trusted_dir_server(nickname, address, dir_port, or_port, - digest, v3_digest, type)) + if (!(ds = trusted_dir_server_new(nickname, address, dir_port, or_port, + digest, v3_digest, type, weight))) goto err; + dir_server_add(ds); } r = 0; @@ -5569,6 +4693,110 @@ parse_dir_server_line(const char *line, dirinfo_type_t required_type, return r; } +/** Read the contents of a FallbackDir line from <b>line</b>. If + * <b>validate_only</b> is 0, and the line is well-formed, then add the + * dirserver described in the line as a fallback directory. Return 0 on + * success, or -1 if the line isn't well-formed or if we can't add it. */ +static int +parse_dir_fallback_line(const char *line, + int validate_only) +{ + int r = -1; + smartlist_t *items = smartlist_new(), *positional = smartlist_new(); + int orport = -1; + uint16_t dirport; + tor_addr_t addr; + int ok; + char id[DIGEST_LEN]; + char *address=NULL; + double weight=1.0; + + memset(id, 0, sizeof(id)); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + SMARTLIST_FOREACH_BEGIN(items, const char *, cp) { + const char *eq = strchr(cp, '='); + ok = 1; + if (! eq) { + smartlist_add(positional, (char*)cp); + continue; + } + if (!strcmpstart(cp, "orport=")) { + orport = (int)tor_parse_long(cp+strlen("orport="), 10, + 1, 65535, &ok, NULL); + } else if (!strcmpstart(cp, "id=")) { + ok = !base16_decode(id, DIGEST_LEN, + cp+strlen("id="), strlen(cp)-strlen("id=")); + } else if (!strcmpstart(cp, "weight=")) { + int ok; + const char *wstring = cp + strlen("weight="); + weight = tor_parse_double(wstring, 0, UINT64_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_CONFIG, "Invalid weight '%s' on FallbackDir line.", cp); + weight=1.0; + } + } + + if (!ok) { + log_warn(LD_CONFIG, "Bad FallbackDir option %s", escaped(cp)); + goto end; + } + } SMARTLIST_FOREACH_END(cp); + + if (smartlist_len(positional) != 1) { + log_warn(LD_CONFIG, "Couldn't parse FallbackDir line %s", escaped(line)); + goto end; + } + + if (tor_digest_is_zero(id)) { + log_warn(LD_CONFIG, "Missing identity on FallbackDir line"); + goto end; + } + + if (orport <= 0) { + log_warn(LD_CONFIG, "Missing orport on FallbackDir line"); + goto end; + } + + if (tor_addr_port_split(LOG_INFO, smartlist_get(positional, 0), + &address, &dirport) < 0 || + tor_addr_parse(&addr, address)<0) { + log_warn(LD_CONFIG, "Couldn't parse address:port %s on FallbackDir line", + (const char*)smartlist_get(positional, 0)); + goto end; + } + + if (!validate_only) { + dir_server_t *ds; + ds = fallback_dir_server_new(&addr, dirport, orport, id, weight); + if (!ds) { + log_warn(LD_CONFIG, "Couldn't create FallbackDir %s", escaped(line)); + goto end; + } + dir_server_add(ds); + } + + r = 0; + + end: + SMARTLIST_FOREACH(items, char *, cp, tor_free(cp)); + smartlist_free(items); + smartlist_free(positional); + tor_free(address); + return r; +} + +/** Allocate and return a new port_cfg_t with reasonable defaults. */ +static port_cfg_t * +port_cfg_new(void) +{ + port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + cfg->ipv4_traffic = 1; + cfg->cache_ipv4_answers = 1; + cfg->prefer_ipv6_virtaddr = 1; + return cfg; +} + /** Free all storage held in <b>port</b> */ static void port_cfg_free(port_cfg_t *port) @@ -5576,24 +4804,29 @@ port_cfg_free(port_cfg_t *port) tor_free(port); } -/** Warn for every port in <b>ports</b> that is on a publicly routable - * address. */ +/** Warn for every port in <b>ports</b> of type <b>listener_type</b> that is + * on a publicly routable address. */ static void -warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname) +warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname, + int listener_type) { SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { + if (port->type != listener_type) + continue; if (port->is_unix_addr) { /* Unix sockets aren't accessible over a network. */ } else if (!tor_addr_is_internal(&port->addr, 1)) { - log_warn(LD_CONFIG, "You specified a public address for %sPort. " + log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. " "Other people on the Internet might find your computer and " "use it as an open proxy. Please don't allow this unless you " - "have a good reason.", portname); + "have a good reason.", + fmt_addrport(&port->addr, port->port), portname); } else if (!tor_addr_is_loopback(&port->addr)) { - log_notice(LD_CONFIG, "You configured a non-loopback address for " - "%sPort. This allows everybody on your local network to use " - "your machine as a proxy. Make sure this is what you wanted.", - portname); + log_notice(LD_CONFIG, "You configured a non-loopback address '%s' " + "for %sPort. This allows everybody on your local network to " + "use your machine as a proxy. Make sure this is what you " + "wanted.", + fmt_addrport(&port->addr, port->port), portname); } } SMARTLIST_FOREACH_END(port); } @@ -5645,6 +4878,7 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid) #define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2) #define CL_PORT_SERVER_OPTIONS (1u<<3) #define CL_PORT_FORBID_NONLOCAL (1u<<4) +#define CL_PORT_TAKES_HOSTNAMES (1u<<5) /** * Parse port configuration for a single port type. @@ -5677,6 +4911,9 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid) * isolation options in the FooPort entries; instead allow the * server-port option set. * + * If CL_PORT_TAKES_HOSTNAMES is set in <b>flags</b>, allow the options + * {No,}IPv{4,6}Traffic. + * * On success, if <b>out</b> is given, add a new port_cfg_t entry to * <b>out</b> for every port that the client should listen on. Return 0 * on success, -1 on failure. @@ -5700,6 +4937,7 @@ parse_port_config(smartlist_t *out, const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL; const unsigned allow_spurious_listenaddr = flags & CL_PORT_ALLOW_EXTRA_LISTENADDR; + const unsigned takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES; int got_zero_port=0, got_nonzero_port=0; /* FooListenAddress is deprecated; let's make it work like it used to work, @@ -5736,12 +4974,14 @@ parse_port_config(smartlist_t *out, if (use_server_options && out) { /* Add a no_listen port. */ - port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + port_cfg_t *cfg = port_cfg_new(); cfg->type = listener_type; cfg->port = mainport; tor_addr_make_unspec(&cfg->addr); /* Server ports default to 0.0.0.0 */ cfg->no_listen = 1; - cfg->ipv4_only = 1; + cfg->bind_ipv4_only = 1; + cfg->ipv4_traffic = 1; + cfg->prefer_ipv6_virtaddr = 1; smartlist_add(out, cfg); } @@ -5754,7 +4994,7 @@ parse_port_config(smartlist_t *out, return -1; } if (out) { - port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + port_cfg_t *cfg = port_cfg_new(); cfg->type = listener_type; cfg->port = port ? port : mainport; tor_addr_copy(&cfg->addr, &addr); @@ -5769,7 +5009,7 @@ parse_port_config(smartlist_t *out, if (is_control) warn_nonlocal_controller_ports(out, forbid_nonlocal); else - warn_nonlocal_client_ports(out, portname); + warn_nonlocal_client_ports(out, portname, listener_type); } return 0; } /* end if (listenaddrs) */ @@ -5778,7 +5018,7 @@ parse_port_config(smartlist_t *out, * one. */ if (! ports) { if (defaultport && out) { - port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + port_cfg_t *cfg = port_cfg_new(); cfg->type = listener_type; cfg->port = defaultport; tor_addr_parse(&cfg->addr, defaultaddr); @@ -5798,12 +5038,17 @@ parse_port_config(smartlist_t *out, int port; int sessiongroup = SESSION_GROUP_UNSET; unsigned isolation = ISO_DEFAULT; + int prefer_no_auth = 0; char *addrport; uint16_t ptmp=0; int ok; int no_listen = 0, no_advertise = 0, all_addrs = 0, - ipv4_only = 0, ipv6_only = 0; + bind_ipv4_only = 0, bind_ipv6_only = 0, + ipv4_traffic = 1, ipv6_traffic = 0, prefer_ipv6 = 0, + cache_ipv4 = 1, use_cached_ipv4 = 0, + cache_ipv6 = 0, use_cached_ipv6 = 0, + prefer_ipv6_automap = 1; smartlist_split_string(elts, ports->value, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); @@ -5868,9 +5113,9 @@ parse_port_config(smartlist_t *out, all_addrs = 1; #endif } else if (!strcasecmp(elt, "IPv4Only")) { - ipv4_only = 1; + bind_ipv4_only = 1; } else if (!strcasecmp(elt, "IPv6Only")) { - ipv6_only = 1; + bind_ipv6_only = 1; } else { log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'", portname, escaped(elt)); @@ -5883,18 +5128,18 @@ parse_port_config(smartlist_t *out, portname, escaped(ports->value)); goto err; } - if (ipv4_only && ipv6_only) { + if (bind_ipv4_only && bind_ipv6_only) { log_warn(LD_CONFIG, "Tried to set both IPv4Only and IPv6Only " "on %sPort line '%s'", portname, escaped(ports->value)); goto err; } - if (ipv4_only && tor_addr_family(&addr) == AF_INET6) { + if (bind_ipv4_only && tor_addr_family(&addr) == AF_INET6) { log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6", portname); goto err; } - if (ipv6_only && tor_addr_family(&addr) == AF_INET) { + if (bind_ipv6_only && tor_addr_family(&addr) == AF_INET) { log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4", portname); goto err; @@ -5927,6 +5172,45 @@ parse_port_config(smartlist_t *out, no = 1; elt += 2; } + + if (takes_hostnames) { + if (!strcasecmp(elt, "IPv4Traffic")) { + ipv4_traffic = ! no; + continue; + } else if (!strcasecmp(elt, "IPv6Traffic")) { + ipv6_traffic = ! no; + continue; + } else if (!strcasecmp(elt, "PreferIPv6")) { + prefer_ipv6 = ! no; + continue; + } + } + if (!strcasecmp(elt, "CacheIPv4DNS")) { + cache_ipv4 = ! no; + continue; + } else if (!strcasecmp(elt, "CacheIPv6DNS")) { + cache_ipv6 = ! no; + continue; + } else if (!strcasecmp(elt, "CacheDNS")) { + cache_ipv4 = cache_ipv6 = ! no; + continue; + } else if (!strcasecmp(elt, "UseIPv4Cache")) { + use_cached_ipv4 = ! no; + continue; + } else if (!strcasecmp(elt, "UseIPv6Cache")) { + use_cached_ipv6 = ! no; + continue; + } else if (!strcasecmp(elt, "UseDNSCache")) { + use_cached_ipv4 = use_cached_ipv6 = ! no; + continue; + } else if (!strcasecmp(elt, "PreferIPv6Automap")) { + prefer_ipv6_automap = ! no; + continue; + } else if (!strcasecmp(elt, "PreferSOCKSNoAuth")) { + prefer_no_auth = ! no; + continue; + } + if (!strcasecmpend(elt, "s")) elt[strlen(elt)-1] = '\0'; /* kill plurals. */ @@ -5958,8 +5242,14 @@ parse_port_config(smartlist_t *out, else got_zero_port = 1; + if (ipv4_traffic == 0 && ipv6_traffic == 0) { + log_warn(LD_CONFIG, "You have a %sPort entry with both IPv4 and " + "IPv6 disabled; that won't work.", portname); + goto err; + } + if (out && port) { - port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + port_cfg_t *cfg = port_cfg_new(); tor_addr_copy(&cfg->addr, &addr); cfg->port = port; cfg->type = listener_type; @@ -5968,8 +5258,19 @@ parse_port_config(smartlist_t *out, cfg->no_advertise = no_advertise; cfg->no_listen = no_listen; cfg->all_addrs = all_addrs; - cfg->ipv4_only = ipv4_only; - cfg->ipv6_only = ipv6_only; + cfg->bind_ipv4_only = bind_ipv4_only; + cfg->bind_ipv6_only = bind_ipv6_only; + cfg->ipv4_traffic = ipv4_traffic; + cfg->ipv6_traffic = ipv6_traffic; + cfg->prefer_ipv6 = prefer_ipv6; + cfg->cache_ipv4_answers = cache_ipv4; + cfg->cache_ipv6_answers = cache_ipv6; + cfg->use_cached_ipv4_answers = use_cached_ipv4; + cfg->use_cached_ipv6_answers = use_cached_ipv6; + cfg->prefer_ipv6_virtaddr = prefer_ipv6_automap; + cfg->socks_prefer_no_auth = prefer_no_auth; + if (! (isolation & ISO_SOCKSAUTH)) + cfg->socks_prefer_no_auth = 1; smartlist_add(out, cfg); } @@ -5981,7 +5282,7 @@ parse_port_config(smartlist_t *out, if (is_control) warn_nonlocal_controller_ports(out, forbid_nonlocal); else - warn_nonlocal_client_ports(out, portname); + warn_nonlocal_client_ports(out, portname, listener_type); } if (got_zero_port && got_nonzero_port) { @@ -6062,7 +5363,8 @@ parse_ports(or_options_t *options, int validate_only, options->SocksPort_lines, options->SocksListenAddress, "Socks", CONN_TYPE_AP_LISTENER, "127.0.0.1", 9050, - CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR) < 0) { + CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR| + CL_PORT_TAKES_HOSTNAMES) < 0) { *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration"); goto err; } @@ -6070,7 +5372,7 @@ parse_ports(or_options_t *options, int validate_only, options->DNSPort_lines, options->DNSListenAddress, "DNS", CONN_TYPE_AP_DNS_LISTENER, "127.0.0.1", 0, - CL_PORT_WARN_NONLOCAL) < 0) { + CL_PORT_WARN_NONLOCAL|CL_PORT_TAKES_HOSTNAMES) < 0) { *msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration"); goto err; } @@ -6202,7 +5504,8 @@ check_server_ports(const smartlist_t *ports, if (! port->no_advertise) { ++n_orport_advertised; if (tor_addr_family(&port->addr) == AF_INET || - (tor_addr_family(&port->addr) == AF_UNSPEC && !port->ipv6_only)) + (tor_addr_family(&port->addr) == AF_UNSPEC && + !port->bind_ipv6_only)) ++n_orport_advertised_ipv4; } if (! port->no_listen) @@ -6211,7 +5514,7 @@ check_server_ports(const smartlist_t *ports, continue; } #ifndef _WIN32 - if (!port->no_advertise && port->port < 1024) + if (!port->no_listen && port->port < 1024) ++n_low_port; #endif } SMARTLIST_FOREACH_END(port); @@ -6221,6 +5524,13 @@ check_server_ports(const smartlist_t *ports, "listening on one."); r = -1; } + if (n_orport_listeners && !n_orport_advertised) { + log_warn(LD_CONFIG, "We are listening on an ORPort, but not advertising " + "any ORPorts. This will keep us from building a %s " + "descriptor, and make us impossible to use.", + options->BridgeRelay ? "bridge" : "router"); + r = -1; + } if (n_dirport_advertised && !n_dirport_listeners) { log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually " "listening on one."); @@ -6238,7 +5548,7 @@ check_server_ports(const smartlist_t *ports, } if (n_low_port && options->AccountingMax) { - log(LOG_WARN, LD_CONFIG, + log_warn(LD_CONFIG, "You have set AccountingMax to use hibernation. You have also " "chosen a low DirPort or OrPort. This combination can make Tor stop " "working when it tries to re-attach the port after a period of " @@ -6302,7 +5612,8 @@ get_first_listener_addrport_string(int listener_type) to iterate all listener connections and find out in which port it ended up listening: */ if (cfg->port == CFG_AUTO_PORT) { - port = router_get_active_listener_port_by_type(listener_type); + port = router_get_active_listener_port_by_type_af(listener_type, + tor_addr_family(&cfg->addr)); if (!port) return NULL; } else { @@ -6332,8 +5643,8 @@ get_first_advertised_port_by_type_af(int listener_type, int address_family) (tor_addr_family(&cfg->addr) == address_family || tor_addr_family(&cfg->addr) == AF_UNSPEC)) { if (tor_addr_family(&cfg->addr) != AF_UNSPEC || - (address_family == AF_INET && !cfg->ipv6_only) || - (address_family == AF_INET6 && !cfg->ipv4_only)) { + (address_family == AF_INET && !cfg->bind_ipv6_only) || + (address_family == AF_INET6 && !cfg->bind_ipv4_only)) { return cfg->port; } } @@ -6494,180 +5805,6 @@ options_save_current(void) return write_configuration_file(get_torrc_fname(0), get_options()); } -/** Mapping from a unit name to a multiplier for converting that unit into a - * base unit. Used by config_parse_unit. */ -struct unit_table_t { - const char *unit; /**< The name of the unit */ - uint64_t multiplier; /**< How many of the base unit appear in this unit */ -}; - -/** Table to map the names of memory units to the number of bytes they - * contain. */ -static struct unit_table_t memory_units[] = { - { "", 1 }, - { "b", 1<< 0 }, - { "byte", 1<< 0 }, - { "bytes", 1<< 0 }, - { "kb", 1<<10 }, - { "kbyte", 1<<10 }, - { "kbytes", 1<<10 }, - { "kilobyte", 1<<10 }, - { "kilobytes", 1<<10 }, - { "m", 1<<20 }, - { "mb", 1<<20 }, - { "mbyte", 1<<20 }, - { "mbytes", 1<<20 }, - { "megabyte", 1<<20 }, - { "megabytes", 1<<20 }, - { "gb", 1<<30 }, - { "gbyte", 1<<30 }, - { "gbytes", 1<<30 }, - { "gigabyte", 1<<30 }, - { "gigabytes", 1<<30 }, - { "tb", U64_LITERAL(1)<<40 }, - { "terabyte", U64_LITERAL(1)<<40 }, - { "terabytes", U64_LITERAL(1)<<40 }, - { NULL, 0 }, -}; - -/** Table to map the names of time units to the number of seconds they - * contain. */ -static struct unit_table_t time_units[] = { - { "", 1 }, - { "second", 1 }, - { "seconds", 1 }, - { "minute", 60 }, - { "minutes", 60 }, - { "hour", 60*60 }, - { "hours", 60*60 }, - { "day", 24*60*60 }, - { "days", 24*60*60 }, - { "week", 7*24*60*60 }, - { "weeks", 7*24*60*60 }, - { NULL, 0 }, -}; - -/** Table to map the names of time units to the number of milliseconds - * they contain. */ -static struct unit_table_t time_msec_units[] = { - { "", 1 }, - { "msec", 1 }, - { "millisecond", 1 }, - { "milliseconds", 1 }, - { "second", 1000 }, - { "seconds", 1000 }, - { "minute", 60*1000 }, - { "minutes", 60*1000 }, - { "hour", 60*60*1000 }, - { "hours", 60*60*1000 }, - { "day", 24*60*60*1000 }, - { "days", 24*60*60*1000 }, - { "week", 7*24*60*60*1000 }, - { "weeks", 7*24*60*60*1000 }, - { NULL, 0 }, -}; - -/** Parse a string <b>val</b> containing a number, zero or more - * spaces, and an optional unit string. If the unit appears in the - * table <b>u</b>, then multiply the number by the unit multiplier. - * On success, set *<b>ok</b> to 1 and return this product. - * Otherwise, set *<b>ok</b> to 0. - */ -static uint64_t -config_parse_units(const char *val, struct unit_table_t *u, int *ok) -{ - 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 || (cp && *cp == '.')) { - d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp); - if (!*ok) - goto done; - use_float = 1; - } - - if (!cp) { - *ok = 1; - v = use_float ? DBL_TO_U64(d) : v; - goto done; - } - - cp = (char*) eat_whitespace(cp); - - for ( ;u->unit;++u) { - if (!strcasecmp(u->unit, cp)) { - if (use_float) - v = u->multiplier * d; - else - v *= u->multiplier; - *ok = 1; - goto done; - } - } - log_warn(LD_CONFIG, "Unknown unit '%s'.", cp); - *ok = 0; - done: - - if (*ok) - return v; - else - return 0; -} - -/** Parse a string in the format "number unit", where unit is a unit of - * information (byte, KB, M, etc). On success, set *<b>ok</b> to true - * and return the number of bytes specified. Otherwise, set - * *<b>ok</b> to false and return 0. */ -static uint64_t -config_parse_memunit(const char *s, int *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 in milliseconds. On success, set *<b>ok</b> to true and return - * the number of milliseconds in the provided interval. Otherwise, set - * *<b>ok</b> to 0 and return -1. */ -static int -config_parse_msec_interval(const char *s, int *ok) -{ - uint64_t r; - r = config_parse_units(s, time_msec_units, ok); - if (!ok) - return -1; - if (r > INT_MAX) { - log_warn(LD_CONFIG, "Msec interval '%s' is too long", s); - *ok = 0; - return -1; - } - return (int)r; -} - -/** Parse a string in the format "number unit", where unit is a unit of time. - * On success, set *<b>ok</b> to true and return the number of seconds in - * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1. - */ -static int -config_parse_interval(const char *s, int *ok) -{ - uint64_t r; - r = config_parse_units(s, time_units, ok); - if (!ok) - return -1; - if (r > INT_MAX) { - log_warn(LD_CONFIG, "Interval '%s' is too long", s); - *ok = 0; - return -1; - } - return (int)r; -} - /** Return the number of cpus configured in <b>options</b>. If we are * told to auto-detect the number of cpus, return the auto-detected number. */ int @@ -6721,14 +5858,6 @@ init_libevent(const or_options_t *options) } } -/** Return the persistent state struct for this Tor. */ -or_state_t * -get_or_state(void) -{ - tor_assert(global_state); - return global_state; -} - /** Return a newly allocated string holding a filename relative to the data * directory. If <b>sub1</b> is present, it is the first path component after * the data directory. If <b>sub2</b> is also present, it is the second path @@ -6779,474 +5908,6 @@ options_get_datadir_fname2_suffix(const or_options_t *options, return fname; } -/** Return true if <b>line</b> is a valid state TransportProxy line. - * Return false otherwise. */ -static int -state_transport_line_is_valid(const char *line) -{ - smartlist_t *items = NULL; - char *addrport=NULL; - tor_addr_t addr; - uint16_t port = 0; - int r; - - items = smartlist_new(); - smartlist_split_string(items, line, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); - - if (smartlist_len(items) != 2) { - log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line."); - goto err; - } - - addrport = smartlist_get(items, 1); - if (tor_addr_port_lookup(addrport, &addr, &port) < 0) { - log_warn(LD_CONFIG, "state: Could not parse addrport."); - goto err; - } - - if (!port) { - log_warn(LD_CONFIG, "state: Transport line did not contain port."); - goto err; - } - - r = 1; - goto done; - - err: - r = 0; - - done: - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - return r; -} - -/** Return 0 if all TransportProxy lines in <b>state</b> are well - * formed. Otherwise, return -1. */ -static int -validate_transports_in_state(or_state_t *state) -{ - int broken = 0; - config_line_t *line; - - for (line = state->TransportProxies ; line ; line = line->next) { - tor_assert(!strcmp(line->key, "TransportProxy")); - if (!state_transport_line_is_valid(line->value)) - broken = 1; - } - - if (broken) - log_warn(LD_CONFIG, "state: State file seems to be broken."); - - return 0; -} - -/** Return 0 if every setting in <b>state</b> is reasonable, and a - * permissible transition from <b>old_state</b>. Else warn and return -1. - * Should have no side effects, except for normalizing the contents of - * <b>state</b>. - */ -/* XXX from_setconf is here because of bug 238 */ -static int -or_state_validate(or_state_t *old_state, or_state_t *state, - int from_setconf, char **msg) -{ - /* We don't use these; only options do. Still, we need to match that - * signature. */ - (void) from_setconf; - (void) old_state; - - if (entry_guards_parse_state(state, 0, msg)<0) - return -1; - - if (validate_transports_in_state(state)<0) - return -1; - - return 0; -} - -/** Replace the current persistent state with <b>new_state</b> */ -static int -or_state_set(or_state_t *new_state) -{ - char *err = NULL; - int ret = 0; - tor_assert(new_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; - char *fname2 = NULL; - for (i = 0; i < 100; ++i) { - tor_asprintf(&fname2, "%s.%d", fname, i); - status = file_status(fname2); - if (status == FN_NOENT) - break; - tor_free(fname2); - } - 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. - * Return 0 on success, less than 0 on failure. - */ -static int -or_state_load(void) -{ - or_state_t *new_state = NULL; - char *contents = NULL, *fname; - char *errmsg = NULL; - int r = -1, badstate = 0; - - fname = get_datadir_fname("state"); - switch (file_status(fname)) { - case FN_FILE: - if (!(contents = read_file_to_str(fname, 0, NULL))) { - log_warn(LD_FS, "Unable to read state file \"%s\"", fname); - goto done; - } - break; - case FN_NOENT: - break; - case FN_ERROR: - case FN_DIR: - default: - log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname); - goto done; - } - new_state = tor_malloc_zero(sizeof(or_state_t)); - new_state->_magic = OR_STATE_MAGIC; - config_init(&state_format, new_state); - if (contents) { - config_line_t *lines=NULL; - int assign_retval; - if (config_get_lines(contents, &lines, 0)<0) - goto done; - assign_retval = config_assign(&state_format, new_state, - lines, 0, 0, &errmsg); - config_free_lines(lines); - if (assign_retval<0) - badstate = 1; - if (errmsg) { - log_warn(LD_GENERAL, "%s", errmsg); - tor_free(errmsg); - } - } - - if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0) - badstate = 1; - - if (errmsg) { - log_warn(LD_GENERAL, "%s", errmsg); - tor_free(errmsg); - } - - if (badstate && !contents) { - log_warn(LD_BUG, "Uh oh. We couldn't even validate our own default state." - " This is a bug in Tor."); - goto done; - } else if (badstate && contents) { - or_state_save_broken(fname); - - tor_free(contents); - config_free(&state_format, new_state); - - new_state = tor_malloc_zero(sizeof(or_state_t)); - new_state->_magic = OR_STATE_MAGIC; - config_init(&state_format, new_state); - } else if (contents) { - log_info(LD_GENERAL, "Loaded state from \"%s\"", fname); - } else { - log_info(LD_GENERAL, "Initialized state"); - } - if (or_state_set(new_state) == -1) { - or_state_save_broken(fname); - } - new_state = NULL; - if (!contents) { - global_state->next_write = 0; - or_state_save(time(NULL)); - } - r = 0; - - done: - tor_free(fname); - tor_free(contents); - if (new_state) - config_free(&state_format, new_state); - - return r; -} - -/** Did the last time we tried to write the state file fail? If so, we - * should consider disabling such features as preemptive circuit generation - * to compute circuit-build-time. */ -static int last_state_file_write_failed = 0; - -/** Return whether the state file failed to write last time we tried. */ -int -did_last_state_file_write_fail(void) -{ - return last_state_file_write_failed; -} - -/** If writing the state to disk fails, try again after this many seconds. */ -#define STATE_WRITE_RETRY_INTERVAL 3600 - -/** If we're a relay, how often should we checkpoint our state file even - * if nothing else dirties it? This will checkpoint ongoing stats like - * bandwidth used, per-country user stats, etc. */ -#define STATE_RELAY_CHECKPOINT_INTERVAL (12*60*60) - -/** Write the persistent state to disk. Return 0 for success, <0 on failure. */ -int -or_state_save(time_t now) -{ - char *state, *contents; - char tbuf[ISO_TIME_LEN+1]; - char *fname; - - tor_assert(global_state); - - if (global_state->next_write > now) - return 0; - - /* Call everything else that might dirty the state even more, in order - * 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 = now; - - tor_free(global_state->TorVersion); - tor_asprintf(&global_state->TorVersion, "Tor %s", get_version()); - - state = config_dump(&state_format, NULL, global_state, 1, 0); - format_local_iso_time(tbuf, now); - tor_asprintf(&contents, - "# Tor state file last generated on %s local time\n" - "# Other times below are in GMT\n" - "# You *do not* need to edit this file.\n\n%s", - tbuf, state); - tor_free(state); - 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\"; " - "will try again later", fname); - last_state_file_write_failed = 1; - tor_free(fname); - tor_free(contents); - /* Try again after STATE_WRITE_RETRY_INTERVAL (or sooner, if the state - * changes sooner). */ - global_state->next_write = now + STATE_WRITE_RETRY_INTERVAL; - return -1; - } - - last_state_file_write_failed = 0; - log_info(LD_GENERAL, "Saved state to \"%s\"", fname); - tor_free(fname); - tor_free(contents); - - if (server_mode(get_options())) - global_state->next_write = now + STATE_RELAY_CHECKPOINT_INTERVAL; - else - global_state->next_write = TIME_MAX; - - return 0; -} - -/** Return the config line for transport <b>transport</b> in the current state. - * Return NULL if there is no config line for <b>transport</b>. */ -static config_line_t * -get_transport_in_state_by_name(const char *transport) -{ - or_state_t *or_state = get_or_state(); - config_line_t *line; - config_line_t *ret = NULL; - smartlist_t *items = NULL; - - for (line = or_state->TransportProxies ; line ; line = line->next) { - tor_assert(!strcmp(line->key, "TransportProxy")); - - items = smartlist_new(); - smartlist_split_string(items, line->value, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); - if (smartlist_len(items) != 2) /* broken state */ - goto done; - - if (!strcmp(smartlist_get(items, 0), transport)) { - ret = line; - goto done; - } - - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - items = NULL; - } - - done: - if (items) { - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - } - return ret; -} - -/** Return string containing the address:port part of the - * TransportProxy <b>line</b> for transport <b>transport</b>. - * If the line is corrupted, return NULL. */ -static const char * -get_transport_bindaddr(const char *line, const char *transport) -{ - char *line_tmp = NULL; - - if (strlen(line) < strlen(transport) + 2) { - goto broken_state; - } else { - /* line should start with the name of the transport and a space. - (for example, "obfs2 127.0.0.1:47245") */ - tor_asprintf(&line_tmp, "%s ", transport); - if (strcmpstart(line, line_tmp)) - goto broken_state; - - tor_free(line_tmp); - return (line+strlen(transport)+1); - } - - broken_state: - tor_free(line_tmp); - return NULL; -} - -/** Return a string containing the address:port that a proxy transport - * should bind on. The string is stored on the heap and must be freed - * by the caller of this function. */ -char * -get_stored_bindaddr_for_server_transport(const char *transport) -{ - char *default_addrport = NULL; - const char *stored_bindaddr = NULL; - - config_line_t *line = get_transport_in_state_by_name(transport); - if (!line) /* Found no references in state for this transport. */ - goto no_bindaddr_found; - - stored_bindaddr = get_transport_bindaddr(line->value, transport); - if (stored_bindaddr) /* found stored bindaddr in state file. */ - return tor_strdup(stored_bindaddr); - - no_bindaddr_found: - /** If we didn't find references for this pluggable transport in the - state file, we should instruct the pluggable transport proxy to - listen on INADDR_ANY on a random ephemeral port. */ - tor_asprintf(&default_addrport, "%s:%s", fmt_addr32(INADDR_ANY), "0"); - return default_addrport; -} - -/** Save <b>transport</b> listening on <b>addr</b>:<b>port</b> to - state */ -void -save_transport_to_state(const char *transport, - const tor_addr_t *addr, uint16_t port) -{ - or_state_t *state = get_or_state(); - - char *transport_addrport=NULL; - - /** find where to write on the state */ - config_line_t **next, *line; - - /* see if this transport is already stored in state */ - config_line_t *transport_line = - get_transport_in_state_by_name(transport); - - if (transport_line) { /* if transport already exists in state... */ - const char *prev_bindaddr = /* get its addrport... */ - get_transport_bindaddr(transport_line->value, transport); - tor_asprintf(&transport_addrport, "%s:%d", fmt_addr(addr), (int)port); - - /* if transport in state has the same address as this one, life is good */ - if (!strcmp(prev_bindaddr, transport_addrport)) { - log_info(LD_CONFIG, "Transport seems to have spawned on its usual " - "address:port."); - goto done; - } else { /* if addrport in state is different than the one we got */ - log_info(LD_CONFIG, "Transport seems to have spawned on different " - "address:port. Let's update the state file with the new " - "address:port"); - tor_free(transport_line->value); /* free the old line */ - tor_asprintf(&transport_line->value, "%s %s:%d", transport, - fmt_addr(addr), - (int) port); /* replace old addrport line with new line */ - } - } else { /* never seen this one before; save it in state for next time */ - log_info(LD_CONFIG, "It's the first time we see this transport. " - "Let's save its address:port"); - next = &state->TransportProxies; - /* find the last TransportProxy line in the state and point 'next' - right after it */ - line = state->TransportProxies; - while (line) { - next = &(line->next); - line = line->next; - } - - /* allocate space for the new line and fill it in */ - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("TransportProxy"); - tor_asprintf(&line->value, "%s %s:%d", transport, - fmt_addr(addr), (int) port); - - next = &(line->next); - } - - if (!get_options()->AvoidDiskWrites) - or_state_mark_dirty(state, 0); - - done: - tor_free(transport_addrport); -} - /** Given a file name check to see whether the file exists but has not been * modified for a very long time. If so, remove it. */ void @@ -7264,6 +5925,43 @@ remove_file_if_very_old(const char *fname, time_t now) } } +/** Return a smartlist of ports that must be forwarded by + * tor-fw-helper. The smartlist contains the ports in a string format + * that is understandable by tor-fw-helper. */ +smartlist_t * +get_list_of_ports_to_forward(void) +{ + smartlist_t *ports_to_forward = smartlist_new(); + int port = 0; + + /** XXX TODO tor-fw-helper does not support forwarding ports to + other hosts than the local one. If the user is binding to a + different IP address, tor-fw-helper won't work. */ + port = router_get_advertised_or_port(get_options()); /* Get ORPort */ + if (port) + smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port); + + port = router_get_advertised_dir_port(get_options(), 0); /* Get DirPort */ + if (port) + smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port); + + /* Get ports of transport proxies */ + { + smartlist_t *transport_ports = get_transport_proxy_ports(); + if (transport_ports) { + smartlist_add_all(ports_to_forward, transport_ports); + smartlist_free(transport_ports); + } + } + + if (!smartlist_len(ports_to_forward)) { + smartlist_free(ports_to_forward); + ports_to_forward = NULL; + } + + return ports_to_forward; +} + /** Helper to implement GETINFO functions about configuration variables (not * their values). Given a "config/names" question, set *<b>answer</b> to a * new string describing the supported configuration variables and their @@ -7278,9 +5976,12 @@ getinfo_helper_config(control_connection_t *conn, if (!strcmp(question, "config/names")) { smartlist_t *sl = smartlist_new(); int i; - for (i = 0; _option_vars[i].name; ++i) { - const config_var_t *var = &_option_vars[i]; + for (i = 0; option_vars_[i].name; ++i) { + const config_var_t *var = &option_vars_[i]; const char *type; + /* don't tell controller about triple-underscore options */ + if (!strncmp(option_vars_[i].name, "___", 3)) + continue; switch (var->type) { case CONFIG_TYPE_STRING: type = "String"; break; case CONFIG_TYPE_FILENAME: type = "Filename"; break; @@ -7310,7 +6011,120 @@ getinfo_helper_config(control_connection_t *conn, *answer = smartlist_join_strings(sl, "", 0, NULL); SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); + } else if (!strcmp(question, "config/defaults")) { + smartlist_t *sl = smartlist_new(); + int i; + for (i = 0; option_vars_[i].name; ++i) { + const config_var_t *var = &option_vars_[i]; + if (var->initvalue != NULL) { + char *val = esc_for_log(var->initvalue); + smartlist_add_asprintf(sl, "%s %s\n",var->name,val); + tor_free(val); + } + } + *answer = smartlist_join_strings(sl, "", 0, NULL); + SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); + smartlist_free(sl); + } + return 0; +} + +/** Parse outbound bind address option lines. If <b>validate_only</b> + * is not 0 update OutboundBindAddressIPv4_ and + * OutboundBindAddressIPv6_ in <b>options</b>. On failure, set + * <b>msg</b> (if provided) to a newly allocated string containing a + * description of the problem and return -1. */ +static int +parse_outbound_addresses(or_options_t *options, int validate_only, char **msg) +{ + const config_line_t *lines = options->OutboundBindAddress; + int found_v4 = 0, found_v6 = 0; + + if (!validate_only) { + memset(&options->OutboundBindAddressIPv4_, 0, + sizeof(options->OutboundBindAddressIPv4_)); + memset(&options->OutboundBindAddressIPv6_, 0, + sizeof(options->OutboundBindAddressIPv6_)); + } + while (lines) { + tor_addr_t addr, *dst_addr = NULL; + int af = tor_addr_parse(&addr, lines->value); + switch (af) { + case AF_INET: + if (found_v4) { + if (msg) + tor_asprintf(msg, "Multiple IPv4 outbound bind addresses " + "configured: %s", lines->value); + return -1; + } + found_v4 = 1; + dst_addr = &options->OutboundBindAddressIPv4_; + break; + case AF_INET6: + if (found_v6) { + if (msg) + tor_asprintf(msg, "Multiple IPv6 outbound bind addresses " + "configured: %s", lines->value); + return -1; + } + found_v6 = 1; + dst_addr = &options->OutboundBindAddressIPv6_; + break; + default: + if (msg) + tor_asprintf(msg, "Outbound bind address '%s' didn't parse.", + lines->value); + return -1; + } + if (!validate_only) + tor_addr_copy(dst_addr, &addr); + lines = lines->next; } return 0; } +/** Load one of the geoip files, <a>family</a> determining which + * one. <a>default_fname</a> is used if on Windows and + * <a>fname</a> equals "<default>". */ +static void +config_load_geoip_file_(sa_family_t family, + const char *fname, + const char *default_fname) +{ +#ifdef _WIN32 + char *free_fname = NULL; /* Used to hold any temporary-allocated value */ + /* XXXX Don't use this "<default>" junk; make our filename options + * understand prefixes somehow. -NM */ + if (!strcmp(fname, "<default>")) { + const char *conf_root = get_windows_conf_root(); + tor_asprintf(&free_fname, "%s\\%s", conf_root, default_fname); + fname = free_fname; + } + geoip_load_file(family, fname); + tor_free(free_fname); +#else + (void)default_fname; + geoip_load_file(family, fname); +#endif +} + +/** Load geoip files for IPv4 and IPv6 if <a>options</a> and + * <a>old_options</a> indicate we should. */ +static void +config_maybe_load_geoip_files_(const or_options_t *options, + const or_options_t *old_options) +{ + /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */ + + if (options->GeoIPFile && + ((!old_options || !opt_streq(old_options->GeoIPFile, + options->GeoIPFile)) + || !geoip_is_loaded(AF_INET))) + config_load_geoip_file_(AF_INET, options->GeoIPFile, "geoip"); + if (options->GeoIPv6File && + ((!old_options || !opt_streq(old_options->GeoIPv6File, + options->GeoIPv6File)) + || !geoip_is_loaded(AF_INET6))) + config_load_geoip_file_(AF_INET6, options->GeoIPv6File, "geoip6"); +} + diff --git a/src/or/config.h b/src/or/config.h index dd76edcf1d..ef4acac514 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for config.c. **/ -#ifndef _TOR_CONFIG_H -#define _TOR_CONFIG_H +#ifndef TOR_CONFIG_H +#define TOR_CONFIG_H const char *get_dirportfrontpage(void); const or_options_t *get_options(void); @@ -23,13 +23,13 @@ const char *escaped_safe_str_client(const char *address); const char *escaped_safe_str(const char *address); const char *get_version(void); const char *get_short_version(void); - -int config_get_lines(const char *string, config_line_t **result, int extended); -void config_free_lines(config_line_t *front); setopt_err_t options_trial_assign(config_line_t *list, int use_defaults, int clear_first, char **msg); + +uint32_t get_last_resolved_addr(void); int resolve_my_address(int warn_severity, const or_options_t *options, - uint32_t *addr, char **hostname_out); + uint32_t *addr_out, + const char **method_out, char **hostname_out); int is_local_addr(const tor_addr_t *addr); void options_init(or_options_t *options); char *options_dump(const or_options_t *options, int minimal); @@ -61,10 +61,6 @@ char *options_get_datadir_fname2_suffix(const or_options_t *options, int get_num_cpus(const or_options_t *options); -or_state_t *get_or_state(void); -int did_last_state_file_write_fail(void); -int or_state_save(time_t now); - const smartlist_t *get_configured_ports(void); int get_first_advertised_port_by_type_af(int listener_type, int address_family); @@ -78,9 +74,7 @@ char *get_first_listener_addrport_string(int listener_type); int options_need_geoip_info(const or_options_t *options, const char **reason_out); -void save_transport_to_state(const char *transport_name, - const tor_addr_t *addr, uint16_t port); -char *get_stored_bindaddr_for_server_transport(const char *transport); +smartlist_t *get_list_of_ports_to_forward(void); int getinfo_helper_config(control_connection_t *conn, const char *question, char **answer, @@ -90,6 +84,8 @@ const char *tor_get_digests(void); uint32_t get_effective_bwrate(const or_options_t *options); uint32_t get_effective_bwburst(const or_options_t *options); +char *get_transport_bindaddr_from_config(const char *transport); + #ifdef CONFIG_PRIVATE /* Used only by config.c and test.c */ or_options_t *options_new(void); diff --git a/src/or/confparse.c b/src/or/confparse.c new file mode 100644 index 0000000000..8863d92409 --- /dev/null +++ b/src/or/confparse.c @@ -0,0 +1,1231 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "confparse.h" +#include "routerset.h" + +static uint64_t config_parse_memunit(const char *s, int *ok); +static int config_parse_msec_interval(const char *s, int *ok); +static int config_parse_interval(const char *s, int *ok); +static void config_reset(const config_format_t *fmt, void *options, + const config_var_t *var, int use_defaults); + +/** Allocate an empty configuration object of a given format type. */ +void * +config_new(const config_format_t *fmt) +{ + void *opts = tor_malloc_zero(fmt->size); + *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic; + CONFIG_CHECK(fmt, opts); + return opts; +} + +/* + * Functions to parse config options + */ + +/** If <b>option</b> is an official abbreviation for a longer option, + * return the longer option. Otherwise return <b>option</b>. + * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only + * apply abbreviations that work for the config file and the command line. + * If <b>warn_obsolete</b> is set, warn about deprecated names. */ +const char * +config_expand_abbrev(const config_format_t *fmt, const char *option, + int command_line, int warn_obsolete) +{ + int i; + if (! fmt->abbrevs) + return option; + for (i=0; fmt->abbrevs[i].abbreviated; ++i) { + /* Abbreviations are case insensitive. */ + if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) && + (command_line || !fmt->abbrevs[i].commandline_only)) { + if (warn_obsolete && fmt->abbrevs[i].warn) { + log_warn(LD_CONFIG, + "The configuration option '%s' is deprecated; " + "use '%s' instead.", + fmt->abbrevs[i].abbreviated, + 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; +} + +/** Helper: allocate a new configuration option mapping 'key' to 'val', + * append it to *<b>lst</b>. */ +void +config_line_append(config_line_t **lst, + const char *key, + const char *val) +{ + config_line_t *newline; + + newline = tor_malloc_zero(sizeof(config_line_t)); + newline->key = tor_strdup(key); + newline->value = tor_strdup(val); + newline->next = NULL; + while (*lst) + lst = &((*lst)->next); + + (*lst) = newline; +} + +/** Helper: parse the config string and strdup into key/value + * strings. Set *result to the list, or NULL if parsing the string + * failed. Return 0 on success, -1 on failure. Warn and ignore any + * misformatted lines. + * + * If <b>extended</b> is set, then treat keys beginning with / and with + as + * indicating "clear" and "append" respectively. */ +int +config_get_lines(const char *string, config_line_t **result, int extended) +{ + config_line_t *list = NULL, **next; + char *k, *v; + const char *parse_err; + + next = &list; + do { + k = v = NULL; + string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err); + if (!string) { + log_warn(LD_CONFIG, "Error while parsing configuration: %s", + parse_err?parse_err:"<unknown>"); + config_free_lines(list); + tor_free(k); + tor_free(v); + return -1; + } + if (k && v) { + unsigned command = CONFIG_LINE_NORMAL; + if (extended) { + if (k[0] == '+') { + char *k_new = tor_strdup(k+1); + tor_free(k); + k = k_new; + command = CONFIG_LINE_APPEND; + } else if (k[0] == '/') { + char *k_new = tor_strdup(k+1); + tor_free(k); + k = k_new; + tor_free(v); + v = tor_strdup(""); + command = CONFIG_LINE_CLEAR; + } + } + /* This list can get long, so we keep a pointer to the end of it + * rather than using config_line_append over and over and getting + * n^2 performance. */ + *next = tor_malloc_zero(sizeof(config_line_t)); + (*next)->key = k; + (*next)->value = v; + (*next)->next = NULL; + (*next)->command = command; + next = &((*next)->next); + } else { + tor_free(k); + tor_free(v); + } + } while (*string); + + *result = list; + return 0; +} + +/** + * Free all the configuration lines on the linked list <b>front</b>. + */ +void +config_free_lines(config_line_t *front) +{ + config_line_t *tmp; + + while (front) { + tmp = front; + front = tmp->next; + + tor_free(tmp->key); + tor_free(tmp->value); + tor_free(tmp); + } +} + +/** As config_find_option, but return a non-const pointer. */ +config_var_t * +config_find_option_mutable(config_format_t *fmt, const char *key) +{ + int i; + size_t keylen = strlen(key); + if (!keylen) + return NULL; /* if they say "--" on the command line, it's not an option */ + /* First, check for an exact (case-insensitive) match */ + for (i=0; fmt->vars[i].name; ++i) { + if (!strcasecmp(key, fmt->vars[i].name)) { + return &fmt->vars[i]; + } + } + /* If none, check for an abbreviated match */ + for (i=0; fmt->vars[i].name; ++i) { + if (!strncasecmp(key, fmt->vars[i].name, keylen)) { + log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. " + "Please use '%s' instead", + key, fmt->vars[i].name); + return &fmt->vars[i]; + } + } + /* Okay, unrecognized option */ + return NULL; +} + +/** If <b>key</b> is a configuration option, return the corresponding const + * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation, + * warn, and return the corresponding const config_var_t. Otherwise return + * NULL. + */ +const config_var_t * +config_find_option(const config_format_t *fmt, const char *key) +{ + return config_find_option_mutable((config_format_t*)fmt, key); +} + +/** Return the number of option entries in <b>fmt</b>. */ +static int +config_count_options(const config_format_t *fmt) +{ + int i; + for (i=0; fmt->vars[i].name; ++i) + ; + return i; +} + +/* + * Functions to assign config options. + */ + +/** <b>c</b>-\>key is known to be a real key. Update <b>options</b> + * with <b>c</b>-\>value and return 0, or return -1 if bad value. + * + * Called from config_assign_line() and option_reset(). + */ +static int +config_assign_value(const config_format_t *fmt, void *options, + config_line_t *c, char **msg) +{ + int i, ok; + const config_var_t *var; + void *lvalue; + + CONFIG_CHECK(fmt, options); + + var = config_find_option(fmt, c->key); + tor_assert(var); + + lvalue = STRUCT_VAR_P(options, var->var_offset); + + switch (var->type) { + + case CONFIG_TYPE_PORT: + if (!strcasecmp(c->value, "auto")) { + *(int *)lvalue = CFG_AUTO_PORT; + break; + } + /* fall through */ + case CONFIG_TYPE_INT: + case CONFIG_TYPE_UINT: + i = (int)tor_parse_long(c->value, 10, + var->type==CONFIG_TYPE_INT ? INT_MIN : 0, + var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX, + &ok, NULL); + if (!ok) { + tor_asprintf(msg, + "Int keyword '%s %s' is malformed or out of bounds.", + c->key, c->value); + return -1; + } + *(int *)lvalue = i; + break; + + case CONFIG_TYPE_INTERVAL: { + i = config_parse_interval(c->value, &ok); + if (!ok) { + tor_asprintf(msg, + "Interval '%s %s' is malformed or out of bounds.", + c->key, c->value); + return -1; + } + *(int *)lvalue = i; + break; + } + + case CONFIG_TYPE_MSEC_INTERVAL: { + i = config_parse_msec_interval(c->value, &ok); + if (!ok) { + tor_asprintf(msg, + "Msec interval '%s %s' is malformed or out of bounds.", + c->key, c->value); + return -1; + } + *(int *)lvalue = i; + break; + } + + case CONFIG_TYPE_MEMUNIT: { + uint64_t u64 = config_parse_memunit(c->value, &ok); + if (!ok) { + tor_asprintf(msg, + "Value '%s %s' is malformed or out of bounds.", + c->key, c->value); + return -1; + } + *(uint64_t *)lvalue = u64; + break; + } + + case CONFIG_TYPE_BOOL: + i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL); + if (!ok) { + tor_asprintf(msg, + "Boolean '%s %s' expects 0 or 1.", + c->key, c->value); + return -1; + } + *(int *)lvalue = i; + break; + + case CONFIG_TYPE_AUTOBOOL: + if (!strcmp(c->value, "auto")) + *(int *)lvalue = -1; + else if (!strcmp(c->value, "0")) + *(int *)lvalue = 0; + else if (!strcmp(c->value, "1")) + *(int *)lvalue = 1; + else { + tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.", + c->key, c->value); + return -1; + } + break; + + case CONFIG_TYPE_STRING: + case CONFIG_TYPE_FILENAME: + tor_free(*(char **)lvalue); + *(char **)lvalue = tor_strdup(c->value); + break; + + case CONFIG_TYPE_DOUBLE: + *(double *)lvalue = atof(c->value); + break; + + case CONFIG_TYPE_ISOTIME: + if (parse_iso_time(c->value, (time_t *)lvalue)) { + tor_asprintf(msg, + "Invalid time '%s' for keyword '%s'", c->value, c->key); + return -1; + } + break; + + case CONFIG_TYPE_ROUTERSET: + if (*(routerset_t**)lvalue) { + routerset_free(*(routerset_t**)lvalue); + } + *(routerset_t**)lvalue = routerset_new(); + if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) { + tor_asprintf(msg, "Invalid exit list '%s' for option '%s'", + c->value, c->key); + return -1; + } + break; + + case CONFIG_TYPE_CSV: + if (*(smartlist_t**)lvalue) { + SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp)); + smartlist_clear(*(smartlist_t**)lvalue); + } else { + *(smartlist_t**)lvalue = smartlist_new(); + } + + smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + break; + + case CONFIG_TYPE_LINELIST: + case CONFIG_TYPE_LINELIST_S: + { + config_line_t *lastval = *(config_line_t**)lvalue; + if (lastval && lastval->fragile) { + if (c->command != CONFIG_LINE_APPEND) { + config_free_lines(lastval); + *(config_line_t**)lvalue = NULL; + } else { + lastval->fragile = 0; + } + } + + config_line_append((config_line_t**)lvalue, c->key, c->value); + } + break; + case CONFIG_TYPE_OBSOLETE: + log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key); + break; + case CONFIG_TYPE_LINELIST_V: + tor_asprintf(msg, + "You may not provide a value for virtual option '%s'", c->key); + return -1; + default: + tor_assert(0); + break; + } + return 0; +} + +/** Mark every linelist in <b>options</b> "fragile", so that fresh assignments + * to it will replace old ones. */ +static void +config_mark_lists_fragile(const config_format_t *fmt, void *options) +{ + int i; + tor_assert(fmt); + tor_assert(options); + + for (i = 0; fmt->vars[i].name; ++i) { + const config_var_t *var = &fmt->vars[i]; + config_line_t *list; + if (var->type != CONFIG_TYPE_LINELIST && + var->type != CONFIG_TYPE_LINELIST_V) + continue; + + list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset); + if (list) + list->fragile = 1; + } +} + +/** If <b>c</b> is a syntactically valid configuration line, update + * <b>options</b> with its value and return 0. Otherwise return -1 for bad + * key, -2 for bad value. + * + * If <b>clear_first</b> is set, clear the value first. Then if + * <b>use_defaults</b> is set, set the value to the default. + * + * Called from config_assign(). + */ +static int +config_assign_line(const config_format_t *fmt, void *options, + config_line_t *c, int use_defaults, + int clear_first, bitarray_t *options_seen, char **msg) +{ + const config_var_t *var; + + CONFIG_CHECK(fmt, options); + + var = config_find_option(fmt, c->key); + if (!var) { + if (fmt->extra) { + void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset); + log_info(LD_CONFIG, + "Found unrecognized option '%s'; saving it.", c->key); + config_line_append((config_line_t**)lvalue, c->key, c->value); + return 0; + } else { + tor_asprintf(msg, + "Unknown option '%s'. Failing.", c->key); + return -1; + } + } + + /* Put keyword into canonical case. */ + if (strcmp(var->name, c->key)) { + tor_free(c->key); + c->key = tor_strdup(var->name); + } + + if (!strlen(c->value)) { + /* reset or clear it, then return */ + if (!clear_first) { + if ((var->type == CONFIG_TYPE_LINELIST || + var->type == CONFIG_TYPE_LINELIST_S) && + c->command != CONFIG_LINE_CLEAR) { + /* We got an empty linelist from the torrc or command line. + As a special case, call this an error. Warn and ignore. */ + log_warn(LD_CONFIG, + "Linelist option '%s' has no value. Skipping.", c->key); + } else { /* not already cleared */ + config_reset(fmt, options, var, use_defaults); + } + } + return 0; + } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) { + config_reset(fmt, options, var, use_defaults); + } + + 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; +} + +/** Restore the option named <b>key</b> in options to its default value. + * Called from config_assign(). */ +static void +config_reset_line(const config_format_t *fmt, void *options, + const char *key, int use_defaults) +{ + const config_var_t *var; + + CONFIG_CHECK(fmt, options); + + var = config_find_option(fmt, key); + if (!var) + return; /* give error on next pass. */ + + config_reset(fmt, options, var, use_defaults); +} + +/** Return true iff value needs to be quoted and escaped to be used in + * a configuration file. */ +static int +config_value_needs_escape(const char *value) +{ + if (*value == '\"') + return 1; + while (*value) { + switch (*value) + { + case '\r': + case '\n': + case '#': + /* Note: quotes and backspaces need special handling when we are using + * quotes, not otherwise, so they don't trigger escaping on their + * own. */ + return 1; + default: + if (!TOR_ISPRINT(*value)) + return 1; + } + ++value; + } + return 0; +} + +/** Return a newly allocated deep copy of the lines in <b>inp</b>. */ +config_line_t * +config_lines_dup(const config_line_t *inp) +{ + config_line_t *result = NULL; + config_line_t **next_out = &result; + while (inp) { + *next_out = tor_malloc_zero(sizeof(config_line_t)); + (*next_out)->key = tor_strdup(inp->key); + (*next_out)->value = tor_strdup(inp->value); + inp = inp->next; + next_out = &((*next_out)->next); + } + (*next_out) = NULL; + return result; +} + +/** Return newly allocated line or lines corresponding to <b>key</b> in the + * configuration <b>options</b>. If <b>escape_val</b> is true and a + * value needs to be quoted before it's put in a config file, quote and + * escape that value. Return NULL if no such key exists. */ +config_line_t * +config_get_assigned_option(const config_format_t *fmt, const void *options, + const char *key, int escape_val) +{ + const config_var_t *var; + const void *value; + config_line_t *result; + tor_assert(options && key); + + CONFIG_CHECK(fmt, options); + + var = config_find_option(fmt, key); + if (!var) { + log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key); + return NULL; + } + value = STRUCT_VAR_P(options, var->var_offset); + + result = tor_malloc_zero(sizeof(config_line_t)); + result->key = tor_strdup(var->name); + switch (var->type) + { + case CONFIG_TYPE_STRING: + case CONFIG_TYPE_FILENAME: + if (*(char**)value) { + result->value = tor_strdup(*(char**)value); + } else { + tor_free(result->key); + tor_free(result); + return NULL; + } + break; + case CONFIG_TYPE_ISOTIME: + if (*(time_t*)value) { + result->value = tor_malloc(ISO_TIME_LEN+1); + format_iso_time(result->value, *(time_t*)value); + } else { + tor_free(result->key); + tor_free(result); + } + escape_val = 0; /* Can't need escape. */ + break; + case CONFIG_TYPE_PORT: + if (*(int*)value == CFG_AUTO_PORT) { + result->value = tor_strdup("auto"); + escape_val = 0; + break; + } + /* fall through */ + case CONFIG_TYPE_INTERVAL: + case CONFIG_TYPE_MSEC_INTERVAL: + case CONFIG_TYPE_UINT: + case CONFIG_TYPE_INT: + /* This means every or_options_t uint or bool element + * needs to be an int. Not, say, a uint16_t or char. */ + tor_asprintf(&result->value, "%d", *(int*)value); + escape_val = 0; /* Can't need escape. */ + break; + case CONFIG_TYPE_MEMUNIT: + tor_asprintf(&result->value, U64_FORMAT, + U64_PRINTF_ARG(*(uint64_t*)value)); + escape_val = 0; /* Can't need escape. */ + break; + case CONFIG_TYPE_DOUBLE: + tor_asprintf(&result->value, "%f", *(double*)value); + escape_val = 0; /* Can't need escape. */ + break; + + case CONFIG_TYPE_AUTOBOOL: + if (*(int*)value == -1) { + result->value = tor_strdup("auto"); + escape_val = 0; + break; + } + /* fall through */ + case CONFIG_TYPE_BOOL: + result->value = tor_strdup(*(int*)value ? "1" : "0"); + escape_val = 0; /* Can't need escape. */ + break; + case CONFIG_TYPE_ROUTERSET: + result->value = routerset_to_string(*(routerset_t**)value); + break; + case CONFIG_TYPE_CSV: + if (*(smartlist_t**)value) + result->value = + smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL); + else + result->value = tor_strdup(""); + break; + case CONFIG_TYPE_OBSOLETE: + log_fn(LOG_INFO, LD_CONFIG, + "You asked me for the value of an obsolete config option '%s'.", + key); + tor_free(result->key); + tor_free(result); + return NULL; + case CONFIG_TYPE_LINELIST_S: + log_warn(LD_CONFIG, + "Can't return context-sensitive '%s' on its own", key); + tor_free(result->key); + tor_free(result); + return NULL; + case CONFIG_TYPE_LINELIST: + case CONFIG_TYPE_LINELIST_V: + tor_free(result->key); + tor_free(result); + result = config_lines_dup(*(const config_line_t**)value); + break; + default: + tor_free(result->key); + tor_free(result); + log_warn(LD_BUG,"Unknown type %d for known key '%s'", + var->type, key); + return NULL; + } + + if (escape_val) { + config_line_t *line; + for (line = result; line; line = line->next) { + if (line->value && config_value_needs_escape(line->value)) { + char *newval = esc_for_log(line->value); + tor_free(line->value); + line->value = newval; + } + } + } + + return result; +} +/** Iterate through the linked list of requested options <b>list</b>. + * For each item, convert as appropriate and assign to <b>options</b>. + * If an item is unrecognized, set *msg and return -1 immediately, + * else return 0 for success. + * + * If <b>clear_first</b>, interpret config options as replacing (not + * extending) their previous values. If <b>clear_first</b> is set, + * then <b>use_defaults</b> to decide if you set to defaults after + * clearing, or make the value 0 or NULL. + * + * Here are the use cases: + * 1. A non-empty AllowInvalid line in your torrc. Appends to current + * if linelist, replaces current if csv. + * 2. An empty AllowInvalid line in your torrc. Should clear it. + * 3. "RESETCONF AllowInvalid" sets it to default. + * 4. "SETCONF AllowInvalid" makes it NULL. + * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo". + * + * Use_defaults Clear_first + * 0 0 "append" + * 1 0 undefined, don't use + * 0 1 "set to null first" + * 1 1 "set to defaults first" + * Return 0 on success, -1 on bad key, -2 on bad value. + * + * As an additional special case, if a LINELIST config option has + * no value and clear_first is 0, then warn and ignore it. + */ + +/* +There are three call cases for config_assign() currently. + +Case one: Torrc entry +options_init_from_torrc() calls config_assign(0, 0) + calls config_assign_line(0, 0). + if value is empty, calls config_reset(0) and returns. + calls config_assign_value(), appends. + +Case two: setconf +options_trial_assign() calls config_assign(0, 1) + calls config_reset_line(0) + calls config_reset(0) + calls option_clear(). + calls config_assign_line(0, 1). + if value is empty, returns. + calls config_assign_value(), appends. + +Case three: resetconf +options_trial_assign() calls config_assign(1, 1) + calls config_reset_line(1) + calls config_reset(1) + calls option_clear(). + calls config_assign_value(default) + calls config_assign_line(1, 1). + returns. +*/ +int +config_assign(const config_format_t *fmt, void *options, config_line_t *list, + int use_defaults, int clear_first, char **msg) +{ + config_line_t *p; + bitarray_t *options_seen; + const int n_options = config_count_options(fmt); + + CONFIG_CHECK(fmt, options); + + /* pass 1: normalize keys */ + for (p = list; p; p = p->next) { + const char *full = config_expand_abbrev(fmt, p->key, 0, 1); + if (strcmp(full,p->key)) { + tor_free(p->key); + p->key = tor_strdup(full); + } + } + + /* pass 2: if we're reading from a resetting source, clear all + * mentioned config options, and maybe set to their defaults. */ + if (clear_first) { + for (p = list; p; p = p->next) + 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, options_seen, msg))) { + bitarray_free(options_seen); + return r; + } + list = list->next; + } + bitarray_free(options_seen); + + /** Now we're done assigning a group of options to the configuration. + * Subsequent group assignments should _replace_ linelists, not extend + * them. */ + config_mark_lists_fragile(fmt, options); + + return 0; +} + +/** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent. + * Called from config_reset() and config_free(). */ +static void +config_clear(const config_format_t *fmt, void *options, + const config_var_t *var) +{ + void *lvalue = STRUCT_VAR_P(options, var->var_offset); + (void)fmt; /* unused */ + switch (var->type) { + case CONFIG_TYPE_STRING: + case CONFIG_TYPE_FILENAME: + tor_free(*(char**)lvalue); + break; + case CONFIG_TYPE_DOUBLE: + *(double*)lvalue = 0.0; + break; + case CONFIG_TYPE_ISOTIME: + *(time_t*)lvalue = 0; + break; + case CONFIG_TYPE_INTERVAL: + case CONFIG_TYPE_MSEC_INTERVAL: + case CONFIG_TYPE_UINT: + case CONFIG_TYPE_INT: + case CONFIG_TYPE_PORT: + case CONFIG_TYPE_BOOL: + *(int*)lvalue = 0; + break; + case CONFIG_TYPE_AUTOBOOL: + *(int*)lvalue = -1; + break; + case CONFIG_TYPE_MEMUNIT: + *(uint64_t*)lvalue = 0; + break; + case CONFIG_TYPE_ROUTERSET: + if (*(routerset_t**)lvalue) { + routerset_free(*(routerset_t**)lvalue); + *(routerset_t**)lvalue = NULL; + } + break; + case CONFIG_TYPE_CSV: + if (*(smartlist_t**)lvalue) { + SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp)); + smartlist_free(*(smartlist_t **)lvalue); + *(smartlist_t **)lvalue = NULL; + } + break; + case CONFIG_TYPE_LINELIST: + case CONFIG_TYPE_LINELIST_S: + config_free_lines(*(config_line_t **)lvalue); + *(config_line_t **)lvalue = NULL; + break; + case CONFIG_TYPE_LINELIST_V: + /* handled by linelist_s. */ + break; + case CONFIG_TYPE_OBSOLETE: + break; + } +} + +/** Clear the option indexed by <b>var</b> in <b>options</b>. Then if + * <b>use_defaults</b>, set it to its default value. + * Called by config_init() and option_reset_line() and option_assign_line(). */ +static void +config_reset(const config_format_t *fmt, void *options, + const config_var_t *var, int use_defaults) +{ + config_line_t *c; + char *msg = NULL; + CONFIG_CHECK(fmt, options); + config_clear(fmt, options, var); /* clear it first */ + if (!use_defaults) + return; /* all done */ + if (var->initvalue) { + c = tor_malloc_zero(sizeof(config_line_t)); + c->key = tor_strdup(var->name); + c->value = tor_strdup(var->initvalue); + if (config_assign_value(fmt, options, c, &msg) < 0) { + log_warn(LD_BUG, "Failed to assign default: %s", msg); + tor_free(msg); /* if this happens it's a bug */ + } + config_free_lines(c); + } +} + +/** Release storage held by <b>options</b>. */ +void +config_free(const config_format_t *fmt, void *options) +{ + int i; + + if (!options) + return; + + tor_assert(fmt); + + for (i=0; fmt->vars[i].name; ++i) + config_clear(fmt, options, &(fmt->vars[i])); + if (fmt->extra) { + config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset); + config_free_lines(*linep); + *linep = NULL; + } + tor_free(options); +} + +/** Return true iff a and b contain identical keys and values in identical + * order. */ +int +config_lines_eq(config_line_t *a, config_line_t *b) +{ + while (a && b) { + if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value)) + return 0; + a = a->next; + b = b->next; + } + if (a || b) + return 0; + return 1; +} + +/** Return the number of lines in <b>a</b> whose key is <b>key</b>. */ +int +config_count_key(const config_line_t *a, const char *key) +{ + int n = 0; + while (a) { + if (!strcasecmp(a->key, key)) { + ++n; + } + a = a->next; + } + return n; +} + +/** Return true iff the option <b>name</b> has the same value in <b>o1</b> + * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options. + */ +int +config_is_same(const config_format_t *fmt, + const void *o1, const void *o2, + const char *name) +{ + config_line_t *c1, *c2; + int r = 1; + CONFIG_CHECK(fmt, o1); + CONFIG_CHECK(fmt, o2); + + c1 = config_get_assigned_option(fmt, o1, name, 0); + c2 = config_get_assigned_option(fmt, o2, name, 0); + r = config_lines_eq(c1, c2); + config_free_lines(c1); + config_free_lines(c2); + return r; +} + +/** Copy storage held by <b>old</b> into a new or_options_t and return it. */ +void * +config_dup(const config_format_t *fmt, const void *old) +{ + void *newopts; + int i; + config_line_t *line; + + newopts = config_new(fmt); + for (i=0; fmt->vars[i].name; ++i) { + if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S) + continue; + if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE) + continue; + line = config_get_assigned_option(fmt, old, fmt->vars[i].name, 0); + if (line) { + char *msg = NULL; + if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) { + log_err(LD_BUG, "config_get_assigned_option() generated " + "something we couldn't config_assign(): %s", msg); + tor_free(msg); + tor_assert(0); + } + } + config_free_lines(line); + } + return newopts; +} +/** Set all vars in the configuration object <b>options</b> to their default + * values. */ +void +config_init(const config_format_t *fmt, void *options) +{ + int i; + const config_var_t *var; + CONFIG_CHECK(fmt, options); + + for (i=0; fmt->vars[i].name; ++i) { + var = &fmt->vars[i]; + if (!var->initvalue) + continue; /* defaults to NULL or 0 */ + config_reset(fmt, options, var, 1); + } +} + +/** Allocate and return a new string holding the written-out values of the vars + * in 'options'. If 'minimal', do not write out any default-valued vars. + * Else, if comment_defaults, write default values as comments. + */ +char * +config_dump(const config_format_t *fmt, const void *default_options, + const void *options, int minimal, + int comment_defaults) +{ + smartlist_t *elements; + const void *defaults = default_options; + void *defaults_tmp = NULL; + config_line_t *line, *assigned; + char *result; + int i; + char *msg = NULL; + + if (defaults == NULL) { + defaults = defaults_tmp = config_new(fmt); + config_init(fmt, defaults_tmp); + } + + /* XXX use a 1 here so we don't add a new log line while dumping */ + if (default_options == NULL) { + if (fmt->validate_fn(NULL, defaults_tmp, 1, &msg) < 0) { + log_err(LD_BUG, "Failed to validate default config."); + tor_free(msg); + tor_assert(0); + } + } + + elements = smartlist_new(); + for (i=0; fmt->vars[i].name; ++i) { + int comment_option = 0; + if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE || + fmt->vars[i].type == CONFIG_TYPE_LINELIST_S) + continue; + /* Don't save 'hidden' control variables. */ + if (!strcmpstart(fmt->vars[i].name, "__")) + continue; + if (minimal && config_is_same(fmt, options, defaults, fmt->vars[i].name)) + continue; + else if (comment_defaults && + config_is_same(fmt, options, defaults, fmt->vars[i].name)) + comment_option = 1; + + line = assigned = + config_get_assigned_option(fmt, options, fmt->vars[i].name, 1); + + for (; line; line = line->next) { + smartlist_add_asprintf(elements, "%s%s %s\n", + comment_option ? "# " : "", + line->key, line->value); + } + config_free_lines(assigned); + } + + if (fmt->extra) { + line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset); + for (; line; line = line->next) { + smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value); + } + } + + result = smartlist_join_strings(elements, "", 0, NULL); + SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); + smartlist_free(elements); + if (defaults_tmp) + config_free(fmt, defaults_tmp); + return result; +} + +/** Mapping from a unit name to a multiplier for converting that unit into a + * base unit. Used by config_parse_unit. */ +struct unit_table_t { + const char *unit; /**< The name of the unit */ + uint64_t multiplier; /**< How many of the base unit appear in this unit */ +}; + +/** Table to map the names of memory units to the number of bytes they + * contain. */ +static struct unit_table_t memory_units[] = { + { "", 1 }, + { "b", 1<< 0 }, + { "byte", 1<< 0 }, + { "bytes", 1<< 0 }, + { "kb", 1<<10 }, + { "kbyte", 1<<10 }, + { "kbytes", 1<<10 }, + { "kilobyte", 1<<10 }, + { "kilobytes", 1<<10 }, + { "m", 1<<20 }, + { "mb", 1<<20 }, + { "mbyte", 1<<20 }, + { "mbytes", 1<<20 }, + { "megabyte", 1<<20 }, + { "megabytes", 1<<20 }, + { "gb", 1<<30 }, + { "gbyte", 1<<30 }, + { "gbytes", 1<<30 }, + { "gigabyte", 1<<30 }, + { "gigabytes", 1<<30 }, + { "tb", U64_LITERAL(1)<<40 }, + { "terabyte", U64_LITERAL(1)<<40 }, + { "terabytes", U64_LITERAL(1)<<40 }, + { NULL, 0 }, +}; + +/** Table to map the names of time units to the number of seconds they + * contain. */ +static struct unit_table_t time_units[] = { + { "", 1 }, + { "second", 1 }, + { "seconds", 1 }, + { "minute", 60 }, + { "minutes", 60 }, + { "hour", 60*60 }, + { "hours", 60*60 }, + { "day", 24*60*60 }, + { "days", 24*60*60 }, + { "week", 7*24*60*60 }, + { "weeks", 7*24*60*60 }, + { "month", 2629728, }, /* about 30.437 days */ + { "months", 2629728, }, + { NULL, 0 }, +}; + +/** Table to map the names of time units to the number of milliseconds + * they contain. */ +static struct unit_table_t time_msec_units[] = { + { "", 1 }, + { "msec", 1 }, + { "millisecond", 1 }, + { "milliseconds", 1 }, + { "second", 1000 }, + { "seconds", 1000 }, + { "minute", 60*1000 }, + { "minutes", 60*1000 }, + { "hour", 60*60*1000 }, + { "hours", 60*60*1000 }, + { "day", 24*60*60*1000 }, + { "days", 24*60*60*1000 }, + { "week", 7*24*60*60*1000 }, + { "weeks", 7*24*60*60*1000 }, + { NULL, 0 }, +}; + +/** Parse a string <b>val</b> containing a number, zero or more + * spaces, and an optional unit string. If the unit appears in the + * table <b>u</b>, then multiply the number by the unit multiplier. + * On success, set *<b>ok</b> to 1 and return this product. + * Otherwise, set *<b>ok</b> to 0. + */ +static uint64_t +config_parse_units(const char *val, struct unit_table_t *u, int *ok) +{ + 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 || (cp && *cp == '.')) { + d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp); + if (!*ok) + goto done; + use_float = 1; + } + + if (!cp) { + *ok = 1; + v = use_float ? DBL_TO_U64(d) : v; + goto done; + } + + cp = (char*) eat_whitespace(cp); + + for ( ;u->unit;++u) { + if (!strcasecmp(u->unit, cp)) { + if (use_float) + v = u->multiplier * d; + else + v *= u->multiplier; + *ok = 1; + goto done; + } + } + log_warn(LD_CONFIG, "Unknown unit '%s'.", cp); + *ok = 0; + done: + + if (*ok) + return v; + else + return 0; +} + +/** Parse a string in the format "number unit", where unit is a unit of + * information (byte, KB, M, etc). On success, set *<b>ok</b> to true + * and return the number of bytes specified. Otherwise, set + * *<b>ok</b> to false and return 0. */ +static uint64_t +config_parse_memunit(const char *s, int *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 in milliseconds. On success, set *<b>ok</b> to true and return + * the number of milliseconds in the provided interval. Otherwise, set + * *<b>ok</b> to 0 and return -1. */ +static int +config_parse_msec_interval(const char *s, int *ok) +{ + uint64_t r; + r = config_parse_units(s, time_msec_units, ok); + if (!ok) + return -1; + if (r > INT_MAX) { + log_warn(LD_CONFIG, "Msec interval '%s' is too long", s); + *ok = 0; + return -1; + } + return (int)r; +} + +/** Parse a string in the format "number unit", where unit is a unit of time. + * On success, set *<b>ok</b> to true and return the number of seconds in + * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1. + */ +static int +config_parse_interval(const char *s, int *ok) +{ + uint64_t r; + r = config_parse_units(s, time_units, ok); + if (!ok) + return -1; + if (r > INT_MAX) { + log_warn(LD_CONFIG, "Interval '%s' is too long", s); + *ok = 0; + return -1; + } + return (int)r; +} + diff --git a/src/or/confparse.h b/src/or/confparse.h new file mode 100644 index 0000000000..1b987f3bf9 --- /dev/null +++ b/src/or/confparse.h @@ -0,0 +1,132 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_CONFPARSE_H +#define TOR_CONFPARSE_H + +/** Enumeration of types which option values can take */ +typedef enum config_type_t { + CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */ + CONFIG_TYPE_FILENAME, /**< A filename: some prefixes get expanded. */ + CONFIG_TYPE_UINT, /**< A non-negative integer less than MAX_INT */ + CONFIG_TYPE_INT, /**< Any integer. */ + CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or + * "auto". */ + CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/ + CONFIG_TYPE_MSEC_INTERVAL,/**< A number of milliseconds, with optional + * units */ + CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/ + CONFIG_TYPE_DOUBLE, /**< A floating-point value */ + CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */ + CONFIG_TYPE_AUTOBOOL, /**< A boolean+auto value, expressed 0 for false, + * 1 for true, and -1 for auto */ + CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to UTC. */ + CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and + * optional whitespace. */ + CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */ + CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines, + * mixed with other keywords. */ + CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize + * context-sensitive config lines when fetching. + */ + CONFIG_TYPE_ROUTERSET, /**< A list of router names, addrs, and fps, + * parsed into a routerset_t. */ + CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */ +} config_type_t; + +/** An abbreviation for a configuration option allowed on the command line. */ +typedef struct config_abbrev_t { + const char *abbreviated; + const char *full; + int commandline_only; + int warn; +} config_abbrev_t; + +/* Handy macro for declaring "In the config file or on the command line, + * you can abbreviate <b>tok</b>s as <b>tok</b>". */ +#define PLURAL(tok) { #tok, #tok "s", 0, 0 } + +/** A variable allowed in the configuration file or on the command line. */ +typedef struct config_var_t { + const char *name; /**< The full keyword (case insensitive). */ + config_type_t type; /**< How to interpret the type and turn it into a + * value. */ + off_t var_offset; /**< Offset of the corresponding member of or_options_t. */ + const char *initvalue; /**< String (or null) describing initial value. */ +} config_var_t; + +/** Represents an English description of a configuration variable; used when + * generating configuration file comments. */ +typedef struct config_var_description_t { + const char *name; + const char *description; +} config_var_description_t; + +/** Type of a callback to validate whether a given configuration is + * well-formed and consistent. See options_trial_assign() for documentation + * of arguments. */ +typedef int (*validate_fn_t)(void*,void*,int,char**); + +/** Information on the keys, value types, key-to-struct-member mappings, + * variable descriptions, validation functions, and abbreviations for a + * configuration or storage format. */ +typedef struct { + size_t size; /**< Size of the struct that everything gets parsed into. */ + uint32_t magic; /**< Required 'magic value' to make sure we have a struct + * of the right type. */ + off_t magic_offset; /**< Offset of the magic value within the struct. */ + config_abbrev_t *abbrevs; /**< List of abbreviations that we expand when + * parsing this format. */ + 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. */ + /** If present, extra is a LINELIST variable for unrecognized + * lines. Otherwise, unrecognized lines are an error. */ + config_var_t *extra; +} config_format_t; + +/** Macro: assert that <b>cfg</b> has the right magic field for format + * <b>fmt</b>. */ +#define CONFIG_CHECK(fmt, cfg) STMT_BEGIN \ + tor_assert(fmt && cfg); \ + tor_assert((fmt)->magic == \ + *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset)); \ + STMT_END + +void *config_new(const config_format_t *fmt); +void config_line_append(config_line_t **lst, + const char *key, const char *val); +config_line_t *config_lines_dup(const config_line_t *inp); +void config_free(const config_format_t *fmt, void *options); +int config_lines_eq(config_line_t *a, config_line_t *b); +int config_count_key(const config_line_t *a, const char *key); +config_line_t *config_get_assigned_option(const config_format_t *fmt, + const void *options, const char *key, + int escape_val); +int config_is_same(const config_format_t *fmt, + const void *o1, const void *o2, + const char *name); +void config_init(const config_format_t *fmt, void *options); +void *config_dup(const config_format_t *fmt, const void *old); +char *config_dump(const config_format_t *fmt, const void *default_options, + const void *options, int minimal, + int comment_defaults); +int config_assign(const config_format_t *fmt, void *options, + config_line_t *list, + int use_defaults, int clear_first, char **msg); +config_var_t *config_find_option_mutable(config_format_t *fmt, + const char *key); +const config_var_t *config_find_option(const config_format_t *fmt, + const char *key); + +int config_get_lines(const char *string, config_line_t **result, int extended); +void config_free_lines(config_line_t *front); +const char *config_expand_abbrev(const config_format_t *fmt, + const char *option, + int command_line, int warn_obsolete); + +#endif + diff --git a/src/or/connection.c b/src/or/connection.c index e366e0e77f..4f74a1d04b 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,6 +12,13 @@ #include "or.h" #include "buffers.h" +/* + * Define this so we get channel internal functions, since we're implementing + * part of a subclass (channel_tls_t). + */ +#define TOR_CHANNEL_INTERNAL_ +#include "channel.h" +#include "channeltls.h" #include "circuitbuild.h" #include "circuitlist.h" #include "circuituse.h" @@ -25,6 +32,7 @@ #include "dirserv.h" #include "dns.h" #include "dnsserv.h" +#include "entrynodes.h" #include "geoip.h" #include "main.h" #include "policies.h" @@ -34,6 +42,7 @@ #include "rendcommon.h" #include "rephist.h" #include "router.h" +#include "transports.h" #include "routerparse.h" #ifdef USE_BUFFEREVENTS @@ -238,7 +247,16 @@ dir_connection_new(int socket_family) } /** Allocate and return a new or_connection_t, initialized as by - * connection_init(). */ + * connection_init(). + * + * Set timestamp_last_added_nonpadding to now. + * + * Assign a pseudorandom next_circ_id between 0 and 2**15. + * + * Initialize active_circuit_pqueue. + * + * Set active_circuit_pqueue_last_recalibrated to current cell_ewma tick. + */ or_connection_t * or_connection_new(int socket_family) { @@ -247,16 +265,15 @@ or_connection_new(int socket_family) connection_init(now, TO_CONN(or_conn), CONN_TYPE_OR, 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_new(); - or_conn->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick(); return or_conn; } /** Allocate and return a new entry_connection_t, initialized as by - * connection_init(). */ + * connection_init(). + * + * Allocate space to store the socks_request. + */ entry_connection_t * entry_connection_new(int type, int socket_family) { @@ -264,6 +281,13 @@ entry_connection_new(int type, int socket_family) tor_assert(type == CONN_TYPE_AP); connection_init(time(NULL), ENTRY_TO_CONN(entry_conn), type, socket_family); entry_conn->socks_request = socks_request_new(); + /* If this is coming from a listener, we'll set it up based on the listener + * in a little while. Otherwise, we're doing this as a linked connection + * of some kind, and we should set it up here based on the socket family */ + if (socket_family == AF_INET) + entry_conn->ipv4_traffic_ok = 1; + else if (socket_family == AF_INET6) + entry_conn->ipv6_traffic_ok = 1; return entry_conn; } @@ -338,14 +362,11 @@ connection_new(int type, int socket_family) /** Initializes conn. (you must call connection_add() to link it into the main * array). * + * Set conn-\>magic to the correct value. + * * Set conn-\>type to <b>type</b>. Set conn-\>s and conn-\>conn_array_index to * -1 to signify they are not yet assigned. * - * If conn is not a listener type, allocate buffers for it. If it's - * an AP type, allocate space to store the socks_request. - * - * Assign a pseudorandom next_circ_id between 0 and 2**15. - * * Initialize conn's timestamps to now. */ static void @@ -414,7 +435,7 @@ connection_link_connections(connection_t *conn_a, connection_t *conn_b) * if <b>conn</b> is an OR or OP connection. */ static void -_connection_free(connection_t *conn) +connection_free_(connection_t *conn) { void *mem; size_t memlen; @@ -492,8 +513,23 @@ _connection_free(connection_t *conn) 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 (or_conn->chan) { + /* Owww, this shouldn't happen, but... */ + log_info(LD_CHANNEL, + "Freeing orconn at %p, saw channel %p with ID " + U64_FORMAT " left un-NULLed", + or_conn, TLS_CHAN_TO_BASE(or_conn->chan), + U64_PRINTF_ARG( + TLS_CHAN_TO_BASE(or_conn->chan)->global_identifier)); + if (!(TLS_CHAN_TO_BASE(or_conn->chan)->state == CHANNEL_STATE_CLOSED || + TLS_CHAN_TO_BASE(or_conn->chan)->state == CHANNEL_STATE_ERROR)) { + channel_close_for_error(TLS_CHAN_TO_BASE(or_conn->chan)); + } + + or_conn->chan->conn = NULL; + or_conn->chan = NULL; + } } if (conn->type == CONN_TYPE_AP) { entry_connection_t *entry_conn = TO_ENTRY_CONN(conn); @@ -592,7 +628,7 @@ connection_free(connection_t *conn) connection_control_closed(TO_CONTROL_CONN(conn)); } connection_unregister_events(conn); - _connection_free(conn); + connection_free_(conn); } /** @@ -668,7 +704,42 @@ connection_close_immediate(connection_t *conn) /** Mark <b>conn</b> to be closed next time we loop through * conn_close_if_marked() in main.c. */ void -_connection_mark_for_close(connection_t *conn, int line, const char *file) +connection_mark_for_close_(connection_t *conn, int line, const char *file) +{ + assert_connection_ok(conn,0); + tor_assert(line); + tor_assert(line < 1<<16); /* marked_for_close can only fit a uint16_t. */ + tor_assert(file); + + if (conn->type == CONN_TYPE_OR) { + /* + * An or_connection should have been closed through one of the channel- + * aware functions in connection_or.c. We'll assume this is an error + * close and do that, and log a bug warning. + */ + log_warn(LD_CHANNEL | LD_BUG, + "Something tried to close an or_connection_t without going " + "through channels at %s:%d", + file, line); + connection_or_close_for_error(TO_OR_CONN(conn), 0); + } else { + /* Pass it down to the real function */ + connection_mark_for_close_internal_(conn, line, file); + } +} + +/** Mark <b>conn</b> to be closed next time we loop through + * conn_close_if_marked() in main.c; the _internal version bypasses the + * CONN_TYPE_OR checks; this should be called when you either are sure that + * if this is an or_connection_t the controlling channel has been notified + * (e.g. with connection_or_notify_error()), or you actually are the + * connection_or_close_for_error() or connection_or_close_normally function. + * For all other cases, use connection_mark_and_flush() instead, which + * checks for or_connection_t properly, instead. See below. + */ +void +connection_mark_for_close_internal_(connection_t *conn, + int line, const char *file) { assert_connection_ok(conn,0); tor_assert(line); @@ -676,13 +747,24 @@ _connection_mark_for_close(connection_t *conn, int line, const char *file) tor_assert(file); if (conn->marked_for_close) { - log(LOG_WARN,LD_BUG,"Duplicate call to connection_mark_for_close at %s:%d" + log_warn(LD_BUG,"Duplicate call to connection_mark_for_close at %s:%d" " (first at %s:%d)", file, line, conn->marked_for_close_file, conn->marked_for_close); tor_fragile_assert(); return; } + if (conn->type == CONN_TYPE_OR) { + /* + * Bad news if this happens without telling the controlling channel; do + * this so we can find things that call this wrongly when the asserts hit. + */ + log_debug(LD_CHANNEL, + "Calling connection_mark_for_close_internal_() on an OR conn " + "at %s:%d", + file, line); + } + conn->marked_for_close = line; conn->marked_for_close_file = file; add_connection_to_closeable_list(conn); @@ -852,11 +934,35 @@ make_socket_reuseable(tor_socket_t sock) * right after somebody else has let it go. But REUSEADDR on win32 * means you can bind to the port _even when somebody else * already has it bound_. So, don't do that on Win32. */ - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, - (socklen_t)sizeof(one)); + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, + (socklen_t)sizeof(one)) == -1) { + log_warn(LD_NET, "Error setting SO_REUSEADDR flag: %s", + tor_socket_strerror(errno)); + } #endif } +/** Max backlog to pass to listen. We start at */ +static int listen_limit = INT_MAX; + +/* Listen on <b>fd</b> with appropriate backlog. Return as for listen. */ +static int +tor_listen(tor_socket_t fd) +{ + int r; + + if ((r = listen(fd, listen_limit)) < 0) { + if (listen_limit == SOMAXCONN) + return r; + if ((r = listen(fd, SOMAXCONN)) == 0) { + listen_limit = SOMAXCONN; + log_warn(LD_NET, "Setting listen backlog to INT_MAX connections " + "didn't work, but SOMAXCONN did. Lowering backlog limit."); + } + } + return r; +} + /** Bind a new non-blocking socket listening to the socket described * by <b>listensockaddr</b>. * @@ -881,7 +987,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, static int global_next_session_group = SESSION_GROUP_FIRST_AUTO; tor_addr_t addr; - if (get_n_open_sockets() >= get_options()->_ConnLimit-1) { + if (get_n_open_sockets() >= get_options()->ConnLimit_-1) { warn_too_many_conns(); return NULL; } @@ -894,8 +1000,8 @@ connection_listener_new(const struct sockaddr *listensockaddr, tor_addr_from_sockaddr(&addr, listensockaddr, &usePort); - log_notice(LD_NET, "Opening %s on %s:%d", - conn_type_to_string(type), fmt_addr(&addr), usePort); + log_notice(LD_NET, "Opening %s on %s", + conn_type_to_string(type), fmt_addrport(&addr, usePort)); s = tor_open_socket(tor_addr_family(&addr), is_tcp ? SOCK_STREAM : SOCK_DGRAM, @@ -940,7 +1046,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, } if (is_tcp) { - if (listen(s,SOMAXCONN) < 0) { + if (tor_listen(s) < 0) { log_warn(LD_NET, "Could not listen on %s:%u: %s", address, usePort, tor_socket_strerror(tor_socket_errno(s))); tor_close_socket(s); @@ -992,6 +1098,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, if (bind(s, listensockaddr, (socklen_t)sizeof(struct sockaddr_un)) == -1) { log_warn(LD_NET,"Bind to %s failed: %s.", address, tor_socket_strerror(tor_socket_errno(s))); + tor_close_socket(s); goto err; } #ifdef HAVE_PWD_H @@ -1000,9 +1107,12 @@ connection_listener_new(const struct sockaddr *listensockaddr, if (pw == NULL) { log_warn(LD_NET,"Unable to chown() %s socket: user %s not found.", address, options->User); + tor_close_socket(s); + goto err; } else if (chown(address, pw->pw_uid, pw->pw_gid) < 0) { log_warn(LD_NET,"Unable to chown() %s socket: %s.", address, strerror(errno)); + tor_close_socket(s); goto err; } } @@ -1032,7 +1142,10 @@ connection_listener_new(const struct sockaddr *listensockaddr, tor_assert(0); } - set_socket_nonblocking(s); + if (set_socket_nonblocking(s) == -1) { + tor_close_socket(s); + goto err; + } lis_conn = listener_connection_new(type, listensockaddr->sa_family); conn = TO_CONN(lis_conn); @@ -1056,6 +1169,20 @@ connection_listener_new(const struct sockaddr *listensockaddr, lis_conn->session_group = global_next_session_group--; } } + if (type == CONN_TYPE_AP_LISTENER) { + lis_conn->socks_ipv4_traffic = port_cfg->ipv4_traffic; + lis_conn->socks_ipv6_traffic = port_cfg->ipv6_traffic; + lis_conn->socks_prefer_ipv6 = port_cfg->prefer_ipv6; + } else { + lis_conn->socks_ipv4_traffic = 1; + lis_conn->socks_ipv6_traffic = 1; + } + lis_conn->cache_ipv4_answers = port_cfg->cache_ipv4_answers; + lis_conn->cache_ipv6_answers = port_cfg->cache_ipv6_answers; + lis_conn->use_cached_ipv4_answers = port_cfg->use_cached_ipv4_answers; + lis_conn->use_cached_ipv6_answers = port_cfg->use_cached_ipv6_answers; + lis_conn->prefer_ipv6_virtaddr = port_cfg->prefer_ipv6_virtaddr; + lis_conn->socks_prefer_no_auth = port_cfg->socks_prefer_no_auth; if (connection_add(conn) < 0) { /* no space, forget it */ log_warn(LD_NET,"connection_add for listener failed. Giving up."); @@ -1089,7 +1216,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, * nmap does). We want to detect that, and not go on with the connection. */ static int -check_sockaddr(struct sockaddr *sa, int len, int level) +check_sockaddr(const struct sockaddr *sa, int len, int level) { int ok = 1; @@ -1182,7 +1309,10 @@ connection_handle_listener_read(connection_t *conn, int new_type) (int)news,(int)conn->s); make_socket_reuseable(news); - set_socket_nonblocking(news); + if (set_socket_nonblocking(news) == -1) { + tor_close_socket(news); + return 0; + } if (options->ConstrainedSockets) set_constrained_socket_buffers(news, (int)options->ConstrainedSockSize); @@ -1202,11 +1332,6 @@ connection_handle_listener_read(connection_t *conn, int new_type) return 0; } - if (check_sockaddr_family_match(remote->sa_family, conn) < 0) { - tor_close_socket(news); - return 0; - } - tor_addr_from_sockaddr(&addr, remote, &port); /* process entrance policies here, before we even create the connection */ @@ -1215,7 +1340,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) if (socks_policy_permits_address(&addr) == 0) { log_notice(LD_APP, "Denying socks connection from untrusted address %s.", - fmt_addr(&addr)); + fmt_and_decorate_addr(&addr)); tor_close_socket(news); return 0; } @@ -1224,7 +1349,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) /* check dirpolicy to see if we should accept it */ if (dir_policy_permits_address(&addr) == 0) { log_notice(LD_DIRSERV,"Denying dir connection from address %s.", - fmt_addr(&addr)); + fmt_and_decorate_addr(&addr)); tor_close_socket(news); return 0; } @@ -1238,6 +1363,11 @@ connection_handle_listener_read(connection_t *conn, int new_type) newconn->port = port; newconn->address = tor_dup_addr(&addr); + if (new_type == CONN_TYPE_AP) { + TO_ENTRY_CONN(newconn)->socks_request->socks_prefer_no_auth = + TO_LISTENER_CONN(conn)->socks_prefer_no_auth; + } + } else if (conn->socket_family == AF_UNIX) { /* For now only control ports can be Unix domain sockets * and listeners at the same time */ @@ -1276,17 +1406,36 @@ static int connection_init_accepted_conn(connection_t *conn, const listener_connection_t *listener) { + int rv; + connection_start_reading(conn); switch (conn->type) { case CONN_TYPE_OR: control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0); - return connection_tls_start_handshake(TO_OR_CONN(conn), 1); + rv = connection_tls_start_handshake(TO_OR_CONN(conn), 1); + if (rv < 0) { + connection_or_close_for_error(TO_OR_CONN(conn), 0); + } + return rv; + break; case CONN_TYPE_AP: TO_ENTRY_CONN(conn)->isolation_flags = listener->isolation_flags; TO_ENTRY_CONN(conn)->session_group = listener->session_group; TO_ENTRY_CONN(conn)->nym_epoch = get_signewnym_epoch(); - TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->_base.type; + TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->base_.type; + TO_ENTRY_CONN(conn)->ipv4_traffic_ok = listener->socks_ipv4_traffic; + TO_ENTRY_CONN(conn)->ipv6_traffic_ok = listener->socks_ipv6_traffic; + TO_ENTRY_CONN(conn)->prefer_ipv6_traffic = listener->socks_prefer_ipv6; + TO_ENTRY_CONN(conn)->cache_ipv4_answers = listener->cache_ipv4_answers; + TO_ENTRY_CONN(conn)->cache_ipv6_answers = listener->cache_ipv6_answers; + TO_ENTRY_CONN(conn)->use_cached_ipv4_answers = + listener->use_cached_ipv4_answers; + TO_ENTRY_CONN(conn)->use_cached_ipv6_answers = + listener->use_cached_ipv6_answers; + TO_ENTRY_CONN(conn)->prefer_ipv6_virtaddr = + listener->prefer_ipv6_virtaddr; + switch (TO_CONN(listener)->type) { case CONN_TYPE_AP_LISTENER: conn->state = AP_CONN_STATE_SOCKS_WAIT; @@ -1333,7 +1482,7 @@ connection_connect(connection_t *conn, const char *address, const or_options_t *options = get_options(); int protocol_family; - if (get_n_open_sockets() >= get_options()->_ConnLimit-1) { + if (get_n_open_sockets() >= get_options()->ConnLimit_-1) { warn_too_many_conns(); *socket_error = SOCK_ERRNO(ENOBUFS); return -1; @@ -1348,16 +1497,9 @@ connection_connect(connection_t *conn, const char *address, /* We should never even try to connect anyplace if DisableNetwork is set. * Warn if we do, and refuse to make the connection. */ static ratelim_t disablenet_violated = RATELIM_INIT(30*60); - char *m; -#ifdef _WIN32 - *socket_error = WSAENETUNREACH; -#else - *socket_error = ENETUNREACH; -#endif - if ((m = rate_limit_log(&disablenet_violated, approx_time()))) { - log_warn(LD_BUG, "Tried to open a socket with DisableNetwork set.%s", m); - tor_free(m); - } + *socket_error = SOCK_ERRNO(ENETUNREACH); + log_fn_ratelim(&disablenet_violated, LOG_WARN, LD_BUG, + "Tried to open a socket with DisableNetwork set."); tor_fragile_assert(); return -1; } @@ -1372,28 +1514,43 @@ connection_connect(connection_t *conn, const char *address, make_socket_reuseable(s); - if (options->OutboundBindAddress && !tor_addr_is_loopback(addr)) { - struct sockaddr_in ext_addr; - - memset(&ext_addr, 0, sizeof(ext_addr)); - ext_addr.sin_family = AF_INET; - ext_addr.sin_port = 0; - if (!tor_inet_aton(options->OutboundBindAddress, &ext_addr.sin_addr)) { - log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.", - options->OutboundBindAddress); - } else { - if (bind(s, (struct sockaddr*)&ext_addr, - (socklen_t)sizeof(ext_addr)) < 0) { - *socket_error = tor_socket_errno(s); - log_warn(LD_NET,"Error binding network socket: %s", - tor_socket_strerror(*socket_error)); - tor_close_socket(s); - return -1; + if (!tor_addr_is_loopback(addr)) { + const tor_addr_t *ext_addr = NULL; + if (protocol_family == AF_INET && + !tor_addr_is_null(&options->OutboundBindAddressIPv4_)) + ext_addr = &options->OutboundBindAddressIPv4_; + else if (protocol_family == AF_INET6 && + !tor_addr_is_null(&options->OutboundBindAddressIPv6_)) + ext_addr = &options->OutboundBindAddressIPv6_; + if (ext_addr) { + struct sockaddr_storage ext_addr_sa; + socklen_t ext_addr_len = 0; + memset(&ext_addr_sa, 0, sizeof(ext_addr_sa)); + ext_addr_len = tor_addr_to_sockaddr(ext_addr, 0, + (struct sockaddr *) &ext_addr_sa, + sizeof(ext_addr_sa)); + if (ext_addr_len == 0) { + log_warn(LD_NET, + "Error converting OutboundBindAddress %s into sockaddr. " + "Ignoring.", fmt_and_decorate_addr(ext_addr)); + } else { + if (bind(s, (struct sockaddr *) &ext_addr_sa, ext_addr_len) < 0) { + *socket_error = tor_socket_errno(s); + log_warn(LD_NET,"Error binding network socket to %s: %s", + fmt_and_decorate_addr(ext_addr), + tor_socket_strerror(*socket_error)); + tor_close_socket(s); + return -1; + } } } } - set_socket_nonblocking(s); + if (set_socket_nonblocking(s) == -1) { + *socket_error = tor_socket_errno(s); + tor_close_socket(s); + return -1; + } if (options->ConstrainedSockets) set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize); @@ -1424,7 +1581,7 @@ 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).", + "Connection to %s:%u %s (sock "TOR_SOCKET_T_FORMAT").", escaped_safe_str_client(address), port, inprogress?"in progress":"established", s); conn->s = s; @@ -1495,17 +1652,17 @@ connection_proxy_connect(connection_t *conn, int type) } if (base64_authenticator) { - const char *addr = fmt_addr(&conn->addr); - tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n" - "Host: %s:%d\r\n" + const char *addrport = fmt_addrport(&conn->addr, conn->port); + tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.1\r\n" + "Host: %s\r\n" "Proxy-Authorization: Basic %s\r\n\r\n", - addr, conn->port, - addr, conn->port, + addrport, + addrport, 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); + tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.0\r\n\r\n", + fmt_addrport(&conn->addr, conn->port)); } connection_write_to_buf(buf, strlen(buf), conn); @@ -1607,6 +1764,7 @@ connection_read_https_proxy_response(connection_t *conn) tor_free(headers); return -1; } + tor_free(headers); if (!reason) reason = tor_strdup("[no reason given]"); if (status_code == 200) { @@ -1952,6 +2110,8 @@ retry_all_listeners(smartlist_t *replaced_conns, const or_options_t *options = get_options(); int retval = 0; const uint16_t old_or_port = router_get_advertised_or_port(options); + const uint16_t old_or_port_ipv6 = + router_get_advertised_or_port_by_af(options,AF_INET6); const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0); SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { @@ -1980,8 +2140,9 @@ retry_all_listeners(smartlist_t *replaced_conns, smartlist_free(listeners); - /* XXXprop186 should take all advertised ports into account */ if (old_or_port != router_get_advertised_or_port(options) || + old_or_port_ipv6 != router_get_advertised_or_port_by_af(options, + AF_INET6) || old_dir_port != router_get_advertised_dir_port(options, 0)) { /* Our chosen ORPort or DirPort is not what it used to be: the * descriptor we had (if any) should be regenerated. (We won't @@ -2033,9 +2194,9 @@ connection_mark_all_noncontrol_connections(void) /** Return 1 if we should apply rate limiting to <b>conn</b>, and 0 * otherwise. * Right now this just checks if it's an internal IP address or an - * internal connection. We also check if the connection uses pluggable - * transports, since we should then limit it even if it comes from an - * internal IP address. */ + * internal connection. We also should, but don't, check if the connection + * uses pluggable transports, since we should then limit it even if it + * comes from an internal IP address. */ static int connection_is_rate_limited(connection_t *conn) { @@ -2075,7 +2236,8 @@ static int connection_counts_as_relayed_traffic(connection_t *conn, time_t now) { if (conn->type == CONN_TYPE_OR && - TO_OR_CONN(conn)->client_used + CLIENT_IDLE_TIME_FOR_PRIORITY < now) + connection_or_client_used(TO_OR_CONN(conn)) + + CLIENT_IDLE_TIME_FOR_PRIORITY < now) return 1; if (conn->type == CONN_TYPE_DIR && DIR_CONN_IS_SERVER(conn)) return 1; @@ -2120,8 +2282,7 @@ connection_bucket_round_robin(int base, int priority, static ssize_t connection_bucket_read_limit(connection_t *conn, time_t now) { - int base = connection_speaks_cells(conn) ? - CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE; + int base = RELAY_PAYLOAD_SIZE; int priority = conn->type != CONN_TYPE_DIR; int conn_bucket = -1; int global_bucket = global_read_bucket; @@ -2130,6 +2291,7 @@ connection_bucket_read_limit(connection_t *conn, time_t now) or_connection_t *or_conn = TO_OR_CONN(conn); if (conn->state == OR_CONN_STATE_OPEN) conn_bucket = or_conn->read_bucket; + base = get_cell_network_size(or_conn->wide_circ_ids); } if (!connection_is_rate_limited(conn)) { @@ -2149,8 +2311,7 @@ connection_bucket_read_limit(connection_t *conn, time_t now) ssize_t connection_bucket_write_limit(connection_t *conn, time_t now) { - int base = connection_speaks_cells(conn) ? - CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE; + int base = RELAY_PAYLOAD_SIZE; int priority = conn->type != CONN_TYPE_DIR; int conn_bucket = (int)conn->outbuf_flushlen; int global_bucket = global_write_bucket; @@ -2168,6 +2329,7 @@ connection_bucket_write_limit(connection_t *conn, time_t now) if (or_conn->write_bucket < conn_bucket) conn_bucket = or_conn->write_bucket >= 0 ? or_conn->write_bucket : 0; + base = get_cell_network_size(or_conn->wide_circ_ids); } if (connection_counts_as_relayed_traffic(conn, now) && @@ -2358,6 +2520,9 @@ connection_consider_empty_read_buckets(connection_t *conn) } else return; /* all good, no need to stop it */ + if (conn->type == CONN_TYPE_CPUWORKER) + return; /* Always okay. */ + LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "%s", reason)); conn->read_blocked_on_bw = 1; connection_stop_reading(conn); @@ -2382,6 +2547,9 @@ connection_consider_empty_write_buckets(connection_t *conn) } else return; /* all good, no need to stop it */ + if (conn->type == CONN_TYPE_CPUWORKER) + return; /* Always okay. */ + LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "%s", reason)); conn->write_blocked_on_bw = 1; connection_stop_writing(conn); @@ -2429,7 +2597,7 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst, *bucket = burst; } } - log(LOG_DEBUG, LD_NET,"%s now %d.", name, *bucket); + log_debug(LD_NET,"%s now %d.", name, *bucket); } } @@ -2534,7 +2702,7 @@ connection_bucket_should_increase(int bucket, or_connection_t *conn) { tor_assert(conn); - if (conn->_base.state != OR_CONN_STATE_OPEN) + if (conn->base_.state != OR_CONN_STATE_OPEN) return 0; /* only open connections play the rate limiting game */ if (bucket >= conn->bandwidthburst) return 0; @@ -2672,11 +2840,14 @@ connection_handle_read_impl(connection_t *conn) before = buf_datalen(conn->inbuf); if (connection_read_to_buf(conn, &max_to_read, &socket_error) < 0) { /* There's a read error; kill the connection.*/ - if (conn->type == CONN_TYPE_OR && - conn->state == OR_CONN_STATE_CONNECTING) { - connection_or_connect_failed(TO_OR_CONN(conn), - errno_to_orconn_end_reason(socket_error), - tor_socket_strerror(socket_error)); + if (conn->type == CONN_TYPE_OR) { + connection_or_notify_error(TO_OR_CONN(conn), + socket_error != 0 ? + errno_to_orconn_end_reason(socket_error) : + END_OR_CONN_REASON_CONNRESET, + socket_error != 0 ? + tor_socket_strerror(socket_error) : + "(unknown, errno was 0)"); } if (CONN_IS_EDGE(conn)) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); @@ -2687,7 +2858,11 @@ connection_handle_read_impl(connection_t *conn) } } connection_close_immediate(conn); /* Don't flush; connection is dead. */ - connection_mark_for_close(conn); + /* + * This can bypass normal channel checking since we did + * connection_or_notify_error() above. + */ + connection_mark_for_close_internal(conn); return -1; } n_read += buf_datalen(conn->inbuf) - before; @@ -3181,6 +3356,7 @@ connection_handle_write_impl(connection_t *conn, int force) ssize_t max_to_write; time_t now = approx_time(); size_t n_read = 0, n_written = 0; + int dont_stop_writing = 0; tor_assert(!connection_is_listener(conn)); @@ -3211,12 +3387,16 @@ connection_handle_write_impl(connection_t *conn, int force) if (CONN_IS_EDGE(conn)) connection_edge_end_errno(TO_EDGE_CONN(conn)); if (conn->type == CONN_TYPE_OR) - connection_or_connect_failed(TO_OR_CONN(conn), - errno_to_orconn_end_reason(e), - tor_socket_strerror(e)); + connection_or_notify_error(TO_OR_CONN(conn), + errno_to_orconn_end_reason(e), + tor_socket_strerror(e)); connection_close_immediate(conn); - connection_mark_for_close(conn); + /* + * This can bypass normal channel checking since we did + * connection_or_notify_error() above. + */ + connection_mark_for_close_internal(conn); return -1; } else { return 0; /* no change, see if next time is better */ @@ -3233,13 +3413,22 @@ connection_handle_write_impl(connection_t *conn, int force) if (connection_speaks_cells(conn) && conn->state > OR_CONN_STATE_PROXY_HANDSHAKING) { or_connection_t *or_conn = TO_OR_CONN(conn); + size_t initial_size; if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING || conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) { connection_stop_writing(conn); if (connection_tls_continue_handshake(or_conn) < 0) { /* Don't flush; connection is dead. */ + connection_or_notify_error(or_conn, + END_OR_CONN_REASON_MISC, + "TLS error in connection_tls_" + "continue_handshake()"); connection_close_immediate(conn); - connection_mark_for_close(conn); + /* + * This can bypass normal channel checking since we did + * connection_or_notify_error() above. + */ + connection_mark_for_close_internal(conn); return -1; } return 0; @@ -3248,29 +3437,39 @@ connection_handle_write_impl(connection_t *conn, int force) } /* else open, or closing */ + initial_size = buf_datalen(conn->outbuf); 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 we just flushed the last bytes, tell the channel on the + * or_conn to check if it needs to geoip_change_dirreq_state() */ /* XXXX move this to flushed_some or finished_flushing -NM */ - if (buf_datalen(conn->outbuf) == 0 && conn->dirreq_id) - geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED, - DIRREQ_OR_CONN_BUFFER_FLUSHED); + if (buf_datalen(conn->outbuf) == 0 && or_conn->chan) + channel_notify_flushed(TLS_CHAN_TO_BASE(or_conn->chan)); switch (result) { CASE_TOR_TLS_ERROR_ANY: case TOR_TLS_CLOSE: - log_info(LD_NET,result!=TOR_TLS_CLOSE? + log_info(LD_NET, result != TOR_TLS_CLOSE ? "tls error. breaking.":"TLS connection closed on flush"); /* Don't flush; connection is dead. */ + connection_or_notify_error(or_conn, + END_OR_CONN_REASON_MISC, + result != TOR_TLS_CLOSE ? + "TLS error in during flush" : + "TLS closed during flush"); connection_close_immediate(conn); - connection_mark_for_close(conn); + /* + * This can bypass normal channel checking since we did + * connection_or_notify_error() above. + */ + connection_mark_for_close_internal(conn); return -1; case TOR_TLS_WANTWRITE: log_debug(LD_NET,"wanted write."); /* we're already writing */ - return 0; + dont_stop_writing = 1; + break; case TOR_TLS_WANTREAD: /* Make sure to avoid a loop if the receive buckets are empty. */ log_debug(LD_NET,"wanted read."); @@ -3292,6 +3491,12 @@ connection_handle_write_impl(connection_t *conn, int force) tor_tls_get_n_raw_bytes(or_conn->tls, &n_read, &n_written); log_debug(LD_GENERAL, "After TLS write of %d: %ld read, %ld written", result, (long)n_read, (long)n_written); + /* So we notice bytes were written even on error */ + /* XXXX024 This cast is safe since we can never write INT_MAX bytes in a + * single set of TLS operations. But it looks kinda ugly. If we refactor + * the *_buf_tls functions, we should make them return ssize_t or size_t + * or something. */ + result = (int)(initial_size-buf_datalen(conn->outbuf)); } else { CONN_LOG_PROTECT(conn, result = flush_buf(conn->s, conn->outbuf, @@ -3299,6 +3504,10 @@ connection_handle_write_impl(connection_t *conn, int force) if (result < 0) { if (CONN_IS_EDGE(conn)) connection_edge_end_errno(TO_EDGE_CONN(conn)); + if (conn->type == CONN_TYPE_AP) { + /* writing failed; we couldn't send a SOCKS reply if we wanted to */ + TO_ENTRY_CONN(conn)->socks_request->has_finished = 1; + } connection_close_immediate(conn); /* Don't flush; connection is dead. */ connection_mark_for_close(conn); @@ -3322,11 +3531,24 @@ connection_handle_write_impl(connection_t *conn, int force) if (result > 0) { /* If we wrote any bytes from our buffer, then call the appropriate * functions. */ - if (connection_flushed_some(conn) < 0) - connection_mark_for_close(conn); + if (connection_flushed_some(conn) < 0) { + if (connection_speaks_cells(conn)) { + connection_or_notify_error(TO_OR_CONN(conn), + END_OR_CONN_REASON_MISC, + "Got error back from " + "connection_flushed_some()"); + } + + /* + * This can bypass normal channel checking since we did + * connection_or_notify_error() above. + */ + connection_mark_for_close_internal(conn); + } } - if (!connection_wants_to_flush(conn)) { /* it's done flushing */ + if (!connection_wants_to_flush(conn) && + !dont_stop_writing) { /* it's done flushing */ if (connection_finished_flushing(conn) < 0) { /* already marked */ return -1; @@ -3375,13 +3597,6 @@ connection_flush(connection_t *conn) return connection_handle_write(conn, 1); } -/** OpenSSL TLS record size is 16383; this is close. The goal here is to - * push data out as soon as we know there's enough for a TLS record, so - * during periods of high load we won't read entire megabytes from - * input before pushing any data out. It also has the feature of not - * growing huge outbufs unless something is slow. */ -#define MIN_TLS_FLUSHLEN 15872 - /** Append <b>len</b> bytes of <b>string</b> onto <b>conn</b>'s * outbuf, and ask it to start writing. * @@ -3390,13 +3605,12 @@ connection_flush(connection_t *conn) * negative, this is the last data to be compressed, and the connection's zlib * state should be flushed. * - * If it's an OR conn and an entire TLS record is ready, then try to - * flush the record now. Similarly, if it's a local control connection - * and a 64k chunk is ready, try to flush it all, so we don't end up with - * many megabytes of controller info queued at once. + * If it's a local control connection and a 64k chunk is ready, try to flush + * it all, so we don't end up with many megabytes of controller info queued at + * once. */ void -_connection_write_to_buf_impl(const char *string, size_t len, +connection_write_to_buf_impl_(const char *string, size_t len, connection_t *conn, int zlib) { /* XXXX This function really needs to return -1 on failure. */ @@ -3461,7 +3675,6 @@ _connection_write_to_buf_impl(const char *string, size_t len, if (zlib) { conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen; } else { - ssize_t extra = 0; conn->outbuf_flushlen += len; /* Should we try flushing the outbuf now? */ @@ -3471,14 +3684,7 @@ _connection_write_to_buf_impl(const char *string, size_t len, return; } - if (conn->type == CONN_TYPE_OR && - conn->outbuf_flushlen-len < MIN_TLS_FLUSHLEN && - conn->outbuf_flushlen >= MIN_TLS_FLUSHLEN) { - /* We just pushed outbuf_flushlen to MIN_TLS_FLUSHLEN or above; - * we can send out a full TLS frame now if we like. */ - extra = conn->outbuf_flushlen - MIN_TLS_FLUSHLEN; - conn->outbuf_flushlen = MIN_TLS_FLUSHLEN; - } else if (conn->type == CONN_TYPE_CONTROL && + if (conn->type == CONN_TYPE_CONTROL && !connection_is_rate_limited(conn) && conn->outbuf_flushlen-len < 1<<16 && conn->outbuf_flushlen >= 1<<16) { @@ -3498,10 +3704,6 @@ _connection_write_to_buf_impl(const char *string, size_t len, } return; } - if (extra) { - conn->outbuf_flushlen += extra; - connection_start_writing(conn); - } } } @@ -3792,7 +3994,7 @@ client_check_address_changed(tor_socket_t sock) } else { /* The interface changed. We're a client, so we need to regenerate our * keys. First, reset the state. */ - log(LOG_NOTICE, LD_NET, "Our IP address has changed. Rotating keys..."); + log_notice(LD_NET, "Our IP address has changed. Rotating keys..."); tor_addr_copy(*last_interface_ip_ptr, &iface_addr); SMARTLIST_FOREACH(outgoing_addrs, tor_addr_t*, a_ptr, tor_free(a_ptr)); smartlist_clear(outgoing_addrs); @@ -3876,8 +4078,9 @@ connection_flushed_some(connection_t *conn) return r; } -/** We just finished flushing bytes from conn-\>outbuf, and there - * are no more bytes remaining. +/** We just finished flushing bytes to the appropriately low network layer, + * and there are no more bytes remaining in conn-\>outbuf, conn-\>bev, or + * conn-\>tls to be flushed. * * This function just passes conn to the connection-specific * connection_*_finished_flushing() function. @@ -3975,9 +4178,9 @@ connection_reached_eof(connection_t *conn) void connection_dump_buffer_mem_stats(int severity) { - uint64_t used_by_type[_CONN_TYPE_MAX+1]; - uint64_t alloc_by_type[_CONN_TYPE_MAX+1]; - int n_conns_by_type[_CONN_TYPE_MAX+1]; + uint64_t used_by_type[CONN_TYPE_MAX_+1]; + uint64_t alloc_by_type[CONN_TYPE_MAX_+1]; + int n_conns_by_type[CONN_TYPE_MAX_+1]; uint64_t total_alloc = 0; uint64_t total_used = 0; int i; @@ -3999,19 +4202,19 @@ connection_dump_buffer_mem_stats(int severity) alloc_by_type[tp] += buf_allocation(c->outbuf); } } SMARTLIST_FOREACH_END(c); - for (i=0; i <= _CONN_TYPE_MAX; ++i) { + for (i=0; i <= CONN_TYPE_MAX_; ++i) { total_used += used_by_type[i]; total_alloc += alloc_by_type[i]; } - log(severity, LD_GENERAL, + tor_log(severity, LD_GENERAL, "In buffers for %d connections: "U64_FORMAT" used/"U64_FORMAT" allocated", smartlist_len(conns), U64_PRINTF_ARG(total_used), U64_PRINTF_ARG(total_alloc)); - for (i=_CONN_TYPE_MIN; i <= _CONN_TYPE_MAX; ++i) { + for (i=CONN_TYPE_MIN_; i <= CONN_TYPE_MAX_; ++i) { if (!n_conns_by_type[i]) continue; - log(severity, LD_GENERAL, + tor_log(severity, LD_GENERAL, " For %d %s connections: "U64_FORMAT" used/"U64_FORMAT" allocated", n_conns_by_type[i], conn_type_to_string(i), U64_PRINTF_ARG(used_by_type[i]), U64_PRINTF_ARG(alloc_by_type[i])); @@ -4026,8 +4229,8 @@ assert_connection_ok(connection_t *conn, time_t now) { (void) now; /* XXXX unused. */ tor_assert(conn); - tor_assert(conn->type >= _CONN_TYPE_MIN); - tor_assert(conn->type <= _CONN_TYPE_MAX); + tor_assert(conn->type >= CONN_TYPE_MIN_); + tor_assert(conn->type <= CONN_TYPE_MAX_); #ifdef USE_BUFFEREVENTS if (conn->bufev) { @@ -4142,34 +4345,33 @@ assert_connection_ok(connection_t *conn, time_t now) tor_assert(conn->state == LISTENER_STATE_READY); break; case CONN_TYPE_OR: - tor_assert(conn->state >= _OR_CONN_STATE_MIN); - tor_assert(conn->state <= _OR_CONN_STATE_MAX); - tor_assert(TO_OR_CONN(conn)->n_circuits >= 0); + tor_assert(conn->state >= OR_CONN_STATE_MIN_); + tor_assert(conn->state <= OR_CONN_STATE_MAX_); break; case CONN_TYPE_EXIT: - tor_assert(conn->state >= _EXIT_CONN_STATE_MIN); - tor_assert(conn->state <= _EXIT_CONN_STATE_MAX); - tor_assert(conn->purpose >= _EXIT_PURPOSE_MIN); - tor_assert(conn->purpose <= _EXIT_PURPOSE_MAX); + tor_assert(conn->state >= EXIT_CONN_STATE_MIN_); + tor_assert(conn->state <= EXIT_CONN_STATE_MAX_); + tor_assert(conn->purpose >= EXIT_PURPOSE_MIN_); + tor_assert(conn->purpose <= EXIT_PURPOSE_MAX_); break; case CONN_TYPE_AP: - tor_assert(conn->state >= _AP_CONN_STATE_MIN); - tor_assert(conn->state <= _AP_CONN_STATE_MAX); + tor_assert(conn->state >= AP_CONN_STATE_MIN_); + tor_assert(conn->state <= AP_CONN_STATE_MAX_); tor_assert(TO_ENTRY_CONN(conn)->socks_request); break; case CONN_TYPE_DIR: - tor_assert(conn->state >= _DIR_CONN_STATE_MIN); - tor_assert(conn->state <= _DIR_CONN_STATE_MAX); - tor_assert(conn->purpose >= _DIR_PURPOSE_MIN); - tor_assert(conn->purpose <= _DIR_PURPOSE_MAX); + tor_assert(conn->state >= DIR_CONN_STATE_MIN_); + tor_assert(conn->state <= DIR_CONN_STATE_MAX_); + tor_assert(conn->purpose >= DIR_PURPOSE_MIN_); + tor_assert(conn->purpose <= DIR_PURPOSE_MAX_); break; case CONN_TYPE_CPUWORKER: - tor_assert(conn->state >= _CPUWORKER_STATE_MIN); - tor_assert(conn->state <= _CPUWORKER_STATE_MAX); + tor_assert(conn->state >= CPUWORKER_STATE_MIN_); + tor_assert(conn->state <= CPUWORKER_STATE_MAX_); break; case CONN_TYPE_CONTROL: - tor_assert(conn->state >= _CONTROL_CONN_STATE_MIN); - tor_assert(conn->state <= _CONTROL_CONN_STATE_MAX); + tor_assert(conn->state >= CONTROL_CONN_STATE_MIN_); + tor_assert(conn->state <= CONTROL_CONN_STATE_MAX_); break; default: tor_assert(0); @@ -4253,10 +4455,10 @@ log_failed_proxy_connection(connection_t *conn) return; /* if we have no proxy set up, leave this function. */ log_warn(LD_NET, - "The connection to the %s proxy server at %s:%u just failed. " + "The connection to the %s proxy server at %s just failed. " "Make sure that the proxy server is up and running.", - proxy_type_to_string(get_proxy_type()), fmt_addr(&proxy_addr), - proxy_port); + proxy_type_to_string(get_proxy_type()), + fmt_addrport(&proxy_addr, proxy_port)); } /** Return string representation of <b>proxy_type</b>. */ @@ -4274,7 +4476,7 @@ proxy_type_to_string(int proxy_type) return NULL; /*Unreached*/ } -/** Call _connection_free() on every connection in our array, and release all +/** Call connection_free_() on every connection in our array, and release all * storage held by connection.c. This is used by cpuworkers and dnsworkers * when they fork, so they don't keep resources held open (especially * sockets). @@ -4300,7 +4502,7 @@ connection_free_all(void) /* Clear out our list of broken connections */ clear_broken_connection_map(0); - SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn)); + SMARTLIST_FOREACH(conns, connection_t *, conn, connection_free_(conn)); if (outgoing_addrs) { SMARTLIST_FOREACH(outgoing_addrs, tor_addr_t *, addr, tor_free(addr)); @@ -4308,6 +4510,9 @@ connection_free_all(void) outgoing_addrs = NULL; } + tor_free(last_interface_ipv4); + tor_free(last_interface_ipv6); + #ifdef USE_BUFFEREVENTS if (global_rate_limit) bufferevent_rate_limit_group_free(global_rate_limit); diff --git a/src/or/connection.h b/src/or/connection.h index 785625e44b..c78fe6e652 100644 --- a/src/or/connection.h +++ b/src/or/connection.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for connection.c. **/ -#ifndef _TOR_CONNECTION_H -#define _TOR_CONNECTION_H +#ifndef TOR_CONNECTION_H +#define TOR_CONNECTION_H /* XXXX For buf_datalen in inline function */ #include "buffers.h" @@ -31,25 +31,57 @@ 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); +void connection_mark_for_close_(connection_t *conn, + int line, const char *file); +void connection_mark_for_close_internal_(connection_t *conn, + int line, const char *file); #define connection_mark_for_close(c) \ - _connection_mark_for_close((c), __LINE__, _SHORT_FILE_) + connection_mark_for_close_((c), __LINE__, SHORT_FILE__) +#define connection_mark_for_close_internal(c) \ + connection_mark_for_close_internal_((c), __LINE__, SHORT_FILE__) /** * Mark 'c' for close, but try to hold it open until all the data is written. + * Use the _internal versions of connection_mark_for_close; this should be + * called when you either are sure that if this is an or_connection_t the + * controlling channel has been notified (e.g. with + * connection_or_notify_error()), or you actually are the + * connection_or_close_for_error() or connection_or_close_normally function. + * For all other cases, use connection_mark_and_flush() instead, which + * checks for or_connection_t properly, instead. See below. */ -#define _connection_mark_and_flush(c,line,file) \ - do { \ - connection_t *tmp_conn_ = (c); \ - _connection_mark_for_close(tmp_conn_, (line), (file)); \ - tmp_conn_->hold_open_until_flushed = 1; \ - IF_HAS_BUFFEREVENT(tmp_conn_, \ - connection_start_writing(tmp_conn_)); \ +#define connection_mark_and_flush_internal_(c,line,file) \ + do { \ + connection_t *tmp_conn_ = (c); \ + connection_mark_for_close_internal_(tmp_conn_, (line), (file)); \ + tmp_conn_->hold_open_until_flushed = 1; \ + IF_HAS_BUFFEREVENT(tmp_conn_, \ + connection_start_writing(tmp_conn_)); \ + } while (0) + +#define connection_mark_and_flush_internal(c) \ + connection_mark_and_flush_internal_((c), __LINE__, SHORT_FILE__) + +/** + * Mark 'c' for close, but try to hold it open until all the data is written. + */ +#define connection_mark_and_flush_(c,line,file) \ + do { \ + connection_t *tmp_conn_ = (c); \ + if (tmp_conn_->type == CONN_TYPE_OR) { \ + log_warn(LD_CHANNEL | LD_BUG, \ + "Something tried to close (and flush) an or_connection_t" \ + " without going through channels at %s:%d", \ + file, line); \ + connection_or_close_for_error(TO_OR_CONN(tmp_conn_), 1); \ + } else { \ + connection_mark_and_flush_internal_(c, line, file); \ + } \ } while (0) #define connection_mark_and_flush(c) \ - _connection_mark_and_flush((c), __LINE__, _SHORT_FILE_) + connection_mark_and_flush_((c), __LINE__, SHORT_FILE__) void connection_expire_held_open(void); @@ -90,7 +122,7 @@ int connection_outbuf_too_full(connection_t *conn); int connection_handle_write(connection_t *conn, int force); int connection_flush(connection_t *conn); -void _connection_write_to_buf_impl(const char *string, size_t len, +void connection_write_to_buf_impl_(const char *string, size_t len, connection_t *conn, int zlib); /* DOCDOC connection_write_to_buf */ static void connection_write_to_buf(const char *string, size_t len, @@ -101,13 +133,13 @@ static void connection_write_to_buf_zlib(const char *string, size_t len, 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); + 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_write_to_buf_impl_(string, len, TO_CONN(conn), done ? -1 : 1); } /* DOCDOC connection_get_inbuf_len */ diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 362ad9af95..895c0f7f01 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1,16 +1,19 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** * \file connection_edge.c * \brief Handle edge streams. **/ +#define CONNECTION_EDGE_PRIVATE #include "or.h" +#include "addressmap.h" #include "buffers.h" +#include "channel.h" #include "circuitlist.h" #include "circuituse.h" #include "config.h" @@ -33,6 +36,8 @@ #include "rephist.h" #include "router.h" #include "routerlist.h" +#include "routerset.h" +#include "circuitbuild.h" #ifdef HAVE_LINUX_TYPES_H #include <linux/types.h> @@ -54,17 +59,20 @@ static int connection_ap_handshake_process_socks(entry_connection_t *conn); static int connection_ap_process_natd(entry_connection_t *conn); static int connection_exit_connect_dir(edge_connection_t *exitconn); -static int address_is_in_virtual_range(const char *addr); static int consider_plaintext_ports(entry_connection_t *conn, uint16_t port); -static void clear_trackexithost_mappings(const char *exitname); static int connection_ap_supports_optimistic_data(const entry_connection_t *); +static void connection_ap_handshake_socks_resolved_addr( + entry_connection_t *conn, + const tor_addr_t *answer, + int ttl, + time_t expires); /** An AP stream has failed/finished. If it hasn't already sent back * a socks reply, send one now (based on endreason). Also set * has_sent_end to 1, and mark the conn. */ void -_connection_mark_unattached_ap(entry_connection_t *conn, int endreason, +connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, int line, const char *file) { connection_t *base_conn = ENTRY_TO_CONN(conn); @@ -87,7 +95,7 @@ _connection_mark_unattached_ap(entry_connection_t *conn, int endreason, if (base_conn->marked_for_close) { /* This call will warn as appropriate. */ - _connection_mark_for_close(base_conn, line, file); + connection_mark_for_close_(base_conn, line, file); return; } @@ -107,7 +115,7 @@ _connection_mark_unattached_ap(entry_connection_t *conn, int endreason, conn->socks_request->has_finished = 1; } - _connection_mark_and_flush(base_conn, line, file); + connection_mark_and_flush_(base_conn, line, file); ENTRY_TO_EDGE_CONN(conn)->end_reason = endreason; } @@ -122,12 +130,13 @@ connection_edge_reached_eof(edge_connection_t *conn) /* it still has stuff to process. don't let it die yet. */ return 0; } - log_info(LD_EDGE,"conn (fd %d) reached eof. Closing.", conn->_base.s); - if (!conn->_base.marked_for_close) { + log_info(LD_EDGE,"conn (fd "TOR_SOCKET_T_FORMAT") reached eof. Closing.", + conn->base_.s); + if (!conn->base_.marked_for_close) { /* only mark it if not already marked. it's possible to * get the 'end' right around when the client hangs up on us. */ connection_edge_end(conn, END_STREAM_REASON_DONE); - if (conn->_base.type == CONN_TYPE_AP) { + if (conn->base_.type == CONN_TYPE_AP) { /* eof, so don't send a socks reply back */ if (EDGE_TO_ENTRY_CONN(conn)->socks_request) EDGE_TO_ENTRY_CONN(conn)->socks_request->has_finished = 1; @@ -152,7 +161,7 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) { tor_assert(conn); - switch (conn->_base.state) { + switch (conn->base_.state) { case AP_CONN_STATE_SOCKS_WAIT: if (connection_ap_handshake_process_socks(EDGE_TO_ENTRY_CONN(conn)) <0) { /* already marked */ @@ -178,7 +187,7 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) log_info(LD_EDGE, "data from edge while in '%s' state. Sending it anyway. " "package_partial=%d, buflen=%ld", - conn_state_to_string(conn->_base.type, conn->_base.state), + conn_state_to_string(conn->base_.type, conn->base_.state), package_partial, (long)connection_get_inbuf_len(TO_CONN(conn))); if (connection_edge_package_raw_inbuf(conn, package_partial, NULL)<0) { @@ -197,10 +206,10 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) case AP_CONN_STATE_CONTROLLER_WAIT: log_info(LD_EDGE, "data from edge while in '%s' state. Leaving it on buffer.", - conn_state_to_string(conn->_base.type, conn->_base.state)); + conn_state_to_string(conn->base_.type, conn->base_.state)); return 0; } - log_warn(LD_BUG,"Got unexpected state %d. Closing.",conn->_base.state); + log_warn(LD_BUG,"Got unexpected state %d. Closing.",conn->base_.state); tor_fragile_assert(); connection_edge_end(conn, END_STREAM_REASON_INTERNAL); connection_mark_for_close(TO_CONN(conn)); @@ -213,10 +222,10 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn) { - if (!conn->_base.marked_for_close) { - log_info(LD_EDGE, - "CircID %d: At an edge. Marking connection for close.", circ_id); - if (conn->_base.type == CONN_TYPE_AP) { + if (!conn->base_.marked_for_close) { + log_info(LD_EDGE, "CircID %u: At an edge. Marking connection for close.", + (unsigned) circ_id); + if (conn->base_.type == CONN_TYPE_AP) { entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DESTROY); control_event_stream_bandwidth(conn); @@ -280,10 +289,10 @@ connection_edge_end(edge_connection_t *conn, uint8_t reason) return -1; } - if (conn->_base.marked_for_close) { + if (conn->base_.marked_for_close) { log_warn(LD_BUG, "called on conn that's already marked for close at %s:%d.", - conn->_base.marked_for_close_file, conn->_base.marked_for_close); + conn->base_.marked_for_close_file, conn->base_.marked_for_close); return 0; } @@ -299,11 +308,11 @@ connection_edge_end(edge_connection_t *conn, uint8_t reason) if (reason == END_STREAM_REASON_EXITPOLICY && !connection_edge_is_rendezvous_stream(conn)) { int addrlen; - if (tor_addr_family(&conn->_base.addr) == AF_INET) { - set_uint32(payload+1, tor_addr_to_ipv4n(&conn->_base.addr)); + if (tor_addr_family(&conn->base_.addr) == AF_INET) { + set_uint32(payload+1, tor_addr_to_ipv4n(&conn->base_.addr)); addrlen = 4; } else { - memcpy(payload+1, tor_addr_to_in6_addr8(&conn->_base.addr), 16); + memcpy(payload+1, tor_addr_to_in6_addr8(&conn->base_.addr), 16); addrlen = 16; } set_uint32(payload+1+addrlen, htonl(dns_clip_ttl(conn->address_ttl))); @@ -311,12 +320,14 @@ connection_edge_end(edge_connection_t *conn, uint8_t reason) } if (circ && !circ->marked_for_close) { - log_debug(LD_EDGE,"Sending end on conn (fd %d).",conn->_base.s); + log_debug(LD_EDGE,"Sending end on conn (fd "TOR_SOCKET_T_FORMAT").", + conn->base_.s); connection_edge_send_command(conn, RELAY_COMMAND_END, payload, payload_len); } else { - log_debug(LD_EDGE,"No circ to send end on conn (fd %d).", - conn->_base.s); + log_debug(LD_EDGE,"No circ to send end on conn " + "(fd "TOR_SOCKET_T_FORMAT").", + conn->base_.s); } conn->edge_has_sent_end = 1; @@ -333,7 +344,7 @@ connection_edge_end_errno(edge_connection_t *conn) { uint8_t reason; tor_assert(conn); - reason = errno_to_stream_end_reason(tor_socket_errno(conn->_base.s)); + reason = errno_to_stream_end_reason(tor_socket_errno(conn->base_.s)); return connection_edge_end(conn, reason); } @@ -345,7 +356,7 @@ connection_edge_end_errno(edge_connection_t *conn) int connection_edge_flushed_some(edge_connection_t *conn) { - switch (conn->_base.state) { + switch (conn->base_.state) { case AP_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN: connection_edge_consider_sending_sendme(conn); @@ -369,7 +380,7 @@ connection_edge_finished_flushing(edge_connection_t *conn) { tor_assert(conn); - switch (conn->_base.state) { + switch (conn->base_.state) { case AP_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN: connection_edge_consider_sending_sendme(conn); @@ -383,13 +394,55 @@ connection_edge_finished_flushing(edge_connection_t *conn) case AP_CONN_STATE_RESOLVE_WAIT: return 0; default: - log_warn(LD_BUG, "Called in unexpected state %d.",conn->_base.state); + log_warn(LD_BUG, "Called in unexpected state %d.",conn->base_.state); tor_fragile_assert(); return -1; } return 0; } +/** Longest size for the relay payload of a RELAY_CONNECTED cell that we're + * able to generate. */ +/* 4 zero bytes; 1 type byte; 16 byte IPv6 address; 4 byte TTL. */ +#define MAX_CONNECTED_CELL_PAYLOAD_LEN 25 + +/** Set the buffer at <b>payload_out</b> -- which must have at least + * MAX_CONNECTED_CELL_PAYLOAD_LEN bytes available -- to the body of a + * RELAY_CONNECTED cell indicating that we have connected to <b>addr</b>, and + * that the name resolution that led us to <b>addr</b> will be valid for + * <b>ttl</b> seconds. Return -1 on error, or the number of bytes used on + * success. */ +/* private */int +connected_cell_format_payload(uint8_t *payload_out, + const tor_addr_t *addr, + uint32_t ttl) +{ + const sa_family_t family = tor_addr_family(addr); + int connected_payload_len; + + /* should be needless */ + memset(payload_out, 0, MAX_CONNECTED_CELL_PAYLOAD_LEN); + + if (family == AF_INET) { + set_uint32(payload_out, tor_addr_to_ipv4n(addr)); + connected_payload_len = 4; + } else if (family == AF_INET6) { + set_uint32(payload_out, 0); + set_uint8(payload_out + 4, 6); + memcpy(payload_out + 5, tor_addr_to_in6_addr8(addr), 16); + connected_payload_len = 21; + } else { + return -1; + } + + set_uint32(payload_out + connected_payload_len, htonl(dns_clip_ttl(ttl))); + connected_payload_len += 4; + + tor_assert(connected_payload_len <= MAX_CONNECTED_CELL_PAYLOAD_LEN); + + return connected_payload_len; +} + /** Connected handler for exit connections: start writing pending * data, deliver 'CONNECTED' relay cells as appropriate, and check * any pending data that may have been received. */ @@ -399,13 +452,13 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) connection_t *conn; tor_assert(edge_conn); - tor_assert(edge_conn->_base.type == CONN_TYPE_EXIT); + tor_assert(edge_conn->base_.type == CONN_TYPE_EXIT); conn = TO_CONN(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, - safe_str(fmt_addr(&conn->addr))); + safe_str(fmt_and_decorate_addr(&conn->addr))); rep_hist_note_exit_stream_opened(conn->port); @@ -421,22 +474,16 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) RELAY_COMMAND_CONNECTED, NULL, 0) < 0) return 0; /* circuit is closed, don't continue */ } else { - char connected_payload[20]; - int connected_payload_len; - if (tor_addr_family(&conn->addr) == AF_INET) { - set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr)); - set_uint32(connected_payload+4, - htonl(dns_clip_ttl(edge_conn->address_ttl))); - connected_payload_len = 8; - } else { - memcpy(connected_payload, tor_addr_to_in6_addr8(&conn->addr), 16); - set_uint32(connected_payload+16, - htonl(dns_clip_ttl(edge_conn->address_ttl))); - connected_payload_len = 20; - } + uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN]; + int connected_payload_len = + connected_cell_format_payload(connected_payload, &conn->addr, + edge_conn->address_ttl); + if (connected_payload_len < 0) + return -1; + if (connection_edge_send_command(edge_conn, - RELAY_COMMAND_CONNECTED, - connected_payload, connected_payload_len) < 0) + RELAY_COMMAND_CONNECTED, + (char*)connected_payload, connected_payload_len) < 0) return 0; /* circuit is closed, don't continue */ } tor_assert(edge_conn->package_window > 0); @@ -600,12 +647,27 @@ connection_ap_expire_beginning(void) " '%s.onion'.", seconds_idle, safe_str_client(entry_conn->socks_request->address)); + /* Roll back path bias use state so that we probe the circuit + * if nothing else succeeds on it */ + pathbias_mark_use_rollback(TO_ORIGIN_CIRCUIT(circ)); + connection_edge_end(conn, END_STREAM_REASON_TIMEOUT); connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT); } continue; } - tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL); + if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL && + circ->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT && + circ->purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) { + log_warn(LD_BUG, "circuit->purpose == CIRCUIT_PURPOSE_C_GENERAL failed. " + "The purpose on the circuit was %s; it was in state %s, " + "path_state %s.", + circuit_purpose_to_string(circ->purpose), + circuit_state_to_string(circ->state), + CIRCUIT_IS_ORIGIN(circ) ? + pathbias_state_to_string(TO_ORIGIN_CIRCUIT(circ)->path_state) : + "none"); + } 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.", @@ -619,14 +681,12 @@ connection_ap_expire_beginning(void) /* un-mark it as ending, since we're going to reuse it */ conn->edge_has_sent_end = 0; conn->end_reason = 0; - /* kludge to make us not try this circuit again, yet to allow - * current streams on it to survive if they can: make it - * unattractive to use for new streams */ - /* XXXX024 this is a kludgy way to do this. */ - tor_assert(circ->timestamp_dirty); - circ->timestamp_dirty -= options->MaxCircuitDirtiness; + /* make us not try this circuit again, but allow + * current streams on it to survive if they can */ + mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ)); + /* give our stream another 'cutoff' seconds to try */ - conn->_base.timestamp_lastread += cutoff; + conn->base_.timestamp_lastread += cutoff; if (entry_conn->num_socks_retries < 250) /* avoid overflow */ entry_conn->num_socks_retries++; /* move it back into 'pending' state, and try to attach. */ @@ -752,7 +812,7 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info) /** The AP connection <b>conn</b> has just failed while attaching or * sending a BEGIN or resolving on <b>circ</b>, but another circuit * might work. Detach the circuit, and either reattach it, launch a - * new circuit, tell the controller, or give up as a appropriate. + * new circuit, tell the controller, or give up as appropriate. * * Returns -1 on err, 1 on success, 0 on not-yet-sure. */ @@ -764,6 +824,10 @@ connection_ap_detach_retriable(entry_connection_t *conn, control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE, reason); ENTRY_TO_CONN(conn)->timestamp_lastread = time(NULL); + /* Roll back path bias use state so that we probe the circuit + * if nothing else succeeds on it */ + pathbias_mark_use_rollback(circ); + if (conn->pending_optimistic_data) { generic_buffer_set_to_copy(&conn->sending_optimistic_data, conn->pending_optimistic_data); @@ -782,957 +846,16 @@ connection_ap_detach_retriable(entry_connection_t *conn, } } -/** A client-side struct to remember requests to rewrite addresses - * to new addresses. These structs are stored in the hash table - * "addressmap" below. - * - * There are 5 ways to set an address mapping: - * - A MapAddress command from the controller [permanent] - * - An AddressMap directive in the torrc [permanent] - * - When a TrackHostExits torrc directive is triggered [temporary] - * - When a DNS resolve succeeds [temporary] - * - When a DNS resolve fails [temporary] - * - * When an addressmap request is made but one is already registered, - * the new one is replaced only if the currently registered one has - * no "new_address" (that is, it's in the process of DNS resolve), - * or if the new one is permanent (expires==0 or 1). - * - * (We overload the 'expires' field, using "0" for mappings set via - * the configuration file, "1" for mappings set from the control - * interface, and other values for DNS and TrackHostExit mappings that can - * expire.) - * - * A mapping may be 'wildcarded'. If "src_wildcard" is true, then - * any address that ends with a . followed by the key for this entry will - * get remapped by it. If "dst_wildcard" is also true, then only the - * matching suffix of such addresses will get replaced by new_address. - */ -typedef struct { - char *new_address; - time_t expires; - addressmap_entry_source_t source:3; - unsigned src_wildcard:1; - unsigned dst_wildcard:1; - short num_resolve_failures; -} addressmap_entry_t; - -/** Entry for mapping addresses to which virtual address we mapped them to. */ -typedef struct { - char *ipv4_address; - char *hostname_address; -} virtaddress_entry_t; - -/** A hash table to store client-side address rewrite instructions. */ -static strmap_t *addressmap=NULL; -/** - * Table mapping addresses to which virtual address, if any, we - * assigned them to. - * - * We maintain the following invariant: if [A,B] is in - * virtaddress_reversemap, then B must be a virtual address, and [A,B] - * must be in addressmap. We do not require that the converse hold: - * if it fails, then we could end up mapping two virtual addresses to - * the same address, which is no disaster. - **/ -static strmap_t *virtaddress_reversemap=NULL; - -/** Initialize addressmap. */ -void -addressmap_init(void) -{ - addressmap = strmap_new(); - virtaddress_reversemap = strmap_new(); -} - -/** Free the memory associated with the addressmap entry <b>_ent</b>. */ -static void -addressmap_ent_free(void *_ent) -{ - addressmap_entry_t *ent; - if (!_ent) - return; - - ent = _ent; - tor_free(ent->new_address); - tor_free(ent); -} - -/** Free storage held by a virtaddress_entry_t* entry in <b>ent</b>. */ -static void -addressmap_virtaddress_ent_free(void *_ent) -{ - virtaddress_entry_t *ent; - if (!_ent) - return; - - ent = _ent; - tor_free(ent->ipv4_address); - tor_free(ent->hostname_address); - tor_free(ent); -} - -/** Free storage held by a virtaddress_entry_t* entry in <b>ent</b>. */ -static void -addressmap_virtaddress_remove(const char *address, addressmap_entry_t *ent) -{ - if (ent && ent->new_address && - address_is_in_virtual_range(ent->new_address)) { - virtaddress_entry_t *ve = - strmap_get(virtaddress_reversemap, ent->new_address); - /*log_fn(LOG_NOTICE,"remove reverse mapping for %s",ent->new_address);*/ - if (ve) { - if (!strcmp(address, ve->ipv4_address)) - tor_free(ve->ipv4_address); - if (!strcmp(address, ve->hostname_address)) - tor_free(ve->hostname_address); - if (!ve->ipv4_address && !ve->hostname_address) { - tor_free(ve); - strmap_remove(virtaddress_reversemap, ent->new_address); - } - } - } -} - -/** Remove <b>ent</b> (which must be mapped to by <b>address</b>) from the - * client address maps. */ -static void -addressmap_ent_remove(const char *address, addressmap_entry_t *ent) -{ - addressmap_virtaddress_remove(address, ent); - addressmap_ent_free(ent); -} - -/** Unregister all TrackHostExits mappings from any address to - * *.exitname.exit. */ -static void -clear_trackexithost_mappings(const char *exitname) -{ - char *suffix = NULL; - if (!addressmap || !exitname) - return; - tor_asprintf(&suffix, ".%s.exit", exitname); - tor_strlower(suffix); - - STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) { - if (ent->source == ADDRMAPSRC_TRACKEXIT && - !strcmpend(ent->new_address, suffix)) { - addressmap_ent_remove(address, ent); - MAP_DEL_CURRENT(address); - } - } STRMAP_FOREACH_END; - - tor_free(suffix); -} - -/** Remove all TRACKEXIT mappings from the addressmap for which the target - * host is unknown or no longer allowed, or for which the source address - * is no longer in trackexithosts. */ -void -addressmap_clear_excluded_trackexithosts(const or_options_t *options) -{ - const routerset_t *allow_nodes = options->ExitNodes; - const routerset_t *exclude_nodes = options->_ExcludeExitNodesUnion; - - if (!addressmap) - return; - if (routerset_is_empty(allow_nodes)) - allow_nodes = NULL; - if (allow_nodes == NULL && routerset_is_empty(exclude_nodes)) - return; - - STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) { - size_t len; - const char *target = ent->new_address, *dot; - char *nodename; - const node_t *node; - - if (!target) { - /* DNS resolving in progress */ - continue; - } else if (strcmpend(target, ".exit")) { - /* Not a .exit mapping */ - continue; - } else if (ent->source != ADDRMAPSRC_TRACKEXIT) { - /* Not a trackexit mapping. */ - continue; - } - len = strlen(target); - if (len < 6) - continue; /* malformed. */ - dot = target + len - 6; /* dot now points to just before .exit */ - while (dot > target && *dot != '.') - dot--; - if (*dot == '.') dot++; - nodename = tor_strndup(dot, len-5-(dot-target));; - node = node_get_by_nickname(nodename, 0); - tor_free(nodename); - if (!node || - (allow_nodes && !routerset_contains_node(allow_nodes, node)) || - routerset_contains_node(exclude_nodes, node) || - !hostname_in_track_host_exits(options, address)) { - /* We don't know this one, or we want to be rid of it. */ - addressmap_ent_remove(address, ent); - MAP_DEL_CURRENT(address); - } - } STRMAP_FOREACH_END; -} - -/** Remove all AUTOMAP mappings from the addressmap for which the - * source address no longer matches AutomapHostsSuffixes, which is - * no longer allowed by AutomapHostsOnResolve, or for which the - * target address is no longer in the virtual network. */ -void -addressmap_clear_invalid_automaps(const or_options_t *options) -{ - int clear_all = !options->AutomapHostsOnResolve; - const smartlist_t *suffixes = options->AutomapHostsSuffixes; - - if (!addressmap) - return; - - if (!suffixes) - clear_all = 1; /* This should be impossible, but let's be sure. */ - - STRMAP_FOREACH_MODIFY(addressmap, src_address, addressmap_entry_t *, ent) { - int remove = clear_all; - if (ent->source != ADDRMAPSRC_AUTOMAP) - continue; /* not an automap mapping. */ - - if (!remove) { - int suffix_found = 0; - SMARTLIST_FOREACH(suffixes, const char *, suffix, { - if (!strcasecmpend(src_address, suffix)) { - suffix_found = 1; - break; - } - }); - if (!suffix_found) - remove = 1; - } - - if (!remove && ! address_is_in_virtual_range(ent->new_address)) - remove = 1; - - if (remove) { - addressmap_ent_remove(src_address, ent); - MAP_DEL_CURRENT(src_address); - } - } STRMAP_FOREACH_END; -} - -/** Remove all entries from the addressmap that were set via the - * configuration file or the command line. */ -void -addressmap_clear_configured(void) -{ - addressmap_get_mappings(NULL, 0, 0, 0); -} - -/** Remove all entries from the addressmap that are set to expire, ever. */ -void -addressmap_clear_transient(void) -{ - addressmap_get_mappings(NULL, 2, TIME_MAX, 0); -} - -/** Clean out entries from the addressmap cache that were - * added long enough ago that they are no longer valid. - */ -void -addressmap_clean(time_t now) -{ - addressmap_get_mappings(NULL, 2, now, 0); -} - -/** Free all the elements in the addressmap, and free the addressmap - * itself. */ -void -addressmap_free_all(void) -{ - strmap_free(addressmap, addressmap_ent_free); - addressmap = NULL; - - strmap_free(virtaddress_reversemap, addressmap_virtaddress_ent_free); - virtaddress_reversemap = NULL; -} - -/** Try to find a match for AddressMap expressions that use - * wildcard notation such as '*.c.d *.e.f' (so 'a.c.d' will map to 'a.e.f') or - * '*.c.d a.b.c' (so 'a.c.d' will map to a.b.c). - * Return the matching entry in AddressMap or NULL if no match is found. - * For expressions such as '*.c.d *.e.f', truncate <b>address</b> 'a.c.d' - * to 'a' before we return the matching AddressMap entry. - * - * This function does not handle the case where a pattern of the form "*.c.d" - * matches the address c.d -- that's done by the main addressmap_rewrite - * function. - */ -static addressmap_entry_t * -addressmap_match_superdomains(char *address) -{ - addressmap_entry_t *val; - char *cp; - - cp = address; - while ((cp = strchr(cp, '.'))) { - /* cp now points to a suffix of address that begins with a . */ - val = strmap_get_lc(addressmap, cp+1); - if (val && val->src_wildcard) { - if (val->dst_wildcard) - *cp = '\0'; - return val; - } - ++cp; - } - return NULL; -} - -/** Look at address, and rewrite it until it doesn't want any - * more rewrites; but don't get into an infinite loop. - * Don't write more than maxlen chars into address. Return true if the - * address changed; false otherwise. Set *<b>expires_out</b> to the - * expiry time of the result, or to <b>time_max</b> if the result does - * not expire. - * - * If <b>exit_source_out</b> is non-null, we set it as follows. If we the - * address starts out as a non-exit address, and we remap it to an .exit - * address at any point, then set *<b>exit_source_out</b> to the - * address_entry_source_t of the first such rule. Set *<b>exit_source_out</b> - * to ADDRMAPSRC_NONE if there is no such rewrite, or if the original address - * was a .exit. - */ -int -addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, - addressmap_entry_source_t *exit_source_out) -{ - addressmap_entry_t *ent; - int rewrites; - time_t expires = TIME_MAX; - addressmap_entry_source_t exit_source = ADDRMAPSRC_NONE; - char *addr_orig = tor_strdup(address); - char *log_addr_orig = NULL; - - for (rewrites = 0; rewrites < 16; rewrites++) { - int exact_match = 0; - log_addr_orig = tor_strdup(escaped_safe_str_client(address)); - - ent = strmap_get(addressmap, address); - - if (!ent || !ent->new_address) { - ent = addressmap_match_superdomains(address); - } else { - if (ent->src_wildcard && !ent->dst_wildcard && - !strcasecmp(address, ent->new_address)) { - /* This is a rule like *.example.com example.com, and we just got - * "example.com" */ - goto done; - } - - exact_match = 1; - } - - if (!ent || !ent->new_address) { - goto done; - } - - if (ent->dst_wildcard && !exact_match) { - strlcat(address, ".", maxlen); - strlcat(address, ent->new_address, maxlen); - } else { - strlcpy(address, ent->new_address, maxlen); - } - - if (!strcmpend(address, ".exit") && - strcmpend(addr_orig, ".exit") && - exit_source == ADDRMAPSRC_NONE) { - exit_source = ent->source; - } - - log_info(LD_APP, "Addressmap: rewriting %s to %s", - log_addr_orig, escaped_safe_str_client(address)); - if (ent->expires > 1 && ent->expires < expires) - expires = ent->expires; - - tor_free(log_addr_orig); - } - log_warn(LD_CONFIG, - "Loop detected: we've rewritten %s 16 times! Using it as-is.", - escaped_safe_str_client(address)); - /* it's fine to rewrite a rewrite, but don't loop forever */ - - done: - tor_free(addr_orig); - tor_free(log_addr_orig); - if (exit_source_out) - *exit_source_out = exit_source; - if (expires_out) - *expires_out = TIME_MAX; - return (rewrites > 0); -} - -/** If we have a cached reverse DNS entry for the address stored in the - * <b>maxlen</b>-byte buffer <b>address</b> (typically, a dotted quad) then - * rewrite to the cached value and return 1. Otherwise return 0. Set - * *<b>expires_out</b> to the expiry time of the result, or to <b>time_max</b> - * if the result does not expire. */ -static int -addressmap_rewrite_reverse(char *address, size_t maxlen, time_t *expires_out) -{ - char *s, *cp; - addressmap_entry_t *ent; - int r = 0; - tor_asprintf(&s, "REVERSE[%s]", address); - ent = strmap_get(addressmap, s); - if (ent) { - cp = tor_strdup(escaped_safe_str_client(ent->new_address)); - log_info(LD_APP, "Rewrote reverse lookup %s -> %s", - escaped_safe_str_client(s), cp); - tor_free(cp); - strlcpy(address, ent->new_address, maxlen); - r = 1; - } - - if (expires_out) - *expires_out = (ent && ent->expires > 1) ? ent->expires : TIME_MAX; - - tor_free(s); - return r; -} - -/** Return 1 if <b>address</b> is already registered, else return 0. If address - * is already registered, and <b>update_expires</b> is non-zero, then update - * the expiry time on the mapping with update_expires if it is a - * mapping created by TrackHostExits. */ -int -addressmap_have_mapping(const char *address, int update_expiry) -{ - addressmap_entry_t *ent; - if (!(ent=strmap_get_lc(addressmap, address))) - return 0; - if (update_expiry && ent->source==ADDRMAPSRC_TRACKEXIT) - ent->expires=time(NULL) + update_expiry; - return 1; -} - -/** Register a request to map <b>address</b> to <b>new_address</b>, - * which will expire on <b>expires</b> (or 0 if never expires from - * config file, 1 if never expires from controller, 2 if never expires - * (virtual address mapping) from the controller.) - * - * <b>new_address</b> should be a newly dup'ed string, which we'll use or - * free as appropriate. We will leave address alone. - * - * If <b>wildcard_addr</b> is true, then the mapping will match any address - * equal to <b>address</b>, or any address ending with a period followed by - * <b>address</b>. If <b>wildcard_addr</b> and <b>wildcard_new_addr</b> are - * both true, the mapping will rewrite addresses that end with - * ".<b>address</b>" into ones that end with ".<b>new_address</b>." - * - * If <b>new_address</b> is NULL, or <b>new_address</b> is equal to - * <b>address</b> and <b>wildcard_addr</b> is equal to - * <b>wildcard_new_addr</b>, remove any mappings that exist from - * <b>address</b>. - * - * - * It is an error to set <b>wildcard_new_addr</b> if <b>wildcard_addr</b> is - * not set. */ -void -addressmap_register(const char *address, char *new_address, time_t expires, - addressmap_entry_source_t source, - const int wildcard_addr, - const int wildcard_new_addr) -{ - addressmap_entry_t *ent; - - if (wildcard_new_addr) - tor_assert(wildcard_addr); - - ent = strmap_get(addressmap, address); - if (!new_address || (!strcasecmp(address,new_address) && - wildcard_addr == wildcard_new_addr)) { - /* Remove the mapping, if any. */ - tor_free(new_address); - if (ent) { - addressmap_ent_remove(address,ent); - strmap_remove(addressmap, address); - } - return; - } - if (!ent) { /* make a new one and register it */ - ent = tor_malloc_zero(sizeof(addressmap_entry_t)); - strmap_set(addressmap, address, ent); - } else if (ent->new_address) { /* we need to clean up the old mapping. */ - if (expires > 1) { - log_info(LD_APP,"Temporary addressmap ('%s' to '%s') not performed, " - "since it's already mapped to '%s'", - safe_str_client(address), - safe_str_client(new_address), - safe_str_client(ent->new_address)); - tor_free(new_address); - return; - } - if (address_is_in_virtual_range(ent->new_address) && - expires != 2) { - /* XXX This isn't the perfect test; we want to avoid removing - * mappings set from the control interface _as virtual mapping */ - addressmap_virtaddress_remove(address, ent); - } - tor_free(ent->new_address); - } /* else { we have an in-progress resolve with no mapping. } */ - - ent->new_address = new_address; - ent->expires = expires==2 ? 1 : expires; - ent->num_resolve_failures = 0; - ent->source = source; - ent->src_wildcard = wildcard_addr ? 1 : 0; - ent->dst_wildcard = wildcard_new_addr ? 1 : 0; - - log_info(LD_CONFIG, "Addressmap: (re)mapped '%s' to '%s'", - safe_str_client(address), - safe_str_client(ent->new_address)); - control_event_address_mapped(address, ent->new_address, expires, NULL); -} - -/** An attempt to resolve <b>address</b> failed at some OR. - * Increment the number of resolve failures we have on record - * for it, and then return that number. - */ -int -client_dns_incr_failures(const char *address) -{ - addressmap_entry_t *ent = strmap_get(addressmap, address); - if (!ent) { - ent = tor_malloc_zero(sizeof(addressmap_entry_t)); - ent->expires = time(NULL) + MAX_DNS_ENTRY_AGE; - strmap_set(addressmap,address,ent); - } - 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_client(address), - ent->num_resolve_failures); - return ent->num_resolve_failures; -} - -/** If <b>address</b> is in the client DNS addressmap, reset - * the number of resolve failures we have on record for it. - * This is used when we fail a stream because it won't resolve: - * otherwise future attempts on that address will only try once. - */ -void -client_dns_clear_failures(const char *address) -{ - addressmap_entry_t *ent = strmap_get(addressmap, address); - if (ent) - ent->num_resolve_failures = 0; -} - -/** Record the fact that <b>address</b> resolved to <b>name</b>. - * We can now use this in subsequent streams via addressmap_rewrite() - * so we can more correctly choose an exit that will allow <b>address</b>. - * - * If <b>exitname</b> is defined, then append the addresses with - * ".exitname.exit" before registering the mapping. - * - * If <b>ttl</b> is nonnegative, the mapping will be valid for - * <b>ttl</b>seconds; otherwise, we use the default. - */ -static void -client_dns_set_addressmap_impl(const char *address, const char *name, - const char *exitname, - int ttl) -{ - /* <address>.<hex or nickname>.exit\0 or just <address>\0 */ - char extendedaddress[MAX_SOCKS_ADDR_LEN+MAX_VERBOSE_NICKNAME_LEN+10]; - /* 123.123.123.123.<hex or nickname>.exit\0 or just 123.123.123.123\0 */ - char extendedval[INET_NTOA_BUF_LEN+MAX_VERBOSE_NICKNAME_LEN+10]; - - tor_assert(address); - tor_assert(name); - - if (ttl<0) - ttl = DEFAULT_DNS_TTL; - else - ttl = dns_clip_ttl(ttl); - - if (exitname) { - /* XXXX fails to ever get attempts to get an exit address of - * google.com.digest[=~]nickname.exit; we need a syntax for this that - * won't make strict RFC952-compliant applications (like us) barf. */ - tor_snprintf(extendedaddress, sizeof(extendedaddress), - "%s.%s.exit", address, exitname); - tor_snprintf(extendedval, sizeof(extendedval), - "%s.%s.exit", name, exitname); - } else { - tor_snprintf(extendedaddress, sizeof(extendedaddress), - "%s", address); - tor_snprintf(extendedval, sizeof(extendedval), - "%s", name); - } - addressmap_register(extendedaddress, tor_strdup(extendedval), - time(NULL) + ttl, ADDRMAPSRC_DNS, 0, 0); -} - -/** Record the fact that <b>address</b> resolved to <b>val</b>. - * We can now use this in subsequent streams via addressmap_rewrite() - * so we can more correctly choose an exit that will allow <b>address</b>. - * - * If <b>exitname</b> is defined, then append the addresses with - * ".exitname.exit" before registering the mapping. - * - * If <b>ttl</b> is nonnegative, the mapping will be valid for - * <b>ttl</b>seconds; otherwise, we use the default. - */ -void -client_dns_set_addressmap(const char *address, uint32_t val, - const char *exitname, - int ttl) -{ - struct in_addr in; - char valbuf[INET_NTOA_BUF_LEN]; - - tor_assert(address); - - if (tor_inet_aton(address, &in)) - return; /* If address was an IP address already, don't add a mapping. */ - in.s_addr = htonl(val); - tor_inet_ntoa(&in,valbuf,sizeof(valbuf)); - - client_dns_set_addressmap_impl(address, valbuf, exitname, ttl); -} - -/** Add a cache entry noting that <b>address</b> (ordinarily a dotted quad) - * resolved via a RESOLVE_PTR request to the hostname <b>v</b>. - * - * If <b>exitname</b> is defined, then append the addresses with - * ".exitname.exit" before registering the mapping. - * - * If <b>ttl</b> is nonnegative, the mapping will be valid for - * <b>ttl</b>seconds; otherwise, we use the default. - */ -static void -client_dns_set_reverse_addressmap(const char *address, const char *v, - const char *exitname, - int ttl) -{ - char *s = NULL; - tor_asprintf(&s, "REVERSE[%s]", address); - client_dns_set_addressmap_impl(s, v, exitname, ttl); - tor_free(s); -} - -/* By default, we hand out 127.192.0.1 through 127.254.254.254. - * These addresses should map to localhost, so even if the - * application accidentally tried to connect to them directly (not - * via Tor), it wouldn't get too far astray. - * - * These options are configured by parse_virtual_addr_network(). - */ -/** Which network should we use for virtual IPv4 addresses? Only the first - * bits of this value are fixed. */ -static uint32_t virtual_addr_network = 0x7fc00000u; -/** How many bits of <b>virtual_addr_network</b> are fixed? */ -static maskbits_t virtual_addr_netmask_bits = 10; -/** What's the next virtual address we will hand out? */ -static uint32_t next_virtual_addr = 0x7fc00000u; - -/** Read a netmask of the form 127.192.0.0/10 from "val", and check whether - * it's a valid set of virtual addresses to hand out in response to MAPADDRESS - * requests. Return 0 on success; set *msg (if provided) to a newly allocated - * string and return -1 on failure. If validate_only is false, sets the - * actual virtual address range to the parsed value. */ -int -parse_virtual_addr_network(const char *val, int validate_only, - char **msg) -{ - uint32_t addr; - uint16_t port_min, port_max; - maskbits_t bits; - - if (parse_addr_and_port_range(val, &addr, &bits, &port_min, &port_max)) { - if (msg) *msg = tor_strdup("Error parsing VirtualAddressNetwork"); - return -1; - } - - if (port_min != 1 || port_max != 65535) { - if (msg) *msg = tor_strdup("Can't specify ports on VirtualAddressNetwork"); - return -1; - } - - if (bits > 16) { - if (msg) *msg = tor_strdup("VirtualAddressNetwork expects a /16 " - "network or larger"); - return -1; - } - - if (validate_only) - return 0; - - virtual_addr_network = (uint32_t)( addr & (0xfffffffful << (32-bits)) ); - virtual_addr_netmask_bits = bits; - - if (addr_mask_cmp_bits(next_virtual_addr, addr, bits)) - next_virtual_addr = addr; - - return 0; -} - -/** - * Return true iff <b>addr</b> is likely to have been returned by - * client_dns_get_unused_address. - **/ -static int -address_is_in_virtual_range(const char *address) -{ - struct in_addr in; - tor_assert(address); - if (!strcasecmpend(address, ".virtual")) { - return 1; - } else if (tor_inet_aton(address, &in)) { - uint32_t addr = ntohl(in.s_addr); - if (!addr_mask_cmp_bits(addr, virtual_addr_network, - virtual_addr_netmask_bits)) - return 1; - } - return 0; -} - -/** Increment the value of next_virtual_addr; reset it to the start of the - * virtual address range if it wraps around. - */ -static INLINE void -increment_virtual_addr(void) -{ - ++next_virtual_addr; - if (addr_mask_cmp_bits(next_virtual_addr, virtual_addr_network, - virtual_addr_netmask_bits)) - next_virtual_addr = virtual_addr_network; -} - -/** Return a newly allocated string holding an address of <b>type</b> - * (one of RESOLVED_TYPE_{IPV4|HOSTNAME}) that has not yet been mapped, - * and that is very unlikely to be the address of any real host. - * - * May return NULL if we have run out of virtual addresses. - */ -static char * -addressmap_get_virtual_address(int type) -{ - char buf[64]; - tor_assert(addressmap); - - if (type == RESOLVED_TYPE_HOSTNAME) { - char rand[10]; - do { - crypto_rand(rand, sizeof(rand)); - base32_encode(buf,sizeof(buf),rand,sizeof(rand)); - strlcat(buf, ".virtual", sizeof(buf)); - } while (strmap_get(addressmap, buf)); - return tor_strdup(buf); - } else if (type == RESOLVED_TYPE_IPV4) { - // This is an imperfect estimate of how many addresses are available, but - // that's ok. - struct in_addr in; - uint32_t available = 1u << (32-virtual_addr_netmask_bits); - while (available) { - /* Don't hand out any .0 or .255 address. */ - while ((next_virtual_addr & 0xff) == 0 || - (next_virtual_addr & 0xff) == 0xff) { - increment_virtual_addr(); - if (! --available) { - log_warn(LD_CONFIG, "Ran out of virtual addresses!"); - return NULL; - } - } - in.s_addr = htonl(next_virtual_addr); - tor_inet_ntoa(&in, buf, sizeof(buf)); - if (!strmap_get(addressmap, buf)) { - increment_virtual_addr(); - break; - } - - increment_virtual_addr(); - --available; - // log_info(LD_CONFIG, "%d addrs available", (int)available); - if (! available) { - log_warn(LD_CONFIG, "Ran out of virtual addresses!"); - return NULL; - } - } - return tor_strdup(buf); - } else { - log_warn(LD_BUG, "Called with unsupported address type (%d)", type); - return NULL; - } -} - -/** A controller has requested that we map some address of type - * <b>type</b> to the address <b>new_address</b>. Choose an address - * that is unlikely to be used, and map it, and return it in a newly - * allocated string. If another address of the same type is already - * mapped to <b>new_address</b>, try to return a copy of that address. - * - * The string in <b>new_address</b> may be freed or inserted into a map - * as appropriate. May return NULL if are out of virtual addresses. - **/ -const char * -addressmap_register_virtual_address(int type, char *new_address) -{ - char **addrp; - virtaddress_entry_t *vent; - int vent_needs_to_be_added = 0; - - tor_assert(new_address); - tor_assert(addressmap); - tor_assert(virtaddress_reversemap); - - vent = strmap_get(virtaddress_reversemap, new_address); - if (!vent) { - vent = tor_malloc_zero(sizeof(virtaddress_entry_t)); - vent_needs_to_be_added = 1; - } - - addrp = (type == RESOLVED_TYPE_IPV4) ? - &vent->ipv4_address : &vent->hostname_address; - if (*addrp) { - addressmap_entry_t *ent = strmap_get(addressmap, *addrp); - if (ent && ent->new_address && - !strcasecmp(new_address, ent->new_address)) { - tor_free(new_address); - tor_assert(!vent_needs_to_be_added); - return tor_strdup(*addrp); - } else - 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_client(new_address), - safe_str_client(*addrp), - safe_str_client(*addrp), - ent?safe_str_client(ent->new_address):"(nothing)"); - } - - tor_free(*addrp); - *addrp = addressmap_get_virtual_address(type); - if (!*addrp) { - tor_free(vent); - tor_free(new_address); - return NULL; - } - log_info(LD_APP, "Registering map from %s to %s", *addrp, new_address); - if (vent_needs_to_be_added) - strmap_set(virtaddress_reversemap, new_address, vent); - addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_AUTOMAP, 0, 0); - -#if 0 - { - /* Try to catch possible bugs */ - addressmap_entry_t *ent; - ent = strmap_get(addressmap, *addrp); - tor_assert(ent); - tor_assert(!strcasecmp(ent->new_address,new_address)); - vent = strmap_get(virtaddress_reversemap, new_address); - tor_assert(vent); - tor_assert(!strcasecmp(*addrp, - (type == RESOLVED_TYPE_IPV4) ? - vent->ipv4_address : vent->hostname_address)); - log_info(LD_APP, "Map from %s to %s okay.", - safe_str_client(*addrp), - safe_str_client(new_address)); - } -#endif - - return *addrp; -} - -/** Return 1 if <b>address</b> has funny characters in it like colons. Return - * 0 if it's fine, or if we're configured to allow it anyway. <b>client</b> - * should be true if we're using this address as a client; false if we're - * using it as a server. - */ -int -address_is_invalid_destination(const char *address, int client) -{ - if (client) { - if (get_options()->AllowNonRFC953Hostnames) - return 0; - } else { - if (get_options()->ServerDNSAllowNonRFC953Hostnames) - return 0; - } - - while (*address) { - if (TOR_ISALNUM(*address) || - *address == '-' || - *address == '.' || - *address == '_') /* Underscore is not allowed, but Windows does it - * sometimes, just to thumb its nose at the IETF. */ - ++address; - else - return 1; - } - return 0; -} - -/** Iterate over all address mappings which have expiry times between - * min_expires and max_expires, inclusive. If sl is provided, add an - * "old-addr new-addr expiry" string to sl for each mapping, omitting - * the expiry time if want_expiry is false. If sl is NULL, remove the - * mappings. - */ -void -addressmap_get_mappings(smartlist_t *sl, time_t min_expires, - time_t max_expires, int want_expiry) -{ - strmap_iter_t *iter; - const char *key; - void *_val; - addressmap_entry_t *val; - - if (!addressmap) - addressmap_init(); - - for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) { - strmap_iter_get(iter, &key, &_val); - val = _val; - if (val->expires >= min_expires && val->expires <= max_expires) { - if (!sl) { - iter = strmap_iter_next_rmv(addressmap,iter); - addressmap_ent_remove(key, val); - continue; - } else if (val->new_address) { - const char *src_wc = val->src_wildcard ? "*." : ""; - const char *dst_wc = val->dst_wildcard ? "*." : ""; - if (want_expiry) { - if (val->expires < 3 || val->expires == TIME_MAX) - smartlist_add_asprintf(sl, "%s%s %s%s NEVER", - src_wc, key, dst_wc, val->new_address); - else { - char time[ISO_TIME_LEN+1]; - format_iso_time(time, val->expires); - smartlist_add_asprintf(sl, "%s%s %s%s \"%s\"", - src_wc, key, dst_wc, val->new_address, - time); - } - } else { - smartlist_add_asprintf(sl, "%s%s %s%s", - src_wc, key, dst_wc, val->new_address); - } - } - } - iter = strmap_iter_next(addressmap,iter); - } -} - /** Check if <b>conn</b> is using a dangerous port. Then warn and/or * reject depending on our config options. */ static int consider_plaintext_ports(entry_connection_t *conn, uint16_t port) { const or_options_t *options = get_options(); - int reject = smartlist_string_num_isin(options->RejectPlaintextPorts, port); + int reject = smartlist_contains_int_as_string( + options->RejectPlaintextPorts, port); - if (smartlist_string_num_isin(options->WarnPlaintextPorts, port)) { + if (smartlist_contains_int_as_string(options->WarnPlaintextPorts, port)) { log_warn(LD_APP, "Application request to port %d: this port is " "commonly used for unencrypted protocols. Please make sure " "you don't send anything you would mind the rest of the " @@ -1798,7 +921,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, socks_request_t *socks = conn->socks_request; hostname_type_t addresstype; const or_options_t *options = get_options(); - struct in_addr addr_tmp; + tor_addr_t addr_tmp; /* We set this to true if this is an address we should automatically * remap to a local address in VirtualAddrNetwork */ int automap = 0; @@ -1828,17 +951,20 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, conn->original_dest_address = tor_strdup(conn->socks_request->address); if (socks->command == SOCKS_COMMAND_RESOLVE && - !tor_inet_aton(socks->address, &addr_tmp) && - options->AutomapHostsOnResolve && options->AutomapHostsSuffixes) { - SMARTLIST_FOREACH(options->AutomapHostsSuffixes, const char *, cp, - if (!strcasecmpend(socks->address, cp)) { - automap = 1; - break; - }); + tor_addr_parse(&addr_tmp, socks->address)<0 && + options->AutomapHostsOnResolve) { + automap = addressmap_address_should_automap(socks->address, options); if (automap) { const char *new_addr; + int addr_type = RESOLVED_TYPE_IPV4; + if (conn->socks_request->socks_version != 4) { + if (!conn->ipv4_traffic_ok || + (conn->ipv6_traffic_ok && conn->prefer_ipv6_traffic) || + conn->prefer_ipv6_virtaddr) + addr_type = RESOLVED_TYPE_IPV6; + } new_addr = addressmap_register_virtual_address( - RESOLVED_TYPE_IPV4, tor_strdup(socks->address)); + addr_type, tor_strdup(socks->address)); if (! new_addr) { log_warn(LD_APP, "Unable to automap address %s", escaped_safe_str(socks->address)); @@ -1853,8 +979,14 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, } if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) { + unsigned rewrite_flags = 0; + if (conn->use_cached_ipv4_answers) + rewrite_flags |= AMR_FLAG_USE_IPV4_DNS; + if (conn->use_cached_ipv6_answers) + rewrite_flags |= AMR_FLAG_USE_IPV6_DNS; + if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address), - &map_expires)) { + rewrite_flags, &map_expires)) { char *result = tor_strdup(socks->address); /* remember _what_ is supposed to have been resolved. */ tor_snprintf(socks->address, sizeof(socks->address), "REVERSE[%s]", @@ -1885,8 +1017,13 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, } } else if (!automap) { /* For address map controls, remap the address. */ + unsigned rewrite_flags = 0; + if (conn->use_cached_ipv4_answers) + rewrite_flags |= AMR_FLAG_USE_IPV4_DNS; + if (conn->use_cached_ipv6_answers) + rewrite_flags |= AMR_FLAG_USE_IPV6_DNS; if (addressmap_rewrite(socks->address, sizeof(socks->address), - &map_expires, &exit_source)) { + rewrite_flags, &map_expires, &exit_source)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, REMAP_STREAM_SOURCE_CACHE); } @@ -1923,7 +1060,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, /* If StrictNodes is not set, then .exit overrides ExcludeNodes. */ routerset_t *excludeset = options->StrictNodes ? - options->_ExcludeExitNodesUnion : options->ExcludeExitNodes; + options->ExcludeExitNodesUnion_ : options->ExcludeExitNodes; const node_t *node; if (exit_source == ADDRMAPSRC_AUTOMAP && !options->AllowDotExit) { @@ -2024,17 +1161,13 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, } if (socks->command == SOCKS_COMMAND_RESOLVE) { - uint32_t answer; - struct in_addr in; + tor_addr_t answer; /* Reply to resolves immediately if we can. */ - if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */ - /* leave it in network order */ - answer = in.s_addr; + if (tor_addr_parse(&answer, socks->address) >= 0) {/* is it an IP? */ /* remember _what_ is supposed to have been resolved. */ strlcpy(socks->address, orig_address, sizeof(socks->address)); - connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4, - (uint8_t*)&answer, - -1,map_expires); + connection_ap_handshake_socks_resolved_addr(conn, &answer, -1, + map_expires); connection_mark_unattached_ap(conn, END_STREAM_REASON_DONE | END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -2087,6 +1220,37 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, } } + { + tor_addr_t addr; + /* XXX Duplicate call to tor_addr_parse. */ + if (tor_addr_parse(&addr, socks->address) >= 0) { + sa_family_t family = tor_addr_family(&addr); + if ((family == AF_INET && ! conn->ipv4_traffic_ok) || + (family == AF_INET6 && ! conn->ipv4_traffic_ok)) { + log_warn(LD_NET, "Rejecting SOCKS request for an IP address " + "family that this listener does not support."); + connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY); + return -1; + } else if (family == AF_INET6 && socks->socks_version == 4) { + log_warn(LD_NET, "Rejecting SOCKS4 request for an IPv6 address."); + connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY); + return -1; + } else if (socks->socks_version == 4 && !conn->ipv4_traffic_ok) { + log_warn(LD_NET, "Rejecting SOCKS4 request on a listener with " + "no IPv4 traffic supported."); + connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY); + return -1; + } else if (family == AF_INET6) { + conn->ipv4_traffic_ok = 0; + } else if (family == AF_INET) { + conn->ipv6_traffic_ok = 0; + } + } + } + + if (socks->socks_version == 4) + conn->ipv6_traffic_ok = 0; + if (!conn->use_begindir && !conn->chosen_exit_name && !circ) { /* see if we can find a suitable enclave exit */ const node_t *r = @@ -2256,7 +1420,7 @@ connection_ap_get_original_destination(entry_connection_t *conn, } tor_addr_from_sockaddr(&addr, (struct sockaddr*)&orig_dst, &req->port); - tor_addr_to_str(req->address, &addr, sizeof(req->address), 0); + tor_addr_to_str(req->address, &addr, sizeof(req->address), 1); return 0; #elif defined(TRANS_PF) @@ -2317,7 +1481,7 @@ connection_ap_get_original_destination(entry_connection_t *conn, return -1; } - tor_addr_to_str(req->address, &addr, sizeof(req->address), 0); + tor_addr_to_str(req->address, &addr, sizeof(req->address), 1); req->port = ntohs(pnl.rdport); return 0; @@ -2517,7 +1681,7 @@ connection_ap_process_natd(entry_connection_t *conn) /** Iterate over the two bytes of stream_id until we get one that is not * already in use; return it. Return 0 if can't get a unique stream_id. */ -static streamid_t +streamid_t get_unique_stream_id_by_circ(origin_circuit_t *circ) { edge_connection_t *tmpconn; @@ -2555,6 +1719,66 @@ connection_ap_supports_optimistic_data(const entry_connection_t *conn) return conn->may_use_optimistic_data; } +/** Return a bitmask of BEGIN_FLAG_* flags that we should transmit in the + * RELAY_BEGIN cell for <b>ap_conn</b>. */ +static uint32_t +connection_ap_get_begincell_flags(entry_connection_t *ap_conn) +{ + edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn); + const node_t *exitnode = NULL; + const crypt_path_t *cpath_layer = edge_conn->cpath_layer; + uint32_t flags = 0; + + /* No flags for begindir */ + if (ap_conn->use_begindir) + return 0; + + /* No flags for hidden services. */ + if (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL) + return 0; + + /* If only IPv4 is supported, no flags */ + if (ap_conn->ipv4_traffic_ok && !ap_conn->ipv6_traffic_ok) + return 0; + + if (! cpath_layer || + ! cpath_layer->extend_info) + return 0; + + if (!ap_conn->ipv4_traffic_ok) + flags |= BEGIN_FLAG_IPV4_NOT_OK; + + exitnode = node_get_by_id(cpath_layer->extend_info->identity_digest); + + if (ap_conn->ipv6_traffic_ok && exitnode) { + tor_addr_t a; + tor_addr_make_null(&a, AF_INET6); + if (compare_tor_addr_to_node_policy(&a, ap_conn->socks_request->port, + exitnode) + != ADDR_POLICY_REJECTED) { + /* Only say "IPv6 OK" if the exit node supports IPv6. Otherwise there's + * no point. */ + flags |= BEGIN_FLAG_IPV6_OK; + } + } + + if (flags == BEGIN_FLAG_IPV6_OK) { + /* When IPv4 and IPv6 are both allowed, consider whether to say we + * prefer IPv6. Otherwise there's no point in declaring a preference */ + if (ap_conn->prefer_ipv6_traffic) + flags |= BEGIN_FLAG_IPV6_PREFERRED; + } + + if (flags == BEGIN_FLAG_IPV4_NOT_OK) { + log_warn(LD_EDGE, "I'm about to ask a node for a connection that I " + "am telling it to fulfil with neither IPv4 nor IPv6. That's " + "not going to work. Did you perhaps ask for an IPv6 address " + "on an IPv4Only port, or vice versa?"); + } + + return flags; +} + /** Write a relay begin cell, using destaddr and destport from ap_conn's * socks_request field, and send it down circ. * @@ -2584,17 +1808,22 @@ connection_ap_handshake_send_begin(entry_connection_t *ap_conn) connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); /* Mark this circuit "unusable for new streams". */ - /* XXXX024 this is a kludgy way to do this. */ - tor_assert(circ->_base.timestamp_dirty); - circ->_base.timestamp_dirty -= get_options()->MaxCircuitDirtiness; + mark_circuit_unusable_for_new_conns(circ); return -1; } + /* Set up begin cell flags. */ + edge_conn->begincell_flags = connection_ap_get_begincell_flags(ap_conn); + tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d", - (circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL) ? + (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL) ? ap_conn->socks_request->address : "", ap_conn->socks_request->port); payload_len = (int)strlen(payload)+1; + if (payload_len <= RELAY_PAYLOAD_SIZE - 4 && edge_conn->begincell_flags) { + set_uint32(payload + payload_len, htonl(edge_conn->begincell_flags)); + payload_len += 4; + } log_info(LD_APP, "Sending relay cell %d to begin stream %d.", @@ -2617,8 +1846,9 @@ connection_ap_handshake_send_begin(entry_connection_t *ap_conn) edge_conn->package_window = STREAMWINDOW_START; edge_conn->deliver_window = STREAMWINDOW_START; base_conn->state = AP_CONN_STATE_CONNECT_WAIT; - log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d", - base_conn->s, circ->_base.n_circ_id); + log_info(LD_APP,"Address/port sent, ap socket "TOR_SOCKET_T_FORMAT + ", n_circ_id %u", + base_conn->s, (unsigned)circ->base_.n_circ_id); control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0); /* If there's queued-up data, send it now */ @@ -2657,7 +1887,7 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn) tor_assert(base_conn->type == CONN_TYPE_AP); tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ap_conn->socks_request); - tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL); + tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL); command = ap_conn->socks_request->command; tor_assert(SOCKS_COMMAND_IS_RESOLVE(command)); @@ -2669,9 +1899,7 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn) connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); /* Mark this circuit "unusable for new streams". */ - /* XXXX024 this is a kludgy way to do this. */ - tor_assert(circ->_base.timestamp_dirty); - circ->_base.timestamp_dirty -= get_options()->MaxCircuitDirtiness; + mark_circuit_unusable_for_new_conns(circ); return -1; } @@ -2686,7 +1914,7 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn) /* We're doing a reverse lookup. The input could be an IP address, or * could be an .in-addr.arpa or .ip6.arpa address */ - r = tor_addr_parse_PTR_name(&addr, a, AF_INET, 1); + r = tor_addr_parse_PTR_name(&addr, a, AF_UNSPEC, 1); if (r <= 0) { log_warn(LD_APP, "Rejecting ill-formed reverse lookup of %s", safe_str_client(a)); @@ -2715,12 +1943,14 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn) string_addr, payload_len) < 0) return -1; /* circuit is closed, don't continue */ - tor_free(base_conn->address); /* Maybe already set by dnsserv. */ - base_conn->address = tor_strdup("(Tor_internal)"); + if (!base_conn->address) { + /* This might be unnecessary. XXXX */ + base_conn->address = tor_dup_addr(&base_conn->addr); + } base_conn->state = AP_CONN_STATE_RESOLVE_WAIT; - log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d", - base_conn->s, circ->_base.n_circ_id); - control_event_stream_status(ap_conn, STREAM_EVENT_NEW, 0); + log_info(LD_APP,"Address sent for resolve, ap socket "TOR_SOCKET_T_FORMAT + ", n_circ_id %u", + base_conn->s, (unsigned)circ->base_.n_circ_id); control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0); return 0; } @@ -2812,25 +2042,49 @@ tell_controller_about_resolved_result(entry_connection_t *conn, int ttl, time_t expires) { - - if (ttl >= 0 && (answer_type == RESOLVED_TYPE_IPV4 || - answer_type == RESOLVED_TYPE_HOSTNAME)) { - return; /* we already told the controller. */ - } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) { + expires = time(NULL) + ttl; + if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) { char *cp = tor_dup_ip(ntohl(get_uint32(answer))); control_event_address_mapped(conn->socks_request->address, - cp, expires, NULL); + cp, expires, NULL, 0); tor_free(cp); } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) { char *cp = tor_strndup(answer, answer_len); control_event_address_mapped(conn->socks_request->address, - cp, expires, NULL); + cp, expires, NULL, 0); tor_free(cp); } else { control_event_address_mapped(conn->socks_request->address, - "<error>", - time(NULL)+ttl, - "error=yes"); + "<error>", time(NULL)+ttl, + "error=yes", 0); + } +} + +/** + * As connection_ap_handshake_socks_resolved, but take a tor_addr_t to send + * as the answer. + */ +static void +connection_ap_handshake_socks_resolved_addr(entry_connection_t *conn, + const tor_addr_t *answer, + int ttl, + time_t expires) +{ + if (tor_addr_family(answer) == AF_INET) { + uint32_t a = tor_addr_to_ipv4n(answer); /* network order */ + connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4, + (uint8_t*)&a, + ttl, expires); + } else if (tor_addr_family(answer) == AF_INET6) { + const uint8_t *a = tor_addr_to_in6_addr8(answer); + connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV6,16, + a, + ttl, expires); + } else { + log_warn(LD_BUG, "Got called with address of unexpected family %d", + tor_addr_family(answer)); + connection_ap_handshake_socks_resolved(conn, + RESOLVED_TYPE_ERROR,0,NULL,-1,-1); } } @@ -2856,13 +2110,25 @@ connection_ap_handshake_socks_resolved(entry_connection_t *conn, if (ttl >= 0) { if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) { - uint32_t a = ntohl(get_uint32(answer)); - if (a) - client_dns_set_addressmap(conn->socks_request->address, a, + tor_addr_t a; + tor_addr_from_ipv4n(&a, get_uint32(answer)); + if (! tor_addr_is_null(&a)) { + client_dns_set_addressmap(conn, + conn->socks_request->address, &a, + conn->chosen_exit_name, ttl); + } + } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) { + tor_addr_t a; + tor_addr_from_ipv6_bytes(&a, (char*)answer); + if (! tor_addr_is_null(&a)) { + client_dns_set_addressmap(conn, + conn->socks_request->address, &a, conn->chosen_exit_name, ttl); + } } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) { char *cp = tor_strndup((char*)answer, answer_len); - client_dns_set_reverse_addressmap(conn->socks_request->address, + client_dns_set_reverse_addressmap(conn, + conn->socks_request->address, cp, conn->chosen_exit_name, ttl); tor_free(cp); @@ -2876,8 +2142,9 @@ connection_ap_handshake_socks_resolved(entry_connection_t *conn, conn->socks_request->has_finished = 1; return; } else { - /* This must be a request from the controller. We already sent - * a mapaddress if there's a ttl. */ + /* This must be a request from the controller. Since answers to those + * requests are not cached, they do not generate an ADDRMAP event on + * their own. */ tell_controller_about_resolved_result(conn, answer_type, answer_len, (char*)answer, ttl, expires); conn->socks_request->has_finished = 1; @@ -2958,9 +2225,36 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, tor_assert(conn->socks_request); /* make sure it's an AP stream */ - control_event_stream_status(conn, - status==SOCKS5_SUCCEEDED ? STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED, - endreason); + if (!SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) { + control_event_stream_status(conn, status==SOCKS5_SUCCEEDED ? + STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED, + endreason); + } + + /* Flag this stream's circuit as having completed a stream successfully + * (for path bias) */ + if (status == SOCKS5_SUCCEEDED || + endreason == END_STREAM_REASON_RESOLVEFAILED || + endreason == END_STREAM_REASON_CONNECTREFUSED || + endreason == END_STREAM_REASON_CONNRESET || + endreason == END_STREAM_REASON_NOROUTE || + endreason == END_STREAM_REASON_RESOURCELIMIT) { + if (!conn->edge_.on_circuit || + !CIRCUIT_IS_ORIGIN(conn->edge_.on_circuit)) { + // DNS remaps can trigger this. So can failed hidden service + // lookups. + log_info(LD_BUG, + "No origin circuit for successful SOCKS stream "U64_FORMAT + ". Reason: %d", + U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier), + endreason); + } else { + // XXX: Hrmm. It looks like optimistic data can't go through this + // codepath, but someone should probably test it and make sure. + // We don't want to mark optimistically opened streams as successful. + pathbias_mark_use_success(TO_ORIGIN_CIRCUIT(conn->edge_.on_circuit)); + } + } if (conn->socks_request->has_finished) { log_warn(LD_BUG, "(Harmless.) duplicate calls to " @@ -2992,6 +2286,70 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, return; } +/** Read a RELAY_BEGIN or RELAY_BEGINDIR cell from <b>cell</b>, decode it, and + * place the result in <b>bcell</b>. On success return 0; on failure return + * <0 and set *<b>end_reason_out</b> to the end reason we should send back to + * the client. + * + * Return -1 in the case where want to send a RELAY_END cell, and < -1 when + * we don't. + **/ +/* static */ int +begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, + uint8_t *end_reason_out) +{ + relay_header_t rh; + const uint8_t *body, *nul; + + memset(bcell, 0, sizeof(*bcell)); + *end_reason_out = END_STREAM_REASON_MISC; + + relay_header_unpack(&rh, cell->payload); + if (rh.length > RELAY_PAYLOAD_SIZE) { + return -2; /*XXXX why not TORPROTOCOL? */ + } + + bcell->stream_id = rh.stream_id; + + if (rh.command == RELAY_COMMAND_BEGIN_DIR) { + bcell->is_begindir = 1; + return 0; + } else if (rh.command != RELAY_COMMAND_BEGIN) { + log_warn(LD_BUG, "Got an unexpected command %d", (int)rh.command); + *end_reason_out = END_STREAM_REASON_INTERNAL; + return -1; + } + + body = cell->payload + RELAY_HEADER_SIZE; + nul = memchr(body, 0, rh.length); + if (! nul) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Relay begin cell has no \\0. Closing."); + *end_reason_out = END_STREAM_REASON_TORPROTOCOL; + return -1; + } + + if (tor_addr_port_split(LOG_PROTOCOL_WARN, + (char*)(body), + &bcell->address,&bcell->port)<0) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Unable to parse addr:port in relay begin cell. Closing."); + *end_reason_out = END_STREAM_REASON_TORPROTOCOL; + return -1; + } + if (bcell->port == 0) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Missing port in relay begin cell. Closing."); + tor_free(bcell->address); + *end_reason_out = END_STREAM_REASON_TORPROTOCOL; + return -1; + } + if (body + rh.length >= nul + 4) + bcell->flags = ntohl(get_uint32(nul+1)); + + return 0; +} + /** A relay 'begin' or 'begin_dir' cell has arrived, and either we are * an exit hop for the circuit, or we are the origin and it is a * rendezvous begin. @@ -3015,10 +2373,13 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { edge_connection_t *n_stream; relay_header_t rh; - char *address=NULL; - uint16_t port; + char *address = NULL; + uint16_t port = 0; or_circuit_t *or_circ = NULL; const or_options_t *options = get_options(); + begin_cell_t bcell; + int r; + uint8_t end_reason=0; assert_circuit_ok(circ); if (!CIRCUIT_IS_ORIGIN(circ)) @@ -3042,52 +2403,43 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) return 0; } - if (rh.command == RELAY_COMMAND_BEGIN) { - if (!memchr(cell->payload+RELAY_HEADER_SIZE, 0, rh.length)) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Relay begin cell has no \\0. Closing."); - relay_send_end_cell_from_edge(rh.stream_id, circ, - END_STREAM_REASON_TORPROTOCOL, NULL); - return 0; - } - if (tor_addr_port_split(LOG_PROTOCOL_WARN, - (char*)(cell->payload+RELAY_HEADER_SIZE), - &address,&port)<0) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Unable to parse addr:port in relay begin cell. Closing."); - relay_send_end_cell_from_edge(rh.stream_id, circ, - END_STREAM_REASON_TORPROTOCOL, NULL); - return 0; - } - if (port==0) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Missing port in relay begin cell. Closing."); - relay_send_end_cell_from_edge(rh.stream_id, circ, - END_STREAM_REASON_TORPROTOCOL, NULL); - tor_free(address); - return 0; - } - 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) && + r = begin_cell_parse(cell, &bcell, &end_reason); + if (r < -1) { + return -1; + } else if (r == -1) { + tor_free(bcell.address); + relay_send_end_cell_from_edge(rh.stream_id, circ, end_reason, NULL); + return 0; + } + + if (! bcell.is_begindir) { + /* Steal reference */ + address = bcell.address; + port = bcell.port; + + if (or_circ && or_circ->p_chan) { + if (!options->AllowSingleHopExits && + (or_circ->is_first_hop || + (!connection_or_digest_is_known_relay( + or_circ->p_chan->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 - * and users who'd be better off with, well, single-hop proxies. - */ - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "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, - or_circ->is_first_hop ? - END_STREAM_REASON_TORPROTOCOL : - END_STREAM_REASON_MISC, - NULL); - tor_free(address); - return 0; + /* Don't let clients use us as a single-hop proxy, unless the user + * 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 by %s to open a stream %s. Closing.", + safe_str(channel_get_canonical_remote_descr(or_circ->p_chan)), + or_circ->is_first_hop ? "on first hop of circuit" : + "from unknown relay"); + relay_send_end_cell_from_edge(rh.stream_id, circ, + 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(options) || @@ -3098,10 +2450,10 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) } /* Make sure to get the 'real' address of the previous hop: the * caller might want to know whether his IP address has changed, and - * we might already have corrected _base.addr[ess] for the relay's + * we might already have corrected base_.addr[ess] for the relay's * canonical IP address. */ - if (or_circ && or_circ->p_conn) - address = tor_dup_addr(&or_circ->p_conn->real_addr); + if (or_circ && or_circ->p_chan) + address = tor_strdup(channel_get_actual_remote_address(or_circ->p_chan)); else address = tor_strdup("127.0.0.1"); port = 1; /* XXXX This value is never actually used anywhere, and there @@ -3114,17 +2466,31 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) return 0; } + if (! options->IPv6Exit) { + /* I don't care if you prefer IPv6; I can't give you any. */ + bcell.flags &= ~BEGIN_FLAG_IPV6_PREFERRED; + /* If you don't want IPv4, I can't help. */ + if (bcell.flags & BEGIN_FLAG_IPV4_NOT_OK) { + tor_free(address); + relay_send_end_cell_from_edge(rh.stream_id, circ, + END_STREAM_REASON_EXITPOLICY, NULL); + return 0; + } + } + log_debug(LD_EXIT,"Creating new exit connection."); + /* The 'AF_INET' here is temporary; we might need to change it later in + * connection_exit_connect(). */ 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->dirreq_id = circ->dirreq_id; + n_stream->base_.purpose = EXIT_PURPOSE_CONNECT; + n_stream->begincell_flags = bcell.flags; n_stream->stream_id = rh.stream_id; - n_stream->_base.port = port; + n_stream->base_.port = port; /* leave n_stream->s at -1, because it's not yet valid */ n_stream->package_window = STREAMWINDOW_START; n_stream->deliver_window = STREAMWINDOW_START; @@ -3132,14 +2498,14 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) { origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); log_info(LD_REND,"begin is for rendezvous. configuring stream."); - n_stream->_base.address = tor_strdup("(rendezvous)"); - n_stream->_base.state = EXIT_CONN_STATE_CONNECTING; + n_stream->base_.address = tor_strdup("(rendezvous)"); + n_stream->base_.state = EXIT_CONN_STATE_CONNECTING; n_stream->rend_data = rend_data_dup(origin_circ->rend_data); tor_assert(connection_edge_is_rendezvous_stream(n_stream)); assert_circuit_ok(circ); if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) { log_info(LD_REND,"Didn't find rendezvous service (port %d)", - n_stream->_base.port); + n_stream->base_.port); relay_send_end_cell_from_edge(rh.stream_id, circ, END_STREAM_REASON_EXITPOLICY, origin_circ->cpath->prev); @@ -3158,12 +2524,16 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) assert_circuit_ok(circ); connection_exit_connect(n_stream); + + /* For path bias: This circuit was used successfully */ + pathbias_mark_use_success(origin_circ); + tor_free(address); return 0; } tor_strlower(address); - n_stream->_base.address = address; - n_stream->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; + n_stream->base_.address = address; + n_stream->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; /* default to failed, change in dns_resolve if it turns out not to fail */ if (we_are_hibernating()) { @@ -3176,9 +2546,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) n_stream->on_circuit = circ; if (rh.command == RELAY_COMMAND_BEGIN_DIR) { + tor_addr_t tmp_addr; tor_assert(or_circ); - if (or_circ->p_conn && !tor_addr_is_null(&or_circ->p_conn->real_addr)) - tor_addr_copy(&n_stream->_base.addr, &or_circ->p_conn->real_addr); + if (or_circ->p_chan && + channel_get_addr_if_possible(or_circ->p_chan, &tmp_addr)) { + tor_addr_copy(&n_stream->base_.addr, &tmp_addr); + } return connection_exit_connect_dir(n_stream); } @@ -3228,12 +2601,12 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) */ dummy_conn = edge_connection_new(CONN_TYPE_EXIT, AF_INET); dummy_conn->stream_id = rh.stream_id; - dummy_conn->_base.address = tor_strndup( + dummy_conn->base_.address = tor_strndup( (char*)cell->payload+RELAY_HEADER_SIZE, rh.length); - dummy_conn->_base.port = 0; - dummy_conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; - dummy_conn->_base.purpose = EXIT_PURPOSE_RESOLVE; + dummy_conn->base_.port = 0; + dummy_conn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; + dummy_conn->base_.purpose = EXIT_PURPOSE_RESOLVE; dummy_conn->on_circuit = TO_CIRCUIT(circ); @@ -3243,7 +2616,7 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) /* Connection freed; don't touch it. */ return 0; case 1: /* The result was cached; a resolved cell was sent. */ - if (!dummy_conn->_base.marked_for_close) + if (!dummy_conn->base_.marked_for_close) connection_free(TO_CONN(dummy_conn)); return 0; case 0: /* resolve added to pending list */ @@ -3268,8 +2641,11 @@ connection_exit_connect(edge_connection_t *edge_conn) connection_t *conn = TO_CONN(edge_conn); int socket_error = 0; - if (!connection_edge_is_rendezvous_stream(edge_conn) && - router_compare_to_my_exit_policy(edge_conn)) { + if ( (!connection_edge_is_rendezvous_stream(edge_conn) && + router_compare_to_my_exit_policy(&edge_conn->base_.addr, + edge_conn->base_.port)) || + (tor_addr_family(&conn->addr) == AF_INET6 && + ! get_options()->IPv6Exit)) { log_info(LD_EXIT,"%s:%d failed exit policy. Closing.", escaped_safe_str_client(conn->address), conn->port); connection_edge_end(edge_conn, END_STREAM_REASON_EXITPOLICY); @@ -3281,6 +2657,9 @@ connection_exit_connect(edge_connection_t *edge_conn) addr = &conn->addr; port = conn->port; + if (tor_addr_family(addr) == AF_INET6) + conn->socket_family = AF_INET6; + log_debug(LD_EXIT,"about to try connecting"); switch (connection_connect(conn, conn->address, addr, port, &socket_error)) { case -1: { @@ -3318,21 +2697,21 @@ connection_exit_connect(edge_connection_t *edge_conn) RELAY_COMMAND_CONNECTED, NULL, 0); } else { /* normal stream */ - char connected_payload[20]; - int connected_payload_len; - if (tor_addr_family(&conn->addr) == AF_INET) { - set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr)); - connected_payload_len = 4; - } else { - memcpy(connected_payload, tor_addr_to_in6_addr8(&conn->addr), 16); - connected_payload_len = 16; + uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN]; + int connected_payload_len = + connected_cell_format_payload(connected_payload, &conn->addr, + edge_conn->address_ttl); + if (connected_payload_len < 0) { + connection_edge_end(edge_conn, END_STREAM_REASON_INTERNAL); + circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn); + connection_free(conn); + return; } - set_uint32(connected_payload+connected_payload_len, - htonl(dns_clip_ttl(edge_conn->address_ttl))); - connected_payload_len += 4; + connection_edge_send_command(edge_conn, RELAY_COMMAND_CONNECTED, - connected_payload, connected_payload_len); + (char*)connected_payload, + connected_payload_len); } } @@ -3351,20 +2730,20 @@ connection_exit_connect_dir(edge_connection_t *exitconn) log_info(LD_EXIT, "Opening local connection for anonymized directory exit"); - exitconn->_base.state = EXIT_CONN_STATE_OPEN; + exitconn->base_.state = EXIT_CONN_STATE_OPEN; - dirconn = dir_connection_new(tor_addr_family(&exitconn->_base.addr)); + dirconn = dir_connection_new(tor_addr_family(&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; + 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; + dirconn->dirreq_id = exitconn->dirreq_id; connection_link_connections(TO_CONN(dirconn), TO_CONN(exitconn)); @@ -3447,11 +2826,15 @@ connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit) } if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) { - struct in_addr in; tor_addr_t addr, *addrp = NULL; addr_policy_result_t r; - if (tor_inet_aton(conn->socks_request->address, &in)) { - tor_addr_from_in(&addr, &in); + if (0 == tor_addr_parse(&addr, conn->socks_request->address)) { + addrp = &addr; + } else if (!conn->ipv4_traffic_ok && conn->ipv6_traffic_ok) { + tor_addr_make_null(&addr, AF_INET6); + addrp = &addr; + } else if (conn->ipv4_traffic_ok && !conn->ipv6_traffic_ok) { + tor_addr_make_null(&addr, AF_INET); addrp = &addr; } r = compare_tor_addr_to_node_policy(addrp, conn->socks_request->port,exit); @@ -3466,7 +2849,7 @@ connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit) if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit)) return 0; } - if (routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) { + if (routerset_contains_node(options->ExcludeExitNodesUnion_, exit)) { /* Not a suitable exit. Refuse it. */ return 0; } @@ -3477,6 +2860,9 @@ connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit) /** 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 "x.y.onion" with a well-formed handle x: + * Drop "x.", put a NUL after y, lower-case it, and return ONION_HOSTNAME. + * * If address is of the form "y.onion" with a badly-formed handle y: * Return BAD_HOSTNAME and log a message. * @@ -3490,6 +2876,7 @@ hostname_type_t parse_extended_hostname(char *address) { char *s; + char *q; char query[REND_SERVICE_ID_LEN_BASE32+1]; s = strrchr(address,'.'); @@ -3504,9 +2891,18 @@ parse_extended_hostname(char *address) /* so it is .onion */ *s = 0; /* NUL-terminate it */ - if (strlcpy(query, address, REND_SERVICE_ID_LEN_BASE32+1) >= + /* locate a 'sub-domain' component, in order to remove it */ + q = strrchr(address, '.'); + if (q == address) { + goto failed; /* reject sub-domain, as DNS does */ + } + q = (NULL == q) ? address : q + 1; + if (strlcpy(query, q, REND_SERVICE_ID_LEN_BASE32+1) >= REND_SERVICE_ID_LEN_BASE32+1) goto failed; + if (q != address) { + memmove(address, q, strlen(q) + 1 /* also get \0 */); + } if (rend_valid_service_id(query)) { return ONION_HOSTNAME; /* success */ } diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index c320d6ba49..ea284cbcfd 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,13 +9,13 @@ * \brief Header file for connection_edge.c. **/ -#ifndef _TOR_CONNECTION_EDGE_H -#define _TOR_CONNECTION_EDGE_H +#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_) + connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__) -void _connection_mark_unattached_ap(entry_connection_t *conn, int endreason, +void connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, int line, const char *file); int connection_edge_reached_eof(edge_connection_t *conn); int connection_edge_process_inbuf(edge_connection_t *conn, @@ -67,30 +67,6 @@ int connection_ap_process_transparent(entry_connection_t *conn); int address_is_invalid_destination(const char *address, int client); -void addressmap_init(void); -void addressmap_clear_excluded_trackexithosts(const or_options_t *options); -void addressmap_clear_invalid_automaps(const or_options_t *options); -void addressmap_clean(time_t now); -void addressmap_clear_configured(void); -void addressmap_clear_transient(void); -void addressmap_free_all(void); -int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, - addressmap_entry_source_t *exit_source_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, - const int address_wildcard, - const int new_address_wildcard); -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(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath); @@ -114,6 +90,52 @@ int connection_edge_update_circuit_isolation(const entry_connection_t *conn, origin_circuit_t *circ, int dry_run); void circuit_clear_isolation(origin_circuit_t *circ); +streamid_t get_unique_stream_id_by_circ(origin_circuit_t *circ); + +/** @name Begin-cell flags + * + * These flags are used in RELAY_BEGIN cells to change the default behavior + * of the cell. + * + * @{ + **/ +/** When this flag is set, the client is willing to get connected to IPv6 + * addresses */ +#define BEGIN_FLAG_IPV6_OK (1u<<0) +/** When this flag is set, the client DOES NOT support connecting to IPv4 + * addresses. (The sense of this flag is inverted from IPV6_OK, so that the + * old default behavior of Tor is equivalent to having all flags set to 0.) + **/ +#define BEGIN_FLAG_IPV4_NOT_OK (1u<<1) +/** When this flag is set, if we find both an IPv4 and an IPv6 address, + * we use the IPv6 address. Otherwise we use the IPv4 address. */ +#define BEGIN_FLAG_IPV6_PREFERRED (1u<<2) +/**@}*/ + +#ifdef CONNECTION_EDGE_PRIVATE + +/** A parsed BEGIN or BEGIN_DIR cell */ +typedef struct begin_cell_t { + /** The address the client has asked us to connect to, or NULL if this is + * a BEGIN_DIR cell*/ + char *address; + /** The flags specified in the BEGIN cell's body. One or more of + * BEGIN_FLAG_*. */ + uint32_t flags; + /** The client's requested port. */ + uint16_t port; + /** The client's requested Stream ID */ + uint16_t stream_id; + /** True iff this is a BEGIN_DIR cell. */ + unsigned is_begindir : 1; +} begin_cell_t; + +int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, + uint8_t *end_reason_out); +int connected_cell_format_payload(uint8_t *payload_out, + const tor_addr_t *addr, + uint32_t ttl); +#endif #endif diff --git a/src/or/connection_or.c b/src/or/connection_or.c index fbb7c31e04..8e7cd9ea51 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,17 +9,25 @@ * \brief Functions to handle OR connections, TLS handshaking, and * cells on the network. **/ - #include "or.h" #include "buffers.h" +/* + * Define this so we get channel internal functions, since we're implementing + * part of a subclass (channel_tls_t). + */ +#define TOR_CHANNEL_INTERNAL_ +#include "channel.h" +#include "channeltls.h" #include "circuitbuild.h" #include "circuitlist.h" +#include "circuitstats.h" #include "command.h" #include "config.h" #include "connection.h" #include "connection_or.h" #include "control.h" #include "dirserv.h" +#include "entrynodes.h" #include "geoip.h" #include "main.h" #include "networkstatus.h" @@ -43,6 +51,17 @@ static int connection_or_check_valid_tls_handshake(or_connection_t *conn, static void connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn); +static unsigned int +connection_or_is_bad_for_new_circs(or_connection_t *or_conn); +static void connection_or_mark_bad_for_new_circs(or_connection_t *or_conn); + +/* + * Call this when changing connection state, so notifications to the owning + * channel can be handled. + */ + +static void connection_or_change_state(or_connection_t *conn, uint8_t state); + #ifdef USE_BUFFEREVENTS static void connection_or_handle_event_cb(struct bufferevent *bufev, short event, void *arg); @@ -127,8 +146,11 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest) return; /* If the identity was set previously, remove the old mapping. */ - if (! tor_digest_is_zero(conn->identity_digest)) + if (! tor_digest_is_zero(conn->identity_digest)) { connection_or_remove_from_identity_map(conn); + if (conn->chan) + channel_clear_identity_digest(TLS_CHAN_TO_BASE(conn->chan)); + } memcpy(conn->identity_digest, digest, DIGEST_LEN); @@ -139,6 +161,10 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest) tmp = digestmap_set(orconn_identity_map, digest, conn); conn->next_with_same_id = tmp; + /* Deal with channels */ + if (conn->chan) + channel_set_identity_digest(TLS_CHAN_TO_BASE(conn->chan), digest); + #if 1 /* Testing code to check for bugs in representation. */ for (; tmp; tmp = tmp->next_with_same_id) { @@ -268,13 +294,13 @@ connection_or_report_broken_states(int severity, int domain) smartlist_sort(items, broken_state_count_compare); - log(severity, domain, "%d connections have failed%s", total, + tor_log(severity, domain, "%d connections have failed%s", total, smartlist_len(items) > MAX_REASONS_TO_REPORT ? ". Top reasons:" : ":"); SMARTLIST_FOREACH_BEGIN(items, const broken_state_count_t *, c) { if (c_sl_idx > MAX_REASONS_TO_REPORT) break; - log(severity, domain, + tor_log(severity, domain, " %d connections died in state %s", (int)c->count, c->state); } SMARTLIST_FOREACH_END(c); @@ -282,6 +308,39 @@ connection_or_report_broken_states(int severity, int domain) smartlist_free(items); } +/** Call this to change or_connection_t states, so the owning channel_tls_t can + * be notified. + */ + +static void +connection_or_change_state(or_connection_t *conn, uint8_t state) +{ + uint8_t old_state; + + tor_assert(conn); + + old_state = conn->base_.state; + conn->base_.state = state; + + if (conn->chan) + channel_tls_handle_state_change_on_orconn(conn->chan, conn, + old_state, state); +} + +/** Return the number of circuits using an or_connection_t; this used to + * be an or_connection_t field, but it got moved to channel_t and we + * shouldn't maintain two copies. */ + +int +connection_or_get_num_circuits(or_connection_t *conn) +{ + tor_assert(conn); + + if (conn->chan) { + return channel_num_circuits(TLS_CHAN_TO_BASE(conn->chan)); + } else return 0; +} + /**************************************************************/ /** Pack the cell_t host-order structure <b>src</b> into network-order @@ -292,33 +351,56 @@ connection_or_report_broken_states(int severity, int domain) * should set it or clear it as appropriate. */ void -cell_pack(packed_cell_t *dst, const cell_t *src) +cell_pack(packed_cell_t *dst, const cell_t *src, int wide_circ_ids) { char *dest = dst->body; - set_uint16(dest, htons(src->circ_id)); - *(uint8_t*)(dest+2) = src->command; - memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE); + if (wide_circ_ids) { + set_uint32(dest, htonl(src->circ_id)); + dest += 4; + } else { + set_uint16(dest, htons(src->circ_id)); + dest += 2; + memset(dest+CELL_MAX_NETWORK_SIZE-2, 0, 2); /*make sure it's clear */ + } + set_uint8(dest, src->command); + memcpy(dest+1, src->payload, CELL_PAYLOAD_SIZE); } /** Unpack the network-order buffer <b>src</b> into a host-order * cell_t structure <b>dest</b>. */ static void -cell_unpack(cell_t *dest, const char *src) +cell_unpack(cell_t *dest, const char *src, int wide_circ_ids) { - dest->circ_id = ntohs(get_uint16(src)); - dest->command = *(uint8_t*)(src+2); - memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE); + if (wide_circ_ids) { + dest->circ_id = ntohl(get_uint32(src)); + src += 4; + } else { + dest->circ_id = ntohs(get_uint16(src)); + src += 2; + } + dest->command = get_uint8(src); + memcpy(dest->payload, src+1, CELL_PAYLOAD_SIZE); } -/** Write the header of <b>cell</b> into the first VAR_CELL_HEADER_SIZE - * bytes of <b>hdr_out</b>. */ -void -var_cell_pack_header(const var_cell_t *cell, char *hdr_out) +/** Write the header of <b>cell</b> into the first VAR_CELL_MAX_HEADER_SIZE + * bytes of <b>hdr_out</b>. Returns number of bytes used. */ +int +var_cell_pack_header(const var_cell_t *cell, char *hdr_out, int wide_circ_ids) { - set_uint16(hdr_out, htons(cell->circ_id)); - set_uint8(hdr_out+2, cell->command); - set_uint16(hdr_out+3, htons(cell->payload_len)); + int r; + if (wide_circ_ids) { + set_uint32(hdr_out, htonl(cell->circ_id)); + hdr_out += 4; + r = VAR_CELL_MAX_HEADER_SIZE; + } else { + set_uint16(hdr_out, htons(cell->circ_id)); + hdr_out += 2; + r = VAR_CELL_MAX_HEADER_SIZE - 2; + } + set_uint8(hdr_out, cell->command); + set_uint16(hdr_out+1, htons(cell->payload_len)); + return r; } /** Allocate and return a new var_cell_t with <b>payload_len</b> bytes of @@ -327,7 +409,7 @@ var_cell_t * var_cell_new(uint16_t payload_len) { size_t size = STRUCT_OFFSET(var_cell_t, payload) + payload_len; - var_cell_t *cell = tor_malloc(size); + var_cell_t *cell = tor_malloc_zero(size); cell->payload_len = payload_len; cell->command = 0; cell->circ_id = 0; @@ -345,8 +427,11 @@ var_cell_free(var_cell_t *cell) int connection_or_reached_eof(or_connection_t *conn) { + tor_assert(conn); + log_info(LD_OR,"OR connection reached EOF. Closing."); - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_normally(conn, 1); + return 0; } @@ -366,7 +451,7 @@ connection_or_process_inbuf(or_connection_t *conn) int ret = 0; tor_assert(conn); - switch (conn->_base.state) { + switch (conn->base_.state) { case OR_CONN_STATE_PROXY_HANDSHAKING: ret = connection_read_proxy_handshake(TO_CONN(conn)); @@ -375,9 +460,12 @@ connection_or_process_inbuf(or_connection_t *conn) tor_assert(TO_CONN(conn)->proxy_state == PROXY_CONNECTED); if (connection_tls_start_handshake(conn, 0) < 0) ret = -1; + /* Touch the channel's active timestamp if there is one */ + if (conn->chan) + channel_timestamp_active(TLS_CHAN_TO_BASE(conn->chan)); } if (ret < 0) { - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_for_error(conn, 0); } return ret; @@ -385,7 +473,7 @@ connection_or_process_inbuf(or_connection_t *conn) #ifdef USE_BUFFEREVENTS if (tor_tls_server_got_renegotiate(conn->tls)) connection_or_tls_renegotiated_cb(conn->tls, conn); - if (conn->_base.marked_for_close) + if (conn->base_.marked_for_close) return 0; /* fall through. */ #endif @@ -403,14 +491,14 @@ connection_or_process_inbuf(or_connection_t *conn) * * XXX024 Remove this check once we verify that the above paragraph is * 100% true. */ - if (buf_datalen(conn->_base.inbuf) > MAX_OR_INBUF_WHEN_NONOPEN) { + if (buf_datalen(conn->base_.inbuf) > MAX_OR_INBUF_WHEN_NONOPEN) { log_fn(LOG_PROTOCOL_WARN, LD_NET, "Accumulated too much data (%d bytes) " "on nonopen OR connection %s %s:%u in state %s; closing.", - (int)buf_datalen(conn->_base.inbuf), + (int)buf_datalen(conn->base_.inbuf), connection_or_nonopen_was_started_here(conn) ? "to" : "from", - conn->_base.address, conn->_base.port, - conn_state_to_string(conn->_base.type, conn->_base.state)); - connection_mark_for_close(TO_CONN(conn)); + conn->base_.address, conn->base_.port, + conn_state_to_string(conn->base_.type, conn->base_.state)); + connection_or_close_for_error(conn, 0); ret = -1; } @@ -430,18 +518,32 @@ connection_or_process_inbuf(or_connection_t *conn) int connection_or_flushed_some(or_connection_t *conn) { - size_t datalen = connection_get_outbuf_len(TO_CONN(conn)); + size_t datalen, temp; + ssize_t n, flushed; + size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids); + /* If we're under the low water mark, add cells until we're just over the * high water mark. */ + datalen = connection_get_outbuf_len(TO_CONN(conn)); if (datalen < OR_CONN_LOWWATER) { - 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; - flushed = connection_or_flush_from_first_active_circuit(conn, 1, now); - n -= flushed; + while ((conn->chan) && channel_tls_more_to_flush(conn->chan)) { + /* Compute how many more cells we want at most */ + n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, cell_network_size); + /* Bail out if we don't want any more */ + if (n <= 0) break; + /* We're still here; try to flush some more cells */ + flushed = channel_tls_flush_some_cells(conn->chan, n); + /* Bail out if it says it didn't flush anything */ + if (flushed <= 0) break; + /* How much in the outbuf now? */ + temp = connection_get_outbuf_len(TO_CONN(conn)); + /* Bail out if we didn't actually increase the outbuf size */ + if (temp <= datalen) break; + /* Update datalen for the next iteration */ + datalen = temp; } } + return 0; } @@ -459,14 +561,14 @@ connection_or_finished_flushing(or_connection_t *conn) tor_assert(conn); assert_connection_ok(TO_CONN(conn),0); - switch (conn->_base.state) { + switch (conn->base_.state) { case OR_CONN_STATE_PROXY_HANDSHAKING: case OR_CONN_STATE_OPEN: case OR_CONN_STATE_OR_HANDSHAKING_V2: case OR_CONN_STATE_OR_HANDSHAKING_V3: break; default: - log_err(LD_BUG,"Called in unexpected state %d.", conn->_base.state); + log_err(LD_BUG,"Called in unexpected state %d.", conn->base_.state); tor_fragile_assert(); return -1; } @@ -480,6 +582,7 @@ connection_or_finished_connecting(or_connection_t *or_conn) { const int proxy_type = or_conn->proxy_type; connection_t *conn; + tor_assert(or_conn); conn = TO_CONN(or_conn); tor_assert(conn->state == OR_CONN_STATE_CONNECTING); @@ -491,18 +594,18 @@ connection_or_finished_connecting(or_connection_t *or_conn) if (proxy_type != PROXY_NONE) { /* start proxy handshake */ if (connection_proxy_connect(conn, proxy_type) < 0) { - connection_mark_for_close(conn); + connection_or_close_for_error(or_conn, 0); return -1; } connection_start_reading(conn); - conn->state = OR_CONN_STATE_PROXY_HANDSHAKING; + connection_or_change_state(or_conn, OR_CONN_STATE_PROXY_HANDSHAKING); return 0; } if (connection_tls_start_handshake(or_conn, 0) < 0) { /* TLS handshaking error of some kind. */ - connection_mark_for_close(conn); + connection_or_close_for_error(or_conn, 0); return -1; } return 0; @@ -516,11 +619,19 @@ connection_or_about_to_close(or_connection_t *or_conn) time_t now = time(NULL); connection_t *conn = TO_CONN(or_conn); + /* Tell the controlling channel we're closed */ + if (or_conn->chan) { + channel_closed(TLS_CHAN_TO_BASE(or_conn->chan)); + /* + * NULL this out because the channel might hang around a little + * longer before channel_run_cleanup() gets it. + */ + or_conn->chan->conn = NULL; + or_conn->chan = NULL; + } + /* Remember why we're closing this connection. */ if (conn->state != OR_CONN_STATE_OPEN) { - /* Inform any pending (not attached) circs that they should - * give up. */ - circuit_n_conn_done(TO_OR_CONN(conn), 0); /* now mark things down as needed */ if (connection_or_nonopen_was_started_here(or_conn)) { const or_options_t *options = get_options(); @@ -548,9 +659,6 @@ connection_or_about_to_close(or_connection_t *or_conn) control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED, tls_error_to_orconn_end_reason(or_conn->tls_error)); } - /* Now close all the attached circuits on it. */ - circuit_unlink_all_from_or_conn(TO_OR_CONN(conn), - END_CIRC_REASON_OR_CONN_CLOSED); } /** Return 1 if identity digest <b>id_digest</b> is known to be a @@ -613,8 +721,8 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset, cfg = ev_token_bucket_cfg_new(rate_per_tick, burst, rate_per_tick, burst, tick); old_cfg = conn->bucket_cfg; - if (conn->_base.bufev) - tor_set_bufferevent_rate_limit(conn->_base.bufev, cfg); + if (conn->base_.bufev) + tor_set_bufferevent_rate_limit(conn->base_.bufev, cfg); if (old_cfg) ev_token_bucket_cfg_free(old_cfg); conn->bucket_cfg = cfg; @@ -663,15 +771,15 @@ connection_or_init_conn_from_address(or_connection_t *conn, 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); + conn->base_.port = port; + tor_addr_copy(&conn->base_.addr, addr); tor_addr_copy(&conn->real_addr, addr); if (r) { tor_addr_port_t node_ap; node_get_pref_orport(r, &node_ap); /* XXXX proposal 186 is making this more complex. For now, a conn is canonical when it uses the _preferred_ address. */ - if (tor_addr_eq(&conn->_base.addr, &node_ap.addr)) + if (tor_addr_eq(&conn->base_.addr, &node_ap.addr)) conn->is_canonical = 1; if (!started_here) { /* Override the addr/port, so our log messages will make sense. @@ -684,12 +792,12 @@ connection_or_init_conn_from_address(or_connection_t *conn, * right IP address and port 56244, that wouldn't be as helpful. now we * log the "right" port too, so we know if it's moria1 or moria2. */ - tor_addr_copy(&conn->_base.addr, &node_ap.addr); - conn->_base.port = node_ap.port; + tor_addr_copy(&conn->base_.addr, &node_ap.addr); + conn->base_.port = node_ap.port; } conn->nickname = tor_strdup(node_get_nickname(r)); - tor_free(conn->_base.address); - conn->_base.address = tor_dup_addr(&node_ap.addr); + tor_free(conn->base_.address); + conn->base_.address = tor_dup_addr(&node_ap.addr); } else { const char *n; /* If we're an authoritative directory server, we may know a @@ -703,157 +811,31 @@ connection_or_init_conn_from_address(or_connection_t *conn, base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, conn->identity_digest, DIGEST_LEN); } - tor_free(conn->_base.address); - conn->_base.address = tor_dup_addr(addr); + tor_free(conn->base_.address); + conn->base_.address = tor_dup_addr(addr); } } -/** Return true iff <b>a</b> is "better" than <b>b</b> for new circuits. - * - * A more canonical connection is always better than a less canonical - * connection. That aside, a connection is better if it has circuits and the - * other does not, or if it was created more recently. - * - * Requires that both input connections are open; not is_bad_for_new_circs, - * and not impossibly non-canonical. - * - * If <b>forgive_new_connections</b> is true, then we do not call - * <b>a</b>better than <b>b</b> simply because b has no circuits, - * unless b is also relatively old. - */ -static int -connection_or_is_better(time_t now, - const or_connection_t *a, - const or_connection_t *b, - int forgive_new_connections) -{ - int newer; -/** Do not definitively deprecate a new connection with no circuits on it - * until this much time has passed. */ -#define NEW_CONN_GRACE_PERIOD (15*60) - - if (b->is_canonical && !a->is_canonical) - return 0; /* A canonical connection is better than a non-canonical - * one, no matter how new it is or which has circuits. */ - - newer = b->_base.timestamp_created < a->_base.timestamp_created; - - if ( - /* We prefer canonical connections regardless of newness. */ - (!b->is_canonical && a->is_canonical) || - /* If both have circuits we prefer the newer: */ - (b->n_circuits && a->n_circuits && newer) || - /* If neither has circuits we prefer the newer: */ - (!b->n_circuits && !a->n_circuits && newer)) - return 1; +/** These just pass all the is_bad_for_new_circs manipulation on to + * channel_t */ - /* If one has no circuits and the other does... */ - if (!b->n_circuits && a->n_circuits) { - /* Then it's bad, unless it's in its grace period and we're forgiving. */ - if (forgive_new_connections && - now < b->_base.timestamp_created + NEW_CONN_GRACE_PERIOD) - return 0; - else - return 1; - } +static unsigned int +connection_or_is_bad_for_new_circs(or_connection_t *or_conn) +{ + tor_assert(or_conn); - return 0; + if (or_conn->chan) + return channel_is_bad_for_new_circs(TLS_CHAN_TO_BASE(or_conn->chan)); + else return 0; } -/** Return the OR connection we should use to extend a circuit to the router - * whose identity is <b>digest</b>, and whose address we believe (or have been - * told in an extend cell) is <b>target_addr</b>. If there is no good - * connection, set *<b>msg_out</b> to a message describing the connection's - * state and our next action, and set <b>launch_out</b> to a boolean for - * whether we should launch a new connection or not. - */ -or_connection_t * -connection_or_get_for_extend(const char *digest, - const tor_addr_t *target_addr, - const char **msg_out, - int *launch_out) +static void +connection_or_mark_bad_for_new_circs(or_connection_t *or_conn) { - or_connection_t *conn, *best=NULL; - int n_inprogress_goodaddr = 0, n_old = 0, n_noncanonical = 0, n_possible = 0; - time_t now = approx_time(); - - tor_assert(msg_out); - tor_assert(launch_out); - - if (!orconn_identity_map) { - *msg_out = "Router not connected (nothing is). Connecting."; - *launch_out = 1; - return NULL; - } - - conn = digestmap_get(orconn_identity_map, digest); - - for (; conn; conn = conn->next_with_same_id) { - tor_assert(conn->_base.magic == OR_CONNECTION_MAGIC); - tor_assert(conn->_base.type == CONN_TYPE_OR); - tor_assert(tor_memeq(conn->identity_digest, digest, DIGEST_LEN)); - if (conn->_base.marked_for_close) - continue; - /* Never return a connection on which the other end appears to be - * a client. */ - if (conn->is_connection_with_client) { - continue; - } - /* Never return a non-open connection. */ - if (conn->_base.state != OR_CONN_STATE_OPEN) { - /* If the address matches, don't launch a new connection for this - * circuit. */ - if (!tor_addr_compare(&conn->real_addr, target_addr, CMP_EXACT)) - ++n_inprogress_goodaddr; - continue; - } - /* Never return a connection that shouldn't be used for circs. */ - if (conn->is_bad_for_new_circs) { - ++n_old; - continue; - } - /* Never return a non-canonical connection using a recent link protocol - * if the address is not what we wanted. - * - * (For old link protocols, we can't rely on is_canonical getting - * set properly if we're talking to the right address, since we might - * have an out-of-date descriptor, and we will get no NETINFO cell to - * tell us about the right address.) */ - if (!conn->is_canonical && conn->link_proto >= 2 && - tor_addr_compare(&conn->real_addr, target_addr, CMP_EXACT)) { - ++n_noncanonical; - continue; - } - - ++n_possible; - - if (!best) { - best = conn; /* If we have no 'best' so far, this one is good enough. */ - continue; - } - - if (connection_or_is_better(now, conn, best, 0)) - best = conn; - } + tor_assert(or_conn); - if (best) { - *msg_out = "Connection is fine; using it."; - *launch_out = 0; - return best; - } else if (n_inprogress_goodaddr) { - *msg_out = "Connection in progress; waiting."; - *launch_out = 0; - return NULL; - } else if (n_old || n_noncanonical) { - *msg_out = "Connections all too old, or too non-canonical. " - " Launching a new one."; - *launch_out = 1; - return NULL; - } else { - *msg_out = "Not connected. Connecting."; - *launch_out = 1; - return NULL; - } + if (or_conn->chan) + channel_mark_bad_for_new_circs(TLS_CHAN_TO_BASE(or_conn->chan)); } /** How old do we let a connection to an OR get before deciding it's @@ -874,8 +856,8 @@ connection_or_get_for_extend(const char *digest, * - 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. + * See channel_is_better() in channel.c for our idea of what makes one OR + * connection better than another. */ static void connection_or_group_set_badness(or_connection_t *head, int force) @@ -887,23 +869,23 @@ connection_or_group_set_badness(or_connection_t *head, int force) /* Pass 1: expire everything that's old, and see what the status of * everything else is. */ for (or_conn = head; or_conn; or_conn = or_conn->next_with_same_id) { - if (or_conn->_base.marked_for_close || - or_conn->is_bad_for_new_circs) + if (or_conn->base_.marked_for_close || + connection_or_is_bad_for_new_circs(or_conn)) continue; if (force || - or_conn->_base.timestamp_created + TIME_BEFORE_OR_CONN_IS_TOO_OLD + 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).", - or_conn->_base.address, or_conn->_base.port, or_conn->_base.s, - (int)(now - or_conn->_base.timestamp_created)); - or_conn->is_bad_for_new_circs = 1; + "(fd "TOR_SOCKET_T_FORMAT", %d secs old).", + or_conn->base_.address, or_conn->base_.port, or_conn->base_.s, + (int)(now - or_conn->base_.timestamp_created)); + connection_or_mark_bad_for_new_circs(or_conn); } - if (or_conn->is_bad_for_new_circs) { + if (connection_or_is_bad_for_new_circs(or_conn)) { ++n_old; - } else if (or_conn->_base.state != OR_CONN_STATE_OPEN) { + } else if (or_conn->base_.state != OR_CONN_STATE_OPEN) { ++n_inprogress; } else if (or_conn->is_canonical) { ++n_canonical; @@ -915,10 +897,10 @@ connection_or_group_set_badness(or_connection_t *head, int force) /* Pass 2: We know how about how good the best connection is. * expire everything that's worse, and find the very best if we can. */ for (or_conn = head; or_conn; or_conn = or_conn->next_with_same_id) { - if (or_conn->_base.marked_for_close || - or_conn->is_bad_for_new_circs) + if (or_conn->base_.marked_for_close || + connection_or_is_bad_for_new_circs(or_conn)) continue; /* This one doesn't need to be marked bad. */ - if (or_conn->_base.state != OR_CONN_STATE_OPEN) + if (or_conn->base_.state != OR_CONN_STATE_OPEN) continue; /* Don't mark anything bad until we have seen what happens * when the connection finishes. */ if (n_canonical && !or_conn->is_canonical) { @@ -926,16 +908,21 @@ connection_or_group_set_badness(or_connection_t *head, int force) * and this one is open but not canonical. Mark it bad. */ log_info(LD_OR, "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, - (int)(now - or_conn->_base.timestamp_created)); - or_conn->is_bad_for_new_circs = 1; + "(fd "TOR_SOCKET_T_FORMAT", %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, + (int)(now - or_conn->base_.timestamp_created)); + connection_or_mark_bad_for_new_circs(or_conn); continue; } - if (!best || connection_or_is_better(now, or_conn, best, 0)) + if (!best || + channel_is_better(now, + TLS_CHAN_TO_BASE(or_conn->chan), + TLS_CHAN_TO_BASE(best->chan), + 0)) { best = or_conn; + } } if (!best) @@ -956,32 +943,37 @@ connection_or_group_set_badness(or_connection_t *head, int force) * "mostly harmless", so a fix can wait until somebody is bored. */ for (or_conn = head; or_conn; or_conn = or_conn->next_with_same_id) { - if (or_conn->_base.marked_for_close || - or_conn->is_bad_for_new_circs || - or_conn->_base.state != OR_CONN_STATE_OPEN) + if (or_conn->base_.marked_for_close || + connection_or_is_bad_for_new_circs(or_conn) || + or_conn->base_.state != OR_CONN_STATE_OPEN) continue; - if (or_conn != best && connection_or_is_better(now, best, or_conn, 1)) { + if (or_conn != best && + channel_is_better(now, + TLS_CHAN_TO_BASE(best->chan), + TLS_CHAN_TO_BASE(or_conn->chan), 1)) { /* This isn't the best conn, _and_ the best conn is better than it, even when we're being forgiving. */ if (best->is_canonical) { log_info(LD_OR, "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, - (int)(now - or_conn->_base.timestamp_created), - best->_base.s, (int)(now - best->_base.timestamp_created)); - or_conn->is_bad_for_new_circs = 1; + "(fd "TOR_SOCKET_T_FORMAT", %d secs old). " + "We have a better canonical one " + "(fd "TOR_SOCKET_T_FORMAT"; %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)); + connection_or_mark_bad_for_new_circs(or_conn); } 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 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)); - or_conn->is_bad_for_new_circs = 1; + "(fd "TOR_SOCKET_T_FORMAT", %d secs old). We have a better " + "one with the " + "same address (fd "TOR_SOCKET_T_FORMAT"; %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)); + connection_or_mark_bad_for_new_circs(or_conn); } } } @@ -1019,8 +1011,41 @@ connection_or_connect_failed(or_connection_t *conn, control_event_bootstrap_problem(msg, reason); } +/** <b>conn</b> got an error in connection_handle_read_impl() or + * connection_handle_write_impl() and is going to die soon. + * + * <b>reason</b> specifies the or_conn_end_reason for the failure; + * <b>msg</b> specifies the strerror-style error message. + */ +void +connection_or_notify_error(or_connection_t *conn, + int reason, const char *msg) +{ + channel_t *chan; + + tor_assert(conn); + + /* If we're connecting, call connect_failed() too */ + if (TO_CONN(conn)->state == OR_CONN_STATE_CONNECTING) + connection_or_connect_failed(conn, reason, msg); + + /* Tell the controlling channel if we have one */ + if (conn->chan) { + chan = TLS_CHAN_TO_BASE(conn->chan); + /* Don't transition if we're already in closing, closed or error */ + if (!(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR)) { + channel_close_for_error(chan); + } + } + + /* No need to mark for error because connection.c is about to do that */ +} + /** Launch a new OR connection to <b>addr</b>:<b>port</b> and expect to - * handshake with an OR with identity digest <b>id_digest</b>. + * handshake with an OR with identity digest <b>id_digest</b>. Optionally, + * pass in a pointer to a channel using this connection. * * If <b>id_digest</b> is me, do nothing. If we're already connected to it, * return that connection. If the connect() is in progress, set the @@ -1035,7 +1060,8 @@ connection_or_connect_failed(or_connection_t *conn, */ or_connection_t * connection_or_connect(const tor_addr_t *_addr, uint16_t port, - const char *id_digest) + const char *id_digest, + channel_tls_t *chan) { or_connection_t *conn; const or_options_t *options = get_options(); @@ -1058,9 +1084,17 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, conn = or_connection_new(tor_addr_family(&addr)); - /* set up conn so it's got all the data we need to remember */ + /* + * Set up conn so it's got all the data we need to remember for channels + * + * This stuff needs to happen before connection_or_init_conn_from_address() + * so connection_or_set_identity_digest() and such know where to look to + * keep the channel up to date. + */ + conn->chan = chan; + chan->conn = conn; connection_or_init_conn_from_address(conn, &addr, port, id_digest, 1); - conn->_base.state = OR_CONN_STATE_CONNECTING; + connection_or_change_state(conn, OR_CONN_STATE_CONNECTING); control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0); conn->is_outgoing = 1; @@ -1072,7 +1106,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, if (proxy_type != PROXY_NONE) { tor_addr_copy(&addr, &proxy_addr); port = proxy_port; - conn->_base.proxy_state = PROXY_INFANT; + conn->base_.proxy_state = PROXY_INFANT; } } else { /* get_proxy_addrport() might fail if we have a Bridge line that @@ -1084,29 +1118,29 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, TO_CONN(conn)->port); if (transport_name) { - log_warn(LD_GENERAL, "We were supposed to connect to bridge '%s:%u' " + log_warn(LD_GENERAL, "We were supposed to connect to bridge '%s' " "using pluggable transport '%s', but we can't find a pluggable " "transport proxy supporting '%s'. This can happen if you " "haven't provided a ClientTransportPlugin line, or if " "your pluggable transport proxy stopped running.", - fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port, + fmt_addrport(&TO_CONN(conn)->addr, TO_CONN(conn)->port), transport_name, transport_name); } else { - log_warn(LD_GENERAL, "Tried to connect to '%s:%u' through a proxy, but " + log_warn(LD_GENERAL, "Tried to connect to '%s' through a proxy, but " "the proxy address could not be found.", - fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port); + fmt_addrport(&TO_CONN(conn)->addr, TO_CONN(conn)->port)); } connection_free(TO_CONN(conn)); return NULL; } - switch (connection_connect(TO_CONN(conn), conn->_base.address, + switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr, port, &socket_error)) { case -1: /* If the connection failed immediately, and we're using * a proxy, our proxy is down. Don't blame the Tor server. */ - if (conn->_base.proxy_state == PROXY_INFANT) + if (conn->base_.proxy_state == PROXY_INFANT) entry_guard_register_connect_status(conn->identity_digest, 0, 1, time(NULL)); connection_or_connect_failed(conn, @@ -1129,6 +1163,62 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, return conn; } +/** Mark orconn for close and transition the associated channel, if any, to + * the closing state. + * + * It's safe to call this and connection_or_close_for_error() any time, and + * channel layer will treat it as a connection closing for reasons outside + * its control, like the remote end closing it. It can also be a local + * reason that's specific to connection_t/or_connection_t rather than + * the channel mechanism, such as expiration of old connections in + * run_connection_housekeeping(). If you want to close a channel_t + * from somewhere that logically works in terms of generic channels + * rather than connections, use channel_mark_for_close(); see also + * the comment on that function in channel.c. + */ + +void +connection_or_close_normally(or_connection_t *orconn, int flush) +{ + channel_t *chan = NULL; + + tor_assert(orconn); + if (flush) connection_mark_and_flush_internal(TO_CONN(orconn)); + else connection_mark_for_close_internal(TO_CONN(orconn)); + if (orconn->chan) { + chan = TLS_CHAN_TO_BASE(orconn->chan); + /* Don't transition if we're already in closing, closed or error */ + if (!(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR)) { + channel_close_from_lower_layer(chan); + } + } +} + +/** Mark orconn for close and transition the associated channel, if any, to + * the error state. + */ + +void +connection_or_close_for_error(or_connection_t *orconn, int flush) +{ + channel_t *chan = NULL; + + tor_assert(orconn); + if (flush) connection_mark_and_flush_internal(TO_CONN(orconn)); + else connection_mark_for_close_internal(TO_CONN(orconn)); + if (orconn->chan) { + chan = TLS_CHAN_TO_BASE(orconn->chan); + /* Don't transition if we're already in closing, closed or error */ + if (!(chan->state == CHANNEL_STATE_CLOSING || + chan->state == CHANNEL_STATE_CLOSED || + chan->state == CHANNEL_STATE_ERROR)) { + channel_close_for_error(chan); + } + } +} + /** Begin the tls handshake with <b>conn</b>. <b>receiving</b> is 0 if * we initiated the connection, else it's 1. * @@ -1140,29 +1230,46 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, int connection_tls_start_handshake(or_connection_t *conn, int receiving) { - conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING; + channel_listener_t *chan_listener; + channel_t *chan; + + /* Incoming connections will need a new channel passed to the + * channel_tls_listener */ + if (receiving) { + /* It shouldn't already be set */ + tor_assert(!(conn->chan)); + chan_listener = channel_tls_get_listener(); + if (!chan_listener) { + chan_listener = channel_tls_start_listener(); + command_setup_listener(chan_listener); + } + chan = channel_tls_handle_incoming(conn); + channel_listener_queue_incoming(chan_listener, chan); + } + + connection_or_change_state(conn, OR_CONN_STATE_TLS_HANDSHAKING); tor_assert(!conn->tls); - conn->tls = tor_tls_new(conn->_base.s, receiving); + conn->tls = tor_tls_new(conn->base_.s, receiving); if (!conn->tls) { log_warn(LD_BUG,"tor_tls_new failed. Closing."); return -1; } tor_tls_set_logged_address(conn->tls, // XXX client and relay? - escaped_safe_str(conn->_base.address)); + escaped_safe_str(conn->base_.address)); #ifdef USE_BUFFEREVENTS if (connection_type_uses_bufferevent(TO_CONN(conn))) { - const int filtering = get_options()->_UseFilteringSSLBufferevents; + const int filtering = get_options()->UseFilteringSSLBufferevents; struct bufferevent *b = - tor_tls_init_bufferevent(conn->tls, conn->_base.bufev, conn->_base.s, + tor_tls_init_bufferevent(conn->tls, conn->base_.bufev, conn->base_.s, receiving, filtering); if (!b) { log_warn(LD_BUG,"tor_tls_init_bufferevent failed. Closing."); return -1; } - conn->_base.bufev = b; + conn->base_.bufev = b; if (conn->bucket_cfg) - tor_set_bufferevent_rate_limit(conn->_base.bufev, conn->bucket_cfg); + tor_set_bufferevent_rate_limit(conn->base_.bufev, conn->bucket_cfg); connection_enable_rate_limiting(TO_CONN(conn)); connection_configure_bufferevent_callbacks(TO_CONN(conn)); @@ -1174,7 +1281,8 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving) } #endif connection_start_reading(TO_CONN(conn)); - log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s); + log_debug(LD_HANDSHAKE,"starting TLS handshake on fd "TOR_SOCKET_T_FORMAT, + conn->base_.s); note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C); IF_HAS_BUFFEREVENT(TO_CONN(conn), { @@ -1211,7 +1319,7 @@ connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn) if (connection_tls_finish_handshake(conn) < 0) { /* XXXX_TLS double-check that it's ok to do this from inside read. */ /* XXXX_TLS double-check that this verifies certificates. */ - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_for_error(conn, 0); } } @@ -1226,12 +1334,12 @@ connection_tls_continue_handshake(or_connection_t *conn) int result; check_no_tls_errors(); again: - if (conn->_base.state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) { + if (conn->base_.state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) { // log_notice(LD_OR, "Renegotiate with %p", conn->tls); result = tor_tls_renegotiate(conn->tls); // log_notice(LD_OR, "Result: %d", result); } else { - tor_assert(conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING); + tor_assert(conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING); // log_notice(LD_OR, "Continue handshake with %p", conn->tls); result = tor_tls_handshake(conn->tls); // log_notice(LD_OR, "Result: %d", result); @@ -1244,19 +1352,21 @@ connection_tls_continue_handshake(or_connection_t *conn) case TOR_TLS_DONE: if (! tor_tls_used_v1_handshake(conn->tls)) { if (!tor_tls_is_server(conn->tls)) { - if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) { + if (conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING) { if (tor_tls_received_v3_certificate(conn->tls)) { log_info(LD_OR, "Client got a v3 cert! Moving on to v3 " - "handshake."); + "handshake with ciphersuite %s", + tor_tls_get_ciphersuite_name(conn->tls)); return connection_or_launch_v3_or_handshake(conn); } else { log_debug(LD_OR, "Done with initial SSL handshake (client-side)." " Requesting renegotiation."); - conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING; + connection_or_change_state(conn, + OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING); goto again; } } - // log_notice(LD_OR,"Done. state was %d.", conn->_base.state); + // log_notice(LD_OR,"Done. state was %d.", conn->base_.state); } else { /* v2/v3 handshake, but not a client. */ log_debug(LD_OR, "Done with initial SSL handshake (server-side). " @@ -1264,7 +1374,8 @@ connection_tls_continue_handshake(or_connection_t *conn) tor_tls_set_renegotiate_callback(conn->tls, connection_or_tls_renegotiated_cb, conn); - conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING; + connection_or_change_state(conn, + OR_CONN_STATE_TLS_SERVER_RENEGOTIATING); connection_stop_writing(TO_CONN(conn)); connection_start_reading(TO_CONN(conn)); return 0; @@ -1294,28 +1405,29 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event, /* XXXX cut-and-paste code; should become a function. */ if (event & BEV_EVENT_CONNECTED) { - if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) { + if (conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING) { if (tor_tls_finish_handshake(conn->tls) < 0) { log_warn(LD_OR, "Problem finishing handshake"); - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_for_error(conn, 0); return; } } if (! tor_tls_used_v1_handshake(conn->tls)) { if (!tor_tls_is_server(conn->tls)) { - if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) { + if (conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING) { if (tor_tls_received_v3_certificate(conn->tls)) { log_info(LD_OR, "Client got a v3 cert!"); if (connection_or_launch_v3_or_handshake(conn) < 0) - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_for_error(conn, 0); return; } else { - conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING; + connection_or_change_state(conn, + OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING); tor_tls_unblock_renegotiation(conn->tls); - if (bufferevent_ssl_renegotiate(conn->_base.bufev)<0) { + if (bufferevent_ssl_renegotiate(conn->base_.bufev)<0) { log_warn(LD_OR, "Start_renegotiating went badly."); - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_for_error(conn, 0); } tor_tls_unblock_renegotiation(conn->tls); return; /* ???? */ @@ -1330,7 +1442,8 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event, tor_tls_set_renegotiate_callback(conn->tls, connection_or_tls_renegotiated_cb, conn); - conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING; + connection_or_change_state(conn, + OR_CONN_STATE_TLS_SERVER_RENEGOTIATING); } else if (handshakes == 2) { /* v2 handshake, as a server. Two handshakes happened already, * so we treat renegotiation as done. @@ -1339,18 +1452,18 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event, } else if (handshakes > 2) { log_warn(LD_OR, "More than two handshakes done on connection. " "Closing."); - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_for_error(conn, 0); } else { log_warn(LD_BUG, "We were unexpectedly told that a connection " "got %d handshakes. Closing.", handshakes); - connection_mark_for_close(TO_CONN(conn)); + connection_or_close_for_error(conn, 0); } return; } } connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT); if (connection_tls_finish_handshake(conn) < 0) - connection_mark_for_close(TO_CONN(conn)); /* ???? */ + connection_or_close_for_error(conn, 0); /* ???? */ return; } @@ -1372,7 +1485,7 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event, int connection_or_nonopen_was_started_here(or_connection_t *conn) { - tor_assert(conn->_base.type == CONN_TYPE_OR); + tor_assert(conn->base_.type == CONN_TYPE_OR); if (!conn->tls) return 1; /* it's still in proxy states or something */ if (conn->handshake_state) @@ -1380,29 +1493,6 @@ connection_or_nonopen_was_started_here(or_connection_t *conn) return !tor_tls_is_server(conn->tls); } -/** Set the circid_type field of <b>conn</b> (which determines which part of - * the circuit ID space we're willing to use) based on comparing our ID to - * <b>identity_rcvd</b> */ -void -connection_or_set_circid_type(or_connection_t *conn, - crypto_pk_t *identity_rcvd) -{ - const int started_here = connection_or_nonopen_was_started_here(conn); - crypto_pk_t *our_identity = - started_here ? get_tlsclient_identity_key() : - get_server_identity_key(); - - if (identity_rcvd) { - if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) { - conn->circ_id_type = CIRC_ID_TYPE_LOWER; - } else { - conn->circ_id_type = CIRC_ID_TYPE_HIGHER; - } - } else { - conn->circ_id_type = CIRC_ID_TYPE_NEITHER; - } -} - /** <b>Conn</b> just completed its handshake. Return 0 if all is well, and * return -1 if he is lying, broken, or otherwise something is wrong. * @@ -1437,8 +1527,8 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, const or_options_t *options = get_options(); int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN; const char *safe_address = - started_here ? conn->_base.address : - safe_str_client(conn->_base.address); + started_here ? conn->base_.address : + safe_str_client(conn->base_.address); const char *conn_type = started_here ? "outgoing" : "incoming"; int has_cert = 0; @@ -1447,7 +1537,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, if (started_here && !has_cert) { log_info(LD_HANDSHAKE,"Tried connecting to router at %s:%d, but it didn't " "send a cert! Closing.", - safe_address, conn->_base.port); + safe_address, conn->base_.port); return -1; } else if (!has_cert) { log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. " @@ -1461,7 +1551,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, if (started_here && v<0) { 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); + safe_address, conn->base_.port); return -1; } else if (v<0) { log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert " @@ -1469,7 +1559,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, } else { log_debug(LD_HANDSHAKE, "The certificate seems to be valid on %s connection " - "with %s:%d", conn_type, safe_address, conn->_base.port); + "with %s:%d", conn_type, safe_address, conn->base_.port); } check_no_tls_errors(); } @@ -1480,7 +1570,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, memset(digest_rcvd_out, 0, DIGEST_LEN); } - connection_or_set_circid_type(conn, identity_rcvd); + tor_assert(conn->chan); + channel_set_circid_type(TLS_CHAN_TO_BASE(conn->chan), identity_rcvd, 1); + crypto_pk_free(identity_rcvd); if (started_here) @@ -1521,10 +1613,10 @@ connection_or_client_learned_peer_id(or_connection_t *conn, conn->identity_digest, DIGEST_LEN); 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); + 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, + learned_router_identity(&conn->base_.addr, conn->base_.port, (const char*)peer_id); } @@ -1538,7 +1630,7 @@ connection_or_client_learned_peer_id(or_connection_t *conn, 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); + conn->base_.address, conn->base_.port, expected, seen); entry_guard_register_connect_status(conn->identity_digest, 0, 1, time(NULL)); control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, @@ -1550,13 +1642,26 @@ connection_or_client_learned_peer_id(or_connection_t *conn, return -1; } if (authdir_mode_tests_reachability(options)) { - dirserv_orconn_tls_done(conn->_base.address, conn->_base.port, + dirserv_orconn_tls_done(&conn->base_.addr, conn->base_.port, (const char*)peer_id); } return 0; } +/** Return when a client used this, for connection.c, since client_used + * is now one of the timestamps of channel_t */ + +time_t +connection_or_client_used(or_connection_t *conn) +{ + tor_assert(conn); + + if (conn->chan) { + return channel_when_last_client(TLS_CHAN_TO_BASE(conn->chan)); + } else return 0; +} + /** The v1/v2 TLS handshake is finished. * * Make sure we are happy with the person we just handshaked with. @@ -1576,10 +1681,12 @@ connection_tls_finish_handshake(or_connection_t *conn) char digest_rcvd[DIGEST_LEN]; int started_here = connection_or_nonopen_was_started_here(conn); - log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done. verifying.", + log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done, using " + "ciphersuite %s. verifying.", started_here?"outgoing":"incoming", conn, - safe_str_client(conn->_base.address)); + safe_str_client(conn->base_.address), + tor_tls_get_ciphersuite_name(conn->tls)); directory_set_dirty(); @@ -1592,18 +1699,18 @@ connection_tls_finish_handshake(or_connection_t *conn) if (tor_tls_used_v1_handshake(conn->tls)) { conn->link_proto = 1; if (!started_here) { - connection_or_init_conn_from_address(conn, &conn->_base.addr, - conn->_base.port, digest_rcvd, 0); + connection_or_init_conn_from_address(conn, &conn->base_.addr, + conn->base_.port, digest_rcvd, 0); } tor_tls_block_renegotiation(conn->tls); return connection_or_set_state_open(conn); } else { - conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V2; + connection_or_change_state(conn, OR_CONN_STATE_OR_HANDSHAKING_V2); if (connection_init_or_handshake_state(conn, started_here) < 0) return -1; if (!started_here) { - connection_or_init_conn_from_address(conn, &conn->_base.addr, - conn->_base.port, digest_rcvd, 0); + connection_or_init_conn_from_address(conn, &conn->base_.addr, + conn->base_.port, digest_rcvd, 0); } return connection_or_send_versions(conn, 0); } @@ -1623,7 +1730,7 @@ connection_or_launch_v3_or_handshake(or_connection_t *conn) circuit_build_times_network_is_live(&circ_times); - conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V3; + connection_or_change_state(conn, OR_CONN_STATE_OR_HANDSHAKING_V3); if (connection_init_or_handshake_state(conn, 1) < 0) return -1; @@ -1671,10 +1778,12 @@ or_handshake_state_free(or_handshake_state_t *state) * authenticate cell.) */ void -or_handshake_state_record_cell(or_handshake_state_t *state, +or_handshake_state_record_cell(or_connection_t *conn, + or_handshake_state_t *state, const cell_t *cell, int incoming) { + size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids); crypto_digest_t *d, **dptr; packed_cell_t packed; if (incoming) { @@ -1696,8 +1805,8 @@ or_handshake_state_record_cell(or_handshake_state_t *state, d = *dptr; /* Re-packing like this is a little inefficient, but we don't have to do this very often at all. */ - cell_pack(&packed, cell); - crypto_digest_add_bytes(d, packed.body, sizeof(packed.body)); + cell_pack(&packed, cell, conn->wide_circ_ids); + crypto_digest_add_bytes(d, packed.body, cell_network_size); memwipe(&packed, 0, sizeof(packed)); } @@ -1710,12 +1819,14 @@ or_handshake_state_record_cell(or_handshake_state_t *state, * authenticate cell.) */ void -or_handshake_state_record_var_cell(or_handshake_state_t *state, +or_handshake_state_record_var_cell(or_connection_t *conn, + or_handshake_state_t *state, const var_cell_t *cell, int incoming) { crypto_digest_t *d, **dptr; - char buf[VAR_CELL_HEADER_SIZE]; + int n; + char buf[VAR_CELL_MAX_HEADER_SIZE]; if (incoming) { if (!state->digest_received_data) return; @@ -1729,8 +1840,8 @@ or_handshake_state_record_var_cell(or_handshake_state_t *state, d = *dptr; - var_cell_pack_header(cell, buf); - crypto_digest_add_bytes(d, buf, sizeof(buf)); + n = var_cell_pack_header(cell, buf, conn->wide_circ_ids); + crypto_digest_add_bytes(d, buf, n); crypto_digest_add_bytes(d, (const char *)cell->payload, cell->payload_len); memwipe(buf, 0, sizeof(buf)); @@ -1742,35 +1853,9 @@ or_handshake_state_record_var_cell(or_handshake_state_t *state, int connection_or_set_state_open(or_connection_t *conn) { - int started_here = connection_or_nonopen_was_started_here(conn); - time_t now = time(NULL); - conn->_base.state = OR_CONN_STATE_OPEN; + connection_or_change_state(conn, OR_CONN_STATE_OPEN); 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) { - /* Close any circuits pending on this conn. We leave it in state - * 'open' though, because it didn't actually *fail* -- we just - * chose not to use it. (Otherwise - * connection_about_to_close_connection() will call a big pile of - * functions to indicate we shouldn't try it again.) */ - log_debug(LD_OR, "New entry guard was reachable, but closing this " - "connection so we can retry the earlier entry guards."); - circuit_n_conn_done(conn, 0); - return -1; - } - router_set_status(conn->identity_digest, 1); - } else { - /* only report it to the geoip module if it's not a known router */ - if (!router_get_by_id_digest(conn->identity_digest)) { - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(conn)->addr, - now); - } - } - or_handshake_state_free(conn->handshake_state); conn->handshake_state = NULL; IF_HAS_BUFFEREVENT(TO_CONN(conn), { @@ -1779,8 +1864,6 @@ connection_or_set_state_open(or_connection_t *conn) connection_start_reading(TO_CONN(conn)); } - circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */ - return 0; } @@ -1792,16 +1875,21 @@ void connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn) { packed_cell_t networkcell; + size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids); tor_assert(cell); tor_assert(conn); - cell_pack(&networkcell, cell); + cell_pack(&networkcell, cell, conn->wide_circ_ids); + + connection_write_to_buf(networkcell.body, cell_network_size, TO_CONN(conn)); - connection_write_to_buf(networkcell.body, CELL_NETWORK_SIZE, TO_CONN(conn)); + /* Touch the channel's active timestamp if there is one */ + if (conn->chan) + channel_timestamp_active(TLS_CHAN_TO_BASE(conn->chan)); - if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) - or_handshake_state_record_cell(conn->handshake_state, cell, 0); + if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) + or_handshake_state_record_cell(conn, conn->handshake_state, cell, 0); if (cell->command != CELL_PADDING) conn->timestamp_last_added_nonpadding = approx_time(); @@ -1815,17 +1903,22 @@ void connection_or_write_var_cell_to_buf(const var_cell_t *cell, or_connection_t *conn) { - char hdr[VAR_CELL_HEADER_SIZE]; + int n; + char hdr[VAR_CELL_MAX_HEADER_SIZE]; tor_assert(cell); tor_assert(conn); - var_cell_pack_header(cell, hdr); - connection_write_to_buf(hdr, sizeof(hdr), TO_CONN(conn)); + n = var_cell_pack_header(cell, hdr, conn->wide_circ_ids); + connection_write_to_buf(hdr, n, TO_CONN(conn)); connection_write_to_buf((char*)cell->payload, cell->payload_len, TO_CONN(conn)); - if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) - or_handshake_state_record_var_cell(conn->handshake_state, cell, 0); + if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) + or_handshake_state_record_var_cell(conn, conn->handshake_state, cell, 0); if (cell->command != CELL_PADDING) conn->timestamp_last_added_nonpadding = approx_time(); + + /* Touch the channel's active timestamp if there is one */ + if (conn->chan) + channel_timestamp_active(TLS_CHAN_TO_BASE(conn->chan)); } /** See whether there's a variable-length cell waiting on <b>or_conn</b>'s @@ -1856,59 +1949,48 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn) while (1) { log_debug(LD_OR, - "%d: starting, inbuf_datalen %d (%d pending in tls object).", - conn->_base.s,(int)connection_get_inbuf_len(TO_CONN(conn)), + TOR_SOCKET_T_FORMAT": starting, inbuf_datalen %d " + "(%d pending in tls object).", + conn->base_.s,(int)connection_get_inbuf_len(TO_CONN(conn)), tor_tls_get_pending_bytes(conn->tls)); if (connection_fetch_var_cell_from_buf(conn, &var_cell)) { if (!var_cell) return 0; /* not yet. */ + + /* Touch the channel's active timestamp if there is one */ + if (conn->chan) + channel_timestamp_active(TLS_CHAN_TO_BASE(conn->chan)); + circuit_build_times_network_is_live(&circ_times); - command_process_var_cell(var_cell, conn); + channel_tls_handle_var_cell(var_cell, conn); var_cell_free(var_cell); } else { - char buf[CELL_NETWORK_SIZE]; + const int wide_circ_ids = conn->wide_circ_ids; + size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids); + char buf[CELL_MAX_NETWORK_SIZE]; cell_t cell; if (connection_get_inbuf_len(TO_CONN(conn)) - < CELL_NETWORK_SIZE) /* whole response available? */ + < cell_network_size) /* whole response available? */ return 0; /* not yet */ + /* Touch the channel's active timestamp if there is one */ + if (conn->chan) + channel_timestamp_active(TLS_CHAN_TO_BASE(conn->chan)); + circuit_build_times_network_is_live(&circ_times); - connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, TO_CONN(conn)); + connection_fetch_from_buf(buf, cell_network_size, TO_CONN(conn)); /* retrieve cell info from buf (create the host-order struct from the * network-order string) */ - cell_unpack(&cell, buf); + cell_unpack(&cell, buf, wide_circ_ids); - command_process_cell(&cell, conn); + channel_tls_handle_cell(&cell, conn); } } } -/** Write a destroy cell with circ ID <b>circ_id</b> and reason <b>reason</b> - * onto OR connection <b>conn</b>. Don't perform range-checking on reason: - * we may want to propagate reasons from other cells. - * - * Return 0. - */ -int -connection_or_send_destroy(circid_t circ_id, or_connection_t *conn, int reason) -{ - cell_t cell; - - tor_assert(conn); - - memset(&cell, 0, sizeof(cell_t)); - cell.circ_id = circ_id; - cell.command = CELL_DESTROY; - cell.payload[0] = (uint8_t) reason; - log_debug(LD_OR,"Sending destroy (circID %d).", circ_id); - - connection_or_write_cell_to_buf(&cell, conn); - return 0; -} - /** Array of recognized link protocol versions. */ -static const uint16_t or_protocol_versions[] = { 1, 2, 3 }; +static const uint16_t or_protocol_versions[] = { 1, 2, 3, 4 }; /** Number of versions in <b>or_protocol_versions</b>. */ static const int n_or_protocol_versions = (int)( sizeof(or_protocol_versions)/sizeof(uint16_t) ); @@ -1984,16 +2066,17 @@ connection_or_send_netinfo(or_connection_t *conn) memset(&cell, 0, sizeof(cell_t)); cell.command = CELL_NETINFO; - /* Timestamp. */ - set_uint32(cell.payload, htonl((uint32_t)now)); + /* Timestamp, if we're a relay. */ + if (public_server_mode(get_options()) || ! conn->is_outgoing) + set_uint32(cell.payload, htonl((uint32_t)now)); /* Their address. */ out = cell.payload + 4; /* We use &conn->real_addr below, unless it hasn't yet been set. If it - * hasn't yet been set, we know that _base.addr hasn't been tampered with + * hasn't yet been set, we know that base_.addr hasn't been tampered with * yet either. */ len = append_address_to_payload(out, !tor_addr_is_null(&conn->real_addr) - ? &conn->real_addr : &conn->_base.addr); + ? &conn->real_addr : &conn->base_.addr); if (len<0) return -1; out += len; @@ -2004,12 +2087,19 @@ connection_or_send_netinfo(or_connection_t *conn) if ((public_server_mode(get_options()) || !conn->is_outgoing) && (me = router_get_my_routerinfo())) { tor_addr_t my_addr; - *out++ = 1; /* only one address is supported. */ + *out++ = 1 + !tor_addr_is_null(&me->ipv6_addr); tor_addr_from_ipv4h(&my_addr, me->addr); len = append_address_to_payload(out, &my_addr); if (len < 0) return -1; + out += len; + + if (!tor_addr_is_null(&me->ipv6_addr)) { + len = append_address_to_payload(out, &me->ipv6_addr); + if (len < 0) + return -1; + } } else { *out = 0; } @@ -2034,7 +2124,7 @@ connection_or_send_certs_cell(or_connection_t *conn) ssize_t pos; int server_mode; - tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3); + tor_assert(conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3); if (! conn->handshake_state) return -1; @@ -2081,7 +2171,7 @@ connection_or_send_auth_challenge_cell(or_connection_t *conn) var_cell_t *cell; uint8_t *cp; uint8_t challenge[OR_AUTH_CHALLENGE_LEN]; - tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3); + tor_assert(conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3); if (! conn->handshake_state) return -1; @@ -2212,19 +2302,11 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, if (server) return V3_AUTH_FIXED_PART_LEN; // ptr-out - /* Time: 8 octets. */ - { - uint64_t now = time(NULL); - if ((time_t)now < 0) - return -1; - set_uint32(ptr, htonl((uint32_t)(now>>32))); - set_uint32(ptr+4, htonl((uint32_t)now)); - ptr += 8; - } - - /* Nonce: 16 octets. */ - crypto_rand((char*)ptr, 16); - ptr += 16; + /* 8 octets were reserved for the current time, but we're trying to get out + * of the habit of sending time around willynilly. Fortunately, nothing + * checks it. That's followed by 16 bytes of nonce. */ + crypto_rand((char*)ptr, 24); + ptr += 24; tor_assert(ptr - out == V3_AUTH_BODY_LEN); diff --git a/src/or/connection_or.h b/src/or/connection_or.h index b78c444921..85e68f1a33 100644 --- a/src/or/connection_or.h +++ b/src/or/connection_or.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for connection_or.c. **/ -#ifndef _TOR_CONNECTION_OR_H -#define _TOR_CONNECTION_OR_H +#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); @@ -34,8 +34,14 @@ void connection_or_update_token_buckets(smartlist_t *conns, void connection_or_connect_failed(or_connection_t *conn, int reason, const char *msg); +void connection_or_notify_error(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); + const char *id_digest, + channel_tls_t *chan); + +void connection_or_close_normally(or_connection_t *orconn, int flush); +void connection_or_close_for_error(or_connection_t *orconn, int flush); void connection_or_report_broken_states(int severity, int domain); @@ -51,13 +57,15 @@ void connection_or_init_conn_from_address(or_connection_t *conn, int started_here); int connection_or_client_learned_peer_id(or_connection_t *conn, const uint8_t *peer_id); -void connection_or_set_circid_type(or_connection_t *conn, - crypto_pk_t *identity_rcvd); +time_t connection_or_client_used(or_connection_t *conn); +int connection_or_get_num_circuits(or_connection_t *conn); void or_handshake_state_free(or_handshake_state_t *state); -void or_handshake_state_record_cell(or_handshake_state_t *state, +void or_handshake_state_record_cell(or_connection_t *conn, + or_handshake_state_t *state, const cell_t *cell, int incoming); -void or_handshake_state_record_var_cell(or_handshake_state_t *state, +void or_handshake_state_record_var_cell(or_connection_t *conn, + or_handshake_state_t *state, const var_cell_t *cell, int incoming); @@ -66,8 +74,6 @@ 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_versions(or_connection_t *conn, int v3_plus); int connection_or_send_netinfo(or_connection_t *conn); int connection_or_send_certs_cell(or_connection_t *conn); @@ -80,10 +86,14 @@ int connection_or_send_authenticate_cell(or_connection_t *conn, int type); int is_or_protocol_version_known(uint16_t version); -void cell_pack(packed_cell_t *dest, const cell_t *src); -void var_cell_pack_header(const var_cell_t *cell, char *hdr_out); +void cell_pack(packed_cell_t *dest, const cell_t *src, int wide_circ_ids); +int var_cell_pack_header(const var_cell_t *cell, char *hdr_out, + int wide_circ_ids); var_cell_t *var_cell_new(uint16_t payload_len); void var_cell_free(var_cell_t *cell); +/** DOCDOC */ +#define MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS 4 + #endif diff --git a/src/or/control.c b/src/or/control.c index 913d18a7fc..a88de12d69 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,11 +11,16 @@ #define CONTROL_PRIVATE #include "or.h" +#include "addressmap.h" #include "buffers.h" +#include "channel.h" +#include "channeltls.h" #include "circuitbuild.h" #include "circuitlist.h" +#include "circuitstats.h" #include "circuituse.h" #include "config.h" +#include "confparse.h" #include "connection.h" #include "connection_edge.h" #include "connection_or.h" @@ -23,6 +28,7 @@ #include "directory.h" #include "dirserv.h" #include "dnsserv.h" +#include "entrynodes.h" #include "geoip.h" #include "hibernate.h" #include "main.h" @@ -50,7 +56,7 @@ * because it is used both as a list of v0 event types, and as indices * into the bitfield to determine which controllers want which events. */ -#define _EVENT_MIN 0x0001 +#define EVENT_MIN_ 0x0001 #define EVENT_CIRCUIT_STATUS 0x0001 #define EVENT_STREAM_STATUS 0x0002 #define EVENT_OR_CONN_STATUS 0x0003 @@ -76,8 +82,8 @@ #define EVENT_BUILDTIMEOUT_SET 0x0017 #define EVENT_SIGNAL 0x0018 #define EVENT_CONF_CHANGED 0x0019 -#define _EVENT_MAX 0x0019 -/* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */ +#define EVENT_MAX_ 0x0019 +/* If EVENT_MAX_ ever hits 0x0020, we need to make the mask wider. */ /** Bitfield: The bit 1<<e is set if <b>any</b> open control * connection is interested in events of type <b>e</b>. We use this @@ -592,7 +598,7 @@ send_control_event_string(uint16_t event, event_format_t which, { smartlist_t *conns = get_connection_array(); (void)which; - tor_assert(event >= _EVENT_MIN && event <= _EVENT_MAX); + tor_assert(event >= EVENT_MIN_ && event <= EVENT_MAX_); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->type == CONN_TYPE_CONTROL && @@ -1215,9 +1221,10 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, connection_mark_for_close(TO_CONN(conn)); return 0; ok: - log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->_base.s); + log_info(LD_CONTROL, "Authenticated control connection ("TOR_SOCKET_T_FORMAT + ")", conn->base_.s); send_control_done(conn); - conn->_base.state = CONTROL_CONN_STATE_OPEN; + conn->base_.state = CONTROL_CONN_STATE_OPEN; tor_free(password); if (sl) { /* clean up */ SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); @@ -1243,6 +1250,27 @@ handle_control_saveconf(control_connection_t *conn, uint32_t len, return 0; } +struct signal_t { + int sig; + const char *signal_name; +}; + +static const struct signal_t signal_table[] = { + { SIGHUP, "RELOAD" }, + { SIGHUP, "HUP" }, + { SIGINT, "SHUTDOWN" }, + { SIGUSR1, "DUMP" }, + { SIGUSR1, "USR1" }, + { SIGUSR2, "DEBUG" }, + { SIGUSR2, "USR2" }, + { SIGTERM, "HALT" }, + { SIGTERM, "TERM" }, + { SIGTERM, "INT" }, + { SIGNEWNYM, "NEWNYM" }, + { SIGCLEARDNSCACHE, "CLEARDNSCACHE"}, + { 0, NULL }, +}; + /** Called when we get a SIGNAL command. React to the provided signal, and * report success or failure. (If the signal results in a shutdown, success * may not be reported.) */ @@ -1250,7 +1278,8 @@ static int handle_control_signal(control_connection_t *conn, uint32_t len, const char *body) { - int sig; + int sig = -1; + int i; int n = 0; char *s; @@ -1259,27 +1288,19 @@ handle_control_signal(control_connection_t *conn, uint32_t len, while (body[n] && ! TOR_ISSPACE(body[n])) ++n; s = tor_strndup(body, n); - if (!strcasecmp(s, "RELOAD") || !strcasecmp(s, "HUP")) - sig = SIGHUP; - else if (!strcasecmp(s, "SHUTDOWN") || !strcasecmp(s, "INT")) - sig = SIGINT; - else if (!strcasecmp(s, "DUMP") || !strcasecmp(s, "USR1")) - sig = SIGUSR1; - else if (!strcasecmp(s, "DEBUG") || !strcasecmp(s, "USR2")) - sig = SIGUSR2; - else if (!strcasecmp(s, "HALT") || !strcasecmp(s, "TERM")) - sig = SIGTERM; - else if (!strcasecmp(s, "NEWNYM")) - sig = SIGNEWNYM; - else if (!strcasecmp(s, "CLEARDNSCACHE")) - sig = SIGCLEARDNSCACHE; - else { + + for (i = 0; signal_table[i].signal_name != NULL; ++i) { + if (!strcasecmp(s, signal_table[i].signal_name)) { + sig = signal_table[i].sig; + break; + } + } + + if (sig < 0) connection_printf_to_buf(conn, "552 Unrecognized signal code \"%s\"\r\n", s); - sig = -1; - } tor_free(s); - if (sig<0) + if (sig < 0) return 0; send_control_done(conn); @@ -1306,7 +1327,7 @@ handle_control_takeownership(control_connection_t *conn, uint32_t len, log_info(LD_CONTROL, "Control connection %d has taken ownership of this " "Tor instance.", - (int)(conn->_base.s)); + (int)(conn->base_.s)); send_control_done(conn); return 0; @@ -1352,10 +1373,13 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len, "512-syntax error: invalid address '%s'", to); log_warn(LD_CONTROL, "Skipping invalid argument '%s' in MapAddress msg", to); - } else if (!strcmp(from, ".") || !strcmp(from, "0.0.0.0")) { + } else if (!strcmp(from, ".") || !strcmp(from, "0.0.0.0") || + !strcmp(from, "::")) { + const char type = + !strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : + (!strcmp(from, "0.0.0.0") ? RESOLVED_TYPE_IPV4 : RESOLVED_TYPE_IPV6); const char *address = addressmap_register_virtual_address( - !strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : RESOLVED_TYPE_IPV4, - tor_strdup(to)); + type, tor_strdup(to)); if (!address) { smartlist_add_asprintf(reply, "451-resource exhausted: skipping '%s'", line); @@ -1440,6 +1464,16 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, *answer = smartlist_join_strings(event_names, " ", 0, NULL); smartlist_free(event_names); + } else if (!strcmp(question, "signal/names")) { + smartlist_t *signal_names = smartlist_new(); + int j; + for (j = 0; signal_table[j].signal_name != NULL; ++j) { + smartlist_add(signal_names, (char*)signal_table[j].signal_name); + } + + *answer = smartlist_join_strings(signal_names, " ", 0, NULL); + + smartlist_free(signal_names); } else if (!strcmp(question, "features/names")) { *answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS"); } else if (!strcmp(question, "address")) { @@ -1614,10 +1648,13 @@ getinfo_helper_dir(control_connection_t *control_conn, const char *question, char **answer, const char **errmsg) { - const routerinfo_t *ri; + const node_t *node; + const routerinfo_t *ri = NULL; (void) control_conn; if (!strcmpstart(question, "desc/id/")) { - ri = router_get_by_hexdigest(question+strlen("desc/id/")); + node = node_get_by_hex_id(question+strlen("desc/id/")); + if (node) + ri = node->ri; if (ri) { const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) @@ -1626,7 +1663,9 @@ getinfo_helper_dir(control_connection_t *control_conn, } else if (!strcmpstart(question, "desc/name/")) { /* XXX023 Setting 'warn_if_unnamed' here is a bit silly -- the * warning goes to the user, not to the controller. */ - ri = router_get_by_nickname(question+strlen("desc/name/"),1); + node = node_get_by_nickname(question+strlen("desc/name/"), 1); + if (node) + ri = node->ri; if (ri) { const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) @@ -1672,8 +1711,7 @@ getinfo_helper_dir(control_connection_t *control_conn, const node_t *node = node_get_by_hex_id(question+strlen("md/id/")); const microdesc_t *md = NULL; if (node) md = node->md; - if (md) { - tor_assert(md->body); + if (md && md->body) { *answer = tor_strndup(md->body, md->bodylen); } } else if (!strcmpstart(question, "md/name/")) { @@ -1683,13 +1721,13 @@ getinfo_helper_dir(control_connection_t *control_conn, /* XXXX duplicated code */ const microdesc_t *md = NULL; if (node) md = node->md; - if (md) { - tor_assert(md->body); + if (md && md->body) { *answer = tor_strndup(md->body, md->bodylen); } } else if (!strcmpstart(question, "desc-annotations/id/")) { - ri = router_get_by_hexdigest(question+ - strlen("desc-annotations/id/")); + node = node_get_by_hex_id(question+strlen("desc-annotations/id/")); + if (node) + ri = node->ri; if (ri) { const char *annotations = signed_descriptor_get_annotations(&ri->cache_info); @@ -1847,11 +1885,11 @@ circuit_describe_status_for_controller(origin_circuit_t *circ) } smartlist_add_asprintf(descparts, "PURPOSE=%s", - circuit_purpose_to_controller_string(circ->_base.purpose)); + circuit_purpose_to_controller_string(circ->base_.purpose)); { const char *hs_state = - circuit_purpose_to_controller_hs_state_string(circ->_base.purpose); + circuit_purpose_to_controller_hs_state_string(circ->base_.purpose); if (hs_state != NULL) { smartlist_add_asprintf(descparts, "HS_STATE=%s", hs_state); @@ -1865,7 +1903,7 @@ circuit_describe_status_for_controller(origin_circuit_t *circ) { char tbuf[ISO_TIME_USEC_LEN+1]; - format_iso_time_nospace_usec(tbuf, &circ->_base.timestamp_created); + format_iso_time_nospace_usec(tbuf, &circ->base_.timestamp_created); smartlist_add_asprintf(descparts, "TIME_CREATED=%s", tbuf); } @@ -1889,7 +1927,7 @@ getinfo_helper_events(control_connection_t *control_conn, if (!strcmp(question, "circuit-status")) { circuit_t *circ_; smartlist_t *status = smartlist_new(); - for (circ_ = _circuit_get_global_list(); circ_; circ_ = circ_->next) { + for (circ_ = circuit_get_global_list_(); circ_; circ_ = circ_->next) { origin_circuit_t *circ; char *circdesc; const char *state; @@ -1897,7 +1935,7 @@ getinfo_helper_events(control_connection_t *control_conn, continue; circ = TO_ORIGIN_CIRCUIT(circ_); - if (circ->_base.state == CIRCUIT_STATE_OPEN) + if (circ->base_.state == CIRCUIT_STATE_OPEN) state = "BUILT"; else if (circ->cpath) state = "EXTENDED"; @@ -1974,7 +2012,7 @@ getinfo_helper_events(control_connection_t *control_conn, if (base_conn->type != CONN_TYPE_OR || base_conn->marked_for_close) continue; conn = TO_OR_CONN(base_conn); - if (conn->_base.state == OR_CONN_STATE_OPEN) + if (conn->base_.state == OR_CONN_STATE_OPEN) state = "CONNECTED"; else if (conn->nickname) state = "LAUNCHED"; @@ -2130,10 +2168,14 @@ static const getinfo_item_t getinfo_items[] = { PREFIX("config/", config, "Current configuration values."), DOC("config/names", "List of configuration options, types, and documentation."), + DOC("config/defaults", + "List of default values for configuration options. " + "See also config/names"), ITEM("info/names", misc, "List of GETINFO options, types, and documentation."), ITEM("events/names", misc, "Events that the controller can ask for with SETEVENTS."), + ITEM("signal/names", misc, "Signal names recognized by the SIGNAL command"), ITEM("features/names", misc, "What arguments can USEFEATURE take?"), PREFIX("desc/id/", dir, "Router descriptors by ID."), PREFIX("desc/name/", dir, "Router descriptors by nickname."), @@ -2497,7 +2539,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, goto done; } } else { - if (circ->_base.state == CIRCUIT_STATE_OPEN) { + if (circ->base_.state == CIRCUIT_STATE_OPEN) { int err_reason = 0; circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING); if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) { @@ -2630,7 +2672,7 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, TO_CONN(edge_conn)->state = AP_CONN_STATE_CONTROLLER_WAIT; } - if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) { + if (circ && (circ->base_.state != CIRCUIT_STATE_OPEN)) { connection_write_str_to_buf( "551 Can't attach stream to non-open origin circuit\r\n", conn); @@ -2895,7 +2937,7 @@ handle_control_resolve(control_connection_t *conn, uint32_t len, failed = smartlist_new(); SMARTLIST_FOREACH(args, const char *, arg, { if (!is_keyval_pair(arg)) { - if (dnsserv_launch_request(arg, is_reverse)<0) + if (dnsserv_launch_request(arg, is_reverse, conn)<0) smartlist_add(failed, (char*)arg); } }); @@ -2903,7 +2945,7 @@ handle_control_resolve(control_connection_t *conn, uint32_t len, send_control_done(conn); SMARTLIST_FOREACH(failed, const char *, arg, { control_event_address_mapped(arg, arg, time(NULL), - "Unable to launch resolve request"); + "internal", 0); }); SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); @@ -3099,6 +3141,8 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len, "SERVERNONCE=%s\r\n", server_hash_encoded, server_nonce_encoded); + + tor_free(client_nonce); return 0; } @@ -3198,7 +3242,7 @@ connection_control_closed(control_connection_t *conn) static int is_valid_initial_command(control_connection_t *conn, const char *cmd) { - if (conn->_base.state == CONTROL_CONN_STATE_OPEN) + if (conn->base_.state == CONTROL_CONN_STATE_OPEN) return 1; if (!strcasecmp(cmd, "PROTOCOLINFO")) return (!conn->have_sent_protocolinfo && @@ -3243,8 +3287,8 @@ connection_control_process_inbuf(control_connection_t *conn) char *args; tor_assert(conn); - tor_assert(conn->_base.state == CONTROL_CONN_STATE_OPEN || - conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH); + tor_assert(conn->base_.state == CONTROL_CONN_STATE_OPEN || + conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH); if (!conn->incoming_cmd) { conn->incoming_cmd = tor_malloc(1024); @@ -3252,7 +3296,7 @@ connection_control_process_inbuf(control_connection_t *conn) conn->incoming_cmd_cur_len = 0; } - if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH && + if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH && peek_connection_has_control0_command(TO_CONN(conn))) { /* Detect v0 commands and send a "no more v0" message. */ size_t body_len; @@ -3351,7 +3395,7 @@ connection_control_process_inbuf(control_connection_t *conn) return 0; } - if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH && + if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH && !is_valid_initial_command(conn, conn->incoming_cmd)) { connection_write_str_to_buf("514 Authentication required.\r\n", conn); connection_mark_for_close(TO_CONN(conn)); @@ -3538,9 +3582,9 @@ control_event_circuit_status_minor(origin_circuit_t *circ, /* event_tail can currently be up to 130 chars long */ const char *hs_state_str = circuit_purpose_to_controller_hs_state_string(purpose); - const struct timeval *old_timestamp_created = tv; + const struct timeval *old_timestamp_began = tv; char tbuf[ISO_TIME_USEC_LEN+1]; - format_iso_time_nospace_usec(tbuf, old_timestamp_created); + format_iso_time_nospace_usec(tbuf, old_timestamp_began); tor_snprintf(event_tail, sizeof(event_tail), " OLD_PURPOSE=%s%s%s OLD_TIME_CREATED=%s", @@ -3696,9 +3740,22 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp, } } - if (tp == STREAM_EVENT_NEW) { - tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d", - ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port); + if (tp == STREAM_EVENT_NEW || tp == STREAM_EVENT_NEW_RESOLVE) { + /* + * When the control conn is an AF_UNIX socket and we have no address, + * it gets set to "(Tor_internal)"; see dnsserv_launch_request() in + * dnsserv.c. + */ + if (strcmp(ENTRY_TO_CONN(conn)->address, "(Tor_internal)") != 0) { + tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d", + ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port); + } else { + /* + * else leave it blank so control on AF_UNIX doesn't need to make + * something up. + */ + addrport_buf[0] = '\0'; + } } else { addrport_buf[0] = '\0'; } @@ -3706,11 +3763,7 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp, if (tp == STREAM_EVENT_NEW_RESOLVE) { purpose = " PURPOSE=DNS_REQUEST"; } else if (tp == STREAM_EVENT_NEW) { - if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request || - (conn->socks_request && - SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command))) - purpose = " PURPOSE=DNS_REQUEST"; - else if (conn->use_begindir) { + if (conn->use_begindir) { connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn; int linked_dir_purpose = -1; if (linked && linked->type == CONN_TYPE_DIR) @@ -3755,7 +3808,7 @@ orconn_target_get_name(char *name, size_t len, or_connection_t *conn) DIGEST_LEN); } else { tor_snprintf(name, len, "%s:%d", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); } } @@ -3787,8 +3840,12 @@ control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t tp, log_warn(LD_BUG, "Unrecognized status code %d", (int)tp); return 0; } - ncircs = circuit_count_pending_on_or_conn(conn); - ncircs += conn->n_circuits; + if (conn->chan) { + ncircs = circuit_count_pending_on_channel(TLS_CHAN_TO_BASE(conn->chan)); + } else { + ncircs = 0; + } + ncircs += connection_or_get_num_circuits(conn); if (ncircs && (tp == OR_CONN_EVENT_FAILED || tp == OR_CONN_EVENT_CLOSED)) { tor_snprintf(ncircs_buf, sizeof(ncircs_buf), "%sNCIRCS=%d", reason ? " " : "", ncircs); @@ -3817,7 +3874,7 @@ control_event_stream_bandwidth(edge_connection_t *edge_conn) 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), + U64_PRINTF_ARG(edge_conn->base_.global_identifier), (unsigned long)edge_conn->n_read, (unsigned long)edge_conn->n_written); @@ -3846,7 +3903,7 @@ control_event_stream_bandwidth_used(void) 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), + U64_PRINTF_ARG(edge_conn->base_.global_identifier), (unsigned long)edge_conn->n_read, (unsigned long)edge_conn->n_written); @@ -3978,15 +4035,17 @@ control_event_descriptors_changed(smartlist_t *routers) */ int control_event_address_mapped(const char *from, const char *to, time_t expires, - const char *error) + const char *error, const int cached) { if (!EVENT_IS_INTERESTING(EVENT_ADDRMAP)) return 0; if (expires < 3 || expires == TIME_MAX) send_control_event(EVENT_ADDRMAP, ALL_FORMATS, - "650 ADDRMAP %s %s NEVER %s\r\n", from, to, - error?error:""); + "650 ADDRMAP %s %s NEVER %s%s" + "CACHED=\"%s\"\r\n", + from, to, error?error:"", error?" ":"", + cached?"YES":"NO"); else { char buf[ISO_TIME_LEN+1]; char buf2[ISO_TIME_LEN+1]; @@ -3994,10 +4053,10 @@ control_event_address_mapped(const char *from, const char *to, time_t expires, format_iso_time(buf2,expires); send_control_event(EVENT_ADDRMAP, ALL_FORMATS, "650 ADDRMAP %s %s \"%s\"" - " %s%sEXPIRES=\"%s\"\r\n", + " %s%sEXPIRES=\"%s\" CACHED=\"%s\"\r\n", from, to, buf, error?error:"", error?" ":"", - buf2); + buf2, cached?"YES":"NO"); } return 0; @@ -4345,7 +4404,7 @@ control_event_guard(const char *nickname, const char *digest, * a smartlist_t containing (key, value, ...) pairs in sequence. * <b>value</b> can be NULL. */ int -control_event_conf_changed(smartlist_t *elements) +control_event_conf_changed(const smartlist_t *elements) { int i; char *result; @@ -4615,7 +4674,7 @@ control_event_bootstrap(bootstrap_status_t status, int progress) if (status > bootstrap_percent || (progress && progress > bootstrap_percent)) { bootstrap_status_to_string(status, &tag, &summary); - log(status ? LOG_NOTICE : LOG_INFO, LD_CONTROL, + tor_log(status ? LOG_NOTICE : LOG_INFO, LD_CONTROL, "Bootstrapped %d%%: %s.", progress ? progress : status, summary); tor_snprintf(buf, sizeof(buf), "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\"", @@ -4667,6 +4726,9 @@ control_event_bootstrap_problem(const char *warn, int reason) !any_pending_bridge_descriptor_fetches()) recommendation = "warn"; + if (we_are_hibernating()) + recommendation = "ignore"; + while (status>=0 && bootstrap_status_to_string(status, &tag, &summary) < 0) status--; /* find a recognized status string based on current progress */ status = bootstrap_percent; /* set status back to the actual number */ diff --git a/src/or/control.h b/src/or/control.h index f301ce91be..61062da2c4 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for control.c. **/ -#ifndef _TOR_CONTROL_H -#define _TOR_CONTROL_H +#ifndef TOR_CONTROL_H +#define TOR_CONTROL_H void control_update_global_event_mask(void); void control_adjust_event_log_severity(void); @@ -53,7 +53,8 @@ int control_event_stream_bandwidth_used(void); void control_event_logmsg(int severity, uint32_t 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); + time_t expires, const char *error, + const int cached); int control_event_or_authdir_new_descriptor(const char *action, const char *desc, size_t desclen, @@ -71,7 +72,7 @@ int control_event_server_status(int severity, const char *format, ...) CHECK_PRINTF(2,3); int control_event_guard(const char *nickname, const char *digest, const char *status); -int control_event_conf_changed(smartlist_t *elements); +int control_event_conf_changed(const smartlist_t *elements); int control_event_buildtimeout_set(const circuit_build_times_t *cbt, buildtimeout_set_event_t type); int control_event_signal(uintptr_t signal); diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 0255227e7b..ecf0d2035d 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,16 +11,19 @@ * * Right now, we only use this for processing onionskins. **/ - #include "or.h" #include "buffers.h" +#include "channel.h" +#include "channeltls.h" #include "circuitbuild.h" #include "circuitlist.h" #include "config.h" #include "connection.h" +#include "connection_or.h" #include "cpuworker.h" #include "main.h" #include "onion.h" +#include "rephist.h" #include "router.h" /** The maximum number of cpuworker processes we will keep around. */ @@ -29,10 +32,7 @@ #define MIN_CPUWORKERS 1 /** The tag specifies which circuit this onionskin was from. */ -#define TAG_LEN 10 -/** How many bytes are sent from the cpuworker back to tor? */ -#define LEN_ONION_RESPONSE \ - (1+TAG_LEN+ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN) +#define TAG_LEN 12 /** How many cpuworkers we have running right now. */ static int num_cpuworkers=0; @@ -68,22 +68,80 @@ connection_cpu_finished_flushing(connection_t *conn) /** Pack global_id and circ_id; set *tag to the result. (See note on * cpuworker_main for wire format.) */ static void -tag_pack(char *tag, uint64_t conn_id, circid_t circ_id) +tag_pack(uint8_t *tag, uint64_t chan_id, circid_t circ_id) { /*XXXX RETHINK THIS WHOLE MESS !!!! !NM NM NM NM*/ - set_uint64(tag, conn_id); - set_uint16(tag+8, circ_id); + /*XXXX DOUBLEPLUSTHIS!!!! AS AS AS AS*/ + set_uint64(tag, chan_id); + set_uint32(tag+8, circ_id); } /** Unpack <b>tag</b> into addr, port, and circ_id. */ static void -tag_unpack(const char *tag, uint64_t *conn_id, circid_t *circ_id) +tag_unpack(const uint8_t *tag, uint64_t *chan_id, circid_t *circ_id) { - *conn_id = get_uint64(tag); - *circ_id = get_uint16(tag+8); + *chan_id = get_uint64(tag); + *circ_id = get_uint32(tag+8); } +/** Magic numbers to make sure our cpuworker_requests don't grow any + * mis-framing bugs. */ +#define CPUWORKER_REQUEST_MAGIC 0xda4afeed +#define CPUWORKER_REPLY_MAGIC 0x5eedf00d + +/** A request sent to a cpuworker. */ +typedef struct cpuworker_request_t { + /** Magic number; must be CPUWORKER_REQUEST_MAGIC. */ + uint32_t magic; + /** Opaque tag to identify the job */ + uint8_t tag[TAG_LEN]; + /** Task code. Must be one of CPUWORKER_TASK_* */ + uint8_t task; + + /** Flag: Are we timing this request? */ + unsigned timed : 1; + /** If we're timing this request, when was it sent to the cpuworker? */ + struct timeval started_at; + + /** A create cell for the cpuworker to process. */ + create_cell_t create_cell; + + /* Turn the above into a tagged union if needed. */ +} cpuworker_request_t; + +/** A reply sent by a cpuworker. */ +typedef struct cpuworker_reply_t { + /** Magic number; must be CPUWORKER_REPLY_MAGIC. */ + uint32_t magic; + /** Opaque tag to identify the job; matches the request's tag.*/ + uint8_t tag[TAG_LEN]; + /** True iff we got a successful request. */ + uint8_t success; + + /** Are we timing this request? */ + unsigned int timed : 1; + /** What handshake type was the request? (Used for timing) */ + uint16_t handshake_type; + /** When did we send the request to the cpuworker? */ + struct timeval started_at; + /** Once the cpuworker received the request, how many microseconds did it + * take? (This shouldn't overflow; 4 billion micoseconds is over an hour, + * and we'll never have an onion handshake that takes so long.) */ + uint32_t n_usec; + + /** Output of processing a create cell + * + * @{ + */ + /** The created cell to send back. */ + created_cell_t created_cell; + /** The keys to use on this circuit. */ + uint8_t keys[CPATH_KEY_MATERIAL_LEN]; + /** Input to use for authenticating introduce1 cells. */ + uint8_t rend_auth_material[DIGEST_LEN]; +} cpuworker_reply_t; + /** Called when the onion key has changed and we need to spawn new * cpuworkers. Close all currently idle cpuworkers, and mark the last * rotation time as now. @@ -122,6 +180,112 @@ connection_cpu_reached_eof(connection_t *conn) return 0; } +/** Indexed by handshake type: how many onionskins have we processed and + * counted of that type? */ +static uint64_t onionskins_n_processed[MAX_ONION_HANDSHAKE_TYPE+1]; +/** Indexed by handshake type, corresponding to the onionskins counted in + * onionskins_n_processed: how many microseconds have we spent in cpuworkers + * processing that kind of onionskin? */ +static uint64_t onionskins_usec_internal[MAX_ONION_HANDSHAKE_TYPE+1]; +/** Indexed by handshake type, corresponding to onionskins counted in + * onionskins_n_processed: how many microseconds have we spent waiting for + * cpuworkers to give us answers for that kind of onionskin? + */ +static uint64_t onionskins_usec_roundtrip[MAX_ONION_HANDSHAKE_TYPE+1]; + +/** If any onionskin takes longer than this, we clip them to this + * time. (microseconds) */ +#define MAX_BELIEVABLE_ONIONSKIN_DELAY (2*1000*1000) + +static tor_weak_rng_t request_sample_rng = TOR_WEAK_RNG_INIT; + +/** Return true iff we'd like to measure a handshake of type + * <b>onionskin_type</b>. Call only from the main thread. */ +static int +should_time_request(uint16_t onionskin_type) +{ + /* If we've never heard of this type, we shouldn't even be here. */ + if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE) + return 0; + /* Measure the first N handshakes of each type, to ensure we have a + * sample */ + if (onionskins_n_processed[onionskin_type] < 4096) + return 1; + /** Otherwise, measure with P=1/128. We avoid doing this for every + * handshake, since the measurement itself can take a little time. */ + return tor_weak_random_one_in_n(&request_sample_rng, 128); +} + +/** Return an estimate of how many microseconds we will need for a single + * cpuworker to to process <b>n_requests</b> onionskins of type + * <b>onionskin_type</b>. */ +uint64_t +estimated_usec_for_onionskins(uint32_t n_requests, uint16_t onionskin_type) +{ + if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE) /* should be impossible */ + return 1000 * (uint64_t)n_requests; + if (PREDICT_UNLIKELY(onionskins_n_processed[onionskin_type] < 100)) { + /* Until we have 100 data points, just asssume everything takes 1 msec. */ + return 1000 * (uint64_t)n_requests; + } else { + /* This can't overflow: we'll never have more than 500000 onionskins + * measured in onionskin_usec_internal, and they won't take anything near + * 1 sec each, and we won't have anything like 1 million queued + * onionskins. But that's 5e5 * 1e6 * 1e6, which is still less than + * UINT64_MAX. */ + return (onionskins_usec_internal[onionskin_type] * n_requests) / + onionskins_n_processed[onionskin_type]; + } +} + +/** Compute the absolute and relative overhead of using the cpuworker + * framework for onionskins of type <b>onionskin_type</b>.*/ +static int +get_overhead_for_onionskins(uint32_t *usec_out, double *frac_out, + uint16_t onionskin_type) +{ + uint64_t overhead; + + *usec_out = 0; + *frac_out = 0.0; + + if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE) /* should be impossible */ + return -1; + if (onionskins_n_processed[onionskin_type] == 0 || + onionskins_usec_internal[onionskin_type] == 0 || + onionskins_usec_roundtrip[onionskin_type] == 0) + return -1; + + overhead = onionskins_usec_roundtrip[onionskin_type] - + onionskins_usec_internal[onionskin_type]; + + *usec_out = (uint32_t)(overhead / onionskins_n_processed[onionskin_type]); + *frac_out = U64_TO_DBL(overhead) / onionskins_usec_internal[onionskin_type]; + + return 0; +} + +/** If we've measured overhead for onionskins of type <b>onionskin_type</b>, + * log it. */ +void +cpuworker_log_onionskin_overhead(int severity, int onionskin_type, + const char *onionskin_type_name) +{ + uint32_t overhead; + double relative_overhead; + int r; + + r = get_overhead_for_onionskins(&overhead, &relative_overhead, + onionskin_type); + if (!overhead || r<0) + return; + + log_fn(severity, LD_OR, + "%s onionskins have averaged %u usec overhead (%.2f%%) in " + "cpuworker code ", + onionskin_type_name, (unsigned)overhead, relative_overhead*100); +} + /** Called when we get data from a cpuworker. If the answer is not complete, * wait for a complete answer. If the answer is complete, * process it as appropriate. @@ -129,12 +293,9 @@ connection_cpu_reached_eof(connection_t *conn) int connection_cpu_process_inbuf(connection_t *conn) { - char success; - char buf[LEN_ONION_RESPONSE]; - uint64_t conn_id; + uint64_t chan_id; circid_t circ_id; - connection_t *tmp_conn; - or_connection_t *p_conn = NULL; + channel_t *p_chan = NULL; circuit_t *circ; tor_assert(conn); @@ -144,25 +305,51 @@ connection_cpu_process_inbuf(connection_t *conn) return 0; if (conn->state == CPUWORKER_STATE_BUSY_ONION) { - if (connection_get_inbuf_len(conn) < LEN_ONION_RESPONSE) + cpuworker_reply_t rpl; + if (connection_get_inbuf_len(conn) < sizeof(cpuworker_reply_t)) return 0; /* not yet */ - tor_assert(connection_get_inbuf_len(conn) == LEN_ONION_RESPONSE); - - connection_fetch_from_buf(&success,1,conn); - connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn); - + tor_assert(connection_get_inbuf_len(conn) == sizeof(cpuworker_reply_t)); + + connection_fetch_from_buf((void*)&rpl,sizeof(cpuworker_reply_t),conn); + + tor_assert(rpl.magic == CPUWORKER_REPLY_MAGIC); + + if (rpl.timed && rpl.success && + rpl.handshake_type <= MAX_ONION_HANDSHAKE_TYPE) { + /* Time how long this request took. The handshake_type check should be + needless, but let's leave it in to be safe. */ + struct timeval tv_end, tv_diff; + int64_t usec_roundtrip; + tor_gettimeofday(&tv_end); + timersub(&tv_end, &rpl.started_at, &tv_diff); + usec_roundtrip = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec; + if (usec_roundtrip >= 0 && + usec_roundtrip < MAX_BELIEVABLE_ONIONSKIN_DELAY) { + ++onionskins_n_processed[rpl.handshake_type]; + onionskins_usec_internal[rpl.handshake_type] += rpl.n_usec; + onionskins_usec_roundtrip[rpl.handshake_type] += usec_roundtrip; + if (onionskins_n_processed[rpl.handshake_type] >= 500000) { + /* Scale down every 500000 handshakes. On a busy server, that's + * less impressive than it sounds. */ + onionskins_n_processed[rpl.handshake_type] /= 2; + onionskins_usec_internal[rpl.handshake_type] /= 2; + onionskins_usec_roundtrip[rpl.handshake_type] /= 2; + } + } + } /* parse out the circ it was talking about */ - tag_unpack(buf, &conn_id, &circ_id); + tag_unpack(rpl.tag, &chan_id, &circ_id); circ = NULL; - tmp_conn = connection_get_by_global_id(conn_id); - if (tmp_conn && !tmp_conn->marked_for_close && - tmp_conn->type == CONN_TYPE_OR) - p_conn = TO_OR_CONN(tmp_conn); + log_debug(LD_OR, + "Unpacking cpuworker reply, chan_id is " U64_FORMAT + ", circ_id is %u", + U64_PRINTF_ARG(chan_id), (unsigned)circ_id); + p_chan = channel_find_by_global_id(chan_id); - if (p_conn) - circ = circuit_get_by_circid_orconn(circ_id, p_conn); + if (p_chan) + circ = circuit_get_by_circid_channel(circ_id, p_chan); - if (success == 0) { + if (rpl.success == 0) { log_debug(LD_OR, "decoding onionskin failed. " "(Old key or bad software.) Closing."); @@ -180,8 +367,10 @@ connection_cpu_process_inbuf(connection_t *conn) goto done_processing; } tor_assert(! CIRCUIT_IS_ORIGIN(circ)); - if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN, - buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) { + if (onionskin_answer(TO_OR_CIRCUIT(circ), + &rpl.created_cell, + (const char*)rpl.keys, + rpl.rend_auth_material) < 0) { log_warn(LD_OR,"onionskin_answer failed. Closing."); circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); goto done_processing; @@ -208,32 +397,21 @@ connection_cpu_process_inbuf(connection_t *conn) * Read and writes from fdarray[1]. Reads requests, writes answers. * * Request format: - * Task type [1 byte, always CPUWORKER_TASK_ONION] - * Opaque tag TAG_LEN - * Onionskin challenge ONIONSKIN_CHALLENGE_LEN + * cpuworker_request_t. * Response format: - * Success/failure [1 byte, boolean.] - * Opaque tag TAG_LEN - * Onionskin challenge ONIONSKIN_REPLY_LEN - * Negotiated keys KEY_LEN*2+DIGEST_LEN*2 - * - * (Note: this _should_ be by addr/port, since we're concerned with specific - * connections, not with routers (where we'd use identity).) + * cpuworker_reply_t */ static void cpuworker_main(void *data) { - char question[ONIONSKIN_CHALLENGE_LEN]; - uint8_t question_type; + /* For talking to the parent thread/process */ tor_socket_t *fdarray = data; tor_socket_t fd; /* variables for onion processing */ - char keys[CPATH_KEY_MATERIAL_LEN]; - char reply_to_proxy[ONIONSKIN_REPLY_LEN]; - char buf[LEN_ONION_RESPONSE]; - char tag[TAG_LEN]; - crypto_pk_t *onion_key = NULL, *last_onion_key = NULL; + server_onion_keys_t onion_keys; + cpuworker_request_t req; + cpuworker_reply_t rpl; fd = fdarray[1]; /* this side is ours */ #ifndef TOR_IS_MULTITHREADED @@ -244,68 +422,85 @@ cpuworker_main(void *data) #endif tor_free(data); - dup_onion_keys(&onion_key, &last_onion_key); + setup_server_onion_keys(&onion_keys); for (;;) { - ssize_t r; - - if ((r = recv(fd, (void *)&question_type, 1, 0)) != 1) { -// log_fn(LOG_ERR,"read type failed. Exiting."); - if (r == 0) { - log_info(LD_OR, - "CPU worker exiting because Tor process closed connection " - "(either rotated keys or died)."); - } else { - log_info(LD_OR, - "CPU worker exiting because of error on connection to Tor " - "process."); - log_info(LD_OR,"(Error on %d was %s)", - fd, tor_socket_strerror(tor_socket_errno(fd))); - } - goto end; - } - tor_assert(question_type == CPUWORKER_TASK_ONION); - - if (read_all(fd, tag, TAG_LEN, 1) != TAG_LEN) { - log_err(LD_BUG,"read tag failed. Exiting."); + if (read_all(fd, (void *)&req, sizeof(req), 1) != sizeof(req)) { + log_info(LD_OR, "read request failed. Exiting."); goto end; } - - if (read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) != - ONIONSKIN_CHALLENGE_LEN) { - log_err(LD_BUG,"read question failed. Exiting."); - goto end; - } - - if (question_type == CPUWORKER_TASK_ONION) { - if (onion_skin_server_handshake(question, onion_key, last_onion_key, - reply_to_proxy, keys, CPATH_KEY_MATERIAL_LEN) < 0) { + tor_assert(req.magic == CPUWORKER_REQUEST_MAGIC); + + memset(&rpl, 0, sizeof(rpl)); + + if (req.task == CPUWORKER_TASK_ONION) { + const create_cell_t *cc = &req.create_cell; + created_cell_t *cell_out = &rpl.created_cell; + struct timeval tv_start, tv_end; + int n; + rpl.timed = req.timed; + rpl.started_at = req.started_at; + rpl.handshake_type = cc->handshake_type; + if (req.timed) + tor_gettimeofday(&tv_start); + n = onion_skin_server_handshake(cc->handshake_type, + cc->onionskin, cc->handshake_len, + &onion_keys, + cell_out->reply, + rpl.keys, CPATH_KEY_MATERIAL_LEN, + rpl.rend_auth_material); + if (n < 0) { /* failure */ log_debug(LD_OR,"onion_skin_server_handshake failed."); - *buf = 0; /* indicate failure in first byte */ - memcpy(buf+1,tag,TAG_LEN); - /* send all zeros as answer */ - memset(buf+1+TAG_LEN, 0, LEN_ONION_RESPONSE-(1+TAG_LEN)); + memset(&rpl, 0, sizeof(rpl)); + memcpy(rpl.tag, req.tag, TAG_LEN); + rpl.success = 0; } else { /* success */ log_debug(LD_OR,"onion_skin_server_handshake succeeded."); - buf[0] = 1; /* 1 means success */ - memcpy(buf+1,tag,TAG_LEN); - memcpy(buf+1+TAG_LEN,reply_to_proxy,ONIONSKIN_REPLY_LEN); - memcpy(buf+1+TAG_LEN+ONIONSKIN_REPLY_LEN,keys,CPATH_KEY_MATERIAL_LEN); + memcpy(rpl.tag, req.tag, TAG_LEN); + cell_out->handshake_len = n; + switch (cc->cell_type) { + case CELL_CREATE: + cell_out->cell_type = CELL_CREATED; break; + case CELL_CREATE2: + cell_out->cell_type = CELL_CREATED2; break; + case CELL_CREATE_FAST: + cell_out->cell_type = CELL_CREATED_FAST; break; + default: + tor_assert(0); + goto end; + } + rpl.success = 1; } - if (write_all(fd, buf, LEN_ONION_RESPONSE, 1) != LEN_ONION_RESPONSE) { + rpl.magic = CPUWORKER_REPLY_MAGIC; + if (req.timed) { + struct timeval tv_diff; + int64_t usec; + tor_gettimeofday(&tv_end); + timersub(&tv_end, &tv_start, &tv_diff); + usec = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec; + if (usec < 0 || usec > MAX_BELIEVABLE_ONIONSKIN_DELAY) + rpl.n_usec = MAX_BELIEVABLE_ONIONSKIN_DELAY; + else + rpl.n_usec = (uint32_t) usec; + } + if (write_all(fd, (void*)&rpl, sizeof(rpl), 1) != sizeof(rpl)) { log_err(LD_BUG,"writing response buf failed. Exiting."); goto end; } log_debug(LD_OR,"finished writing response."); + } else if (req.task == CPUWORKER_TASK_SHUTDOWN) { + log_info(LD_OR,"Clean shutdown: exiting"); + goto end; } + memwipe(&req, 0, sizeof(req)); + memwipe(&rpl, 0, sizeof(req)); } end: - if (onion_key) - crypto_pk_free(onion_key); - if (last_onion_key) - crypto_pk_free(last_onion_key); + memwipe(&req, 0, sizeof(req)); + memwipe(&rpl, 0, sizeof(req)); + release_server_onion_keys(&onion_keys); tor_close_socket(fd); crypto_thread_cleanup(); spawn_exit(); @@ -342,13 +537,16 @@ spawn_cpuworker(void) conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX); - set_socket_nonblocking(fd); - /* set up conn so it's got all the data we need to remember */ conn->s = fd; conn->address = tor_strdup("localhost"); tor_addr_make_unspec(&conn->addr); + if (set_socket_nonblocking(fd) == -1) { + connection_free(conn); /* this closes fd */ + return -1; + } + if (connection_add(conn) < 0) { /* no space, forget it */ log_warn(LD_NET,"connection_add for cpuworker failed. Giving up."); connection_free(conn); /* this closes fd */ @@ -368,6 +566,7 @@ static void spawn_enough_cpuworkers(void) { int num_cpuworkers_needed = get_num_cpus(get_options()); + int reseed = 0; if (num_cpuworkers_needed < MIN_CPUWORKERS) num_cpuworkers_needed = MIN_CPUWORKERS; @@ -380,7 +579,11 @@ spawn_enough_cpuworkers(void) return; } num_cpuworkers++; + reseed++; } + + if (reseed) + crypto_seed_weak_rng(&request_sample_rng); } /** Take a pending task from the queue and assign it to 'cpuworker'. */ @@ -388,7 +591,7 @@ static void process_pending_task(connection_t *cpuworker) { or_circuit_t *circ; - char *onionskin = NULL; + create_cell_t *onionskin = NULL; tor_assert(cpuworker); @@ -441,12 +644,13 @@ cull_wedged_cpuworkers(void) */ int assign_onionskin_to_cpuworker(connection_t *cpuworker, - or_circuit_t *circ, char *onionskin) + or_circuit_t *circ, + create_cell_t *onionskin) { - char qbuf[1]; - char tag[TAG_LEN]; + cpuworker_request_t req; time_t now = approx_time(); static time_t last_culled_cpuworkers = 0; + int should_time; /* Checking for wedged cpuworkers requires a linear search over all * connections, so let's do it only once a minute. @@ -475,26 +679,39 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker, tor_assert(cpuworker); - if (!circ->p_conn) { - log_info(LD_OR,"circ->p_conn gone. Failing circ."); + if (!circ->p_chan) { + log_info(LD_OR,"circ->p_chan gone. Failing circ."); tor_free(onionskin); return -1; } - tag_pack(tag, circ->p_conn->_base.global_identifier, + + if (connection_or_digest_is_known_relay(circ->p_chan->identity_digest)) + rep_hist_note_circuit_handshake_completed(onionskin->handshake_type); + + should_time = should_time_request(onionskin->handshake_type); + memset(&req, 0, sizeof(req)); + req.magic = CPUWORKER_REQUEST_MAGIC; + tag_pack(req.tag, circ->p_chan->global_identifier, circ->p_circ_id); + req.timed = should_time; cpuworker->state = CPUWORKER_STATE_BUSY_ONION; /* touch the lastwritten timestamp, since that's how we check to * see how long it's been since we asked the question, and sometimes * we check before the first call to connection_handle_write(). */ - cpuworker->timestamp_lastwritten = time(NULL); + cpuworker->timestamp_lastwritten = now; num_cpuworkers_busy++; - qbuf[0] = CPUWORKER_TASK_ONION; - connection_write_to_buf(qbuf, 1, cpuworker); - connection_write_to_buf(tag, sizeof(tag), cpuworker); - connection_write_to_buf(onionskin, ONIONSKIN_CHALLENGE_LEN, cpuworker); + req.task = CPUWORKER_TASK_ONION; + memcpy(&req.create_cell, onionskin, sizeof(create_cell_t)); + tor_free(onionskin); + + if (should_time) + tor_gettimeofday(&req.started_at); + + connection_write_to_buf((void*)&req, sizeof(req), cpuworker); + memwipe(&req, 0, sizeof(req)); } return 0; } diff --git a/src/or/cpuworker.h b/src/or/cpuworker.h index 91172caa56..317cef43ba 100644 --- a/src/or/cpuworker.h +++ b/src/or/cpuworker.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,17 +9,23 @@ * \brief Header file for cpuworker.c. **/ -#ifndef _TOR_CPUWORKER_H -#define _TOR_CPUWORKER_H +#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); +struct create_cell_t; int assign_onionskin_to_cpuworker(connection_t *cpuworker, or_circuit_t *circ, - char *onionskin); + struct create_cell_t *onionskin); + +uint64_t estimated_usec_for_onionskins(uint32_t n_requests, + uint16_t onionskin_type); +void cpuworker_log_onionskin_overhead(int severity, int onionskin_type, + const char *onionskin_type_name); #endif diff --git a/src/or/directory.c b/src/or/directory.c index f235bf3b41..3752367c44 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "or.h" @@ -13,6 +13,7 @@ #include "directory.h" #include "dirserv.h" #include "dirvote.h" +#include "entrynodes.h" #include "geoip.h" #include "main.h" #include "microdesc.h" @@ -25,6 +26,7 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "routerset.h" #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) #ifndef OPENBSD @@ -58,7 +60,6 @@ static void directory_send_command(dir_connection_t *conn, int purpose, int direct, const char *resource, const char *payload, size_t payload_len, - int supports_conditional_consensus, time_t if_modified_since); static int directory_handle_command(dir_connection_t *conn); static int body_is_plausible(const char *body, size_t body_len, int purpose); @@ -89,12 +90,10 @@ static void directory_initiate_command_rend(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, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -227,16 +226,9 @@ router_supports_extrainfo(const char *identity_digest, int is_authority) if (node && node->ri) { if (node->ri->caches_extra_info) return 1; - if (is_authority && node->ri->platform && - tor_version_as_new_as(node->ri->platform, - "Tor 0.2.0.0-alpha-dev (r10070)")) - return 1; } if (is_authority) { - const routerstatus_t *rs = - router_get_consensus_status_by_id(identity_digest); - if (rs && rs->version_supports_extrainfo_upload) - return 1; + return 1; } return 0; } @@ -252,10 +244,10 @@ router_supports_extrainfo(const char *identity_digest, int is_authority) int directories_have_accepted_server_descriptor(void) { - smartlist_t *servers = router_get_trusted_dir_servers(); + const smartlist_t *servers = router_get_trusted_dir_servers(); const or_options_t *options = get_options(); - SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, { - if ((d->type & options->_PublishServerDescriptor) && + SMARTLIST_FOREACH(servers, dir_server_t *, d, { + if ((d->type & options->PublishServerDescriptor_) && d->has_accepted_serverdesc) { return 1; } @@ -288,7 +280,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, { const or_options_t *options = get_options(); int post_via_tor; - smartlist_t *dirservers = router_get_trusted_dir_servers(); + const smartlist_t *dirservers = router_get_trusted_dir_servers(); int found = 0; const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE || dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES); @@ -296,7 +288,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, /* This tries dirservers which we believe to be down, but ultimately, that's * harmless, and we may as well err on the side of getting things uploaded. */ - SMARTLIST_FOREACH_BEGIN(dirservers, trusted_dir_server_t *, ds) { + SMARTLIST_FOREACH_BEGIN(dirservers, dir_server_t *, ds) { routerstatus_t *rs = &(ds->fake_status); size_t upload_len = payload_len; tor_addr_t ds_addr; @@ -342,6 +334,60 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, } } +/** Return true iff, according to the values in <b>options</b>, we should be + * using directory guards for direct downloads of directory information. */ +static int +should_use_directory_guards(const or_options_t *options) +{ + /* Public (non-bridge) servers never use directory guards. */ + if (public_server_mode(options)) + return 0; + /* If guards are disabled, or directory guards are disabled, we can't + * use directory guards. + */ + if (!options->UseEntryGuards || !options->UseEntryGuardsAsDirGuards) + return 0; + /* If we're configured to fetch directory info aggressively or of a + * nonstandard type, don't use directory guards. */ + if (options->DownloadExtraInfo || options->FetchDirInfoEarly || + options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors || + options->FetchV2Networkstatus) + return 0; + if (! options->PreferTunneledDirConns) + return 0; + return 1; +} + +/** Pick an unconsetrained directory server from among our guards, the latest + * networkstatus, or the fallback dirservers, for use in downloading + * information of type <b>type</b>, and return its routerstatus. */ +static const routerstatus_t * +directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags, + uint8_t dir_purpose) +{ + const routerstatus_t *rs = NULL; + const or_options_t *options = get_options(); + + if (options->UseBridges) + log_warn(LD_BUG, "Called when we have UseBridges set."); + + if (should_use_directory_guards(options)) { + const node_t *node = choose_random_dirguard(type); + if (node) + rs = node->rs; + } else { + /* anybody with a non-zero dirport will do */ + rs = router_pick_directory_server(type, pds_flags); + } + if (!rs) { + log_info(LD_DIR, "No router found for %s; falling back to " + "dirserver list.", dir_conn_purpose_to_string(dir_purpose)); + rs = router_pick_fallback_dirserver(type, pds_flags); + } + + return rs; +} + /** Start a connection to a random running directory server, using * connection purpose <b>dir_purpose</b>, intending to fetch descriptors * of purpose <b>router_purpose</b>, and requesting <b>resource</b>. @@ -426,26 +472,25 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, if (options->UseBridges && type != BRIDGE_DIRINFO) { /* We want to ask a running bridge for which we have a descriptor. * - * Be careful here: we should only ask questions that we know our - * bridges can answer. So far we're solving that by backing off to - * the behavior supported by our oldest bridge; see for example - * any_bridges_dont_support_microdescriptors(). + * When we ask choose_random_entry() for a bridge, we specify what + * sort of dir fetch we'll be doing, so it won't return a bridge + * that can't answer our question. */ /* XXX024 Not all bridges handle conditional consensus downloading, * so, for now, never assume the server supports that. -PP */ - const node_t *node = choose_random_entry(NULL); + const node_t *node = choose_random_dirguard(type); if (node && node->ri) { /* every bridge has a routerinfo. */ tor_addr_t addr; routerinfo_t *ri = node->ri; node_get_addr(node, &addr); directory_initiate_command(ri->address, &addr, - ri->or_port, 0, - 0, /* don't use conditional consensus url */ - 1, ri->cache_info.identity_digest, + ri->or_port, 0/*no dirport*/, + ri->cache_info.identity_digest, dir_purpose, router_purpose, - 0, resource, NULL, 0, if_modified_since); + DIRIND_ONEHOP, + resource, NULL, 0, if_modified_since); } else log_notice(LD_DIR, "Ignoring directory request, since no bridge " "nodes are available yet."); @@ -479,14 +524,13 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, } } if (!rs && type != BRIDGE_DIRINFO) { - /* anybody with a non-zero dirport will do */ - rs = router_pick_directory_server(type, pds_flags); + /* */ + rs = directory_pick_generic_dirserver(type, pds_flags, + dir_purpose); if (!rs) { - log_info(LD_DIR, "No router found for %s; falling back to " - "dirserver list.", dir_conn_purpose_to_string(dir_purpose)); - rs = router_pick_trusteddirserver(type, pds_flags); - if (!rs) - get_via_tor = 1; /* last resort: try routing it via Tor */ + /*XXXX024 I'm pretty sure this can never do any good, since + * rs isn't set. */ + get_via_tor = 1; /* last resort: try routing it via Tor */ } } } @@ -506,13 +550,15 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, } } - if (rs) + if (rs) { + const dir_indirection_t indirection = + get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP; directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, - get_via_tor, + indirection, resource, NULL, 0, if_modified_since); - else { + } else { log_notice(LD_DIR, "While fetching directory info, " "no running dirservers known. Will try again later. " @@ -536,7 +582,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose, dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES); SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(), - trusted_dir_server_t *, ds) { + dir_server_t *, ds) { routerstatus_t *rs; if (router_digest_is_me(ds->digest)) continue; @@ -544,17 +590,25 @@ directory_get_from_all_authorities(uint8_t dir_purpose, continue; rs = &ds->fake_status; directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, - 0, resource, NULL, 0, 0); + DIRIND_ONEHOP, resource, NULL, + 0, 0); } SMARTLIST_FOREACH_END(ds); } +/** Return true iff <b>ind</b> requires a multihop circuit. */ +static int +dirind_is_anon(dir_indirection_t ind) +{ + return ind == DIRIND_ANON_DIRPORT || ind == DIRIND_ANONYMOUS; +} + /** Same as directory_initiate_command_routerstatus(), but accepts * rendezvous data to fetch a hidden service descriptor. */ void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -567,6 +621,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, struct in_addr in; const char *address; tor_addr_t addr; + const int anonymized_connection = dirind_is_anon(indirection); node = node_get_by_id(status->identity_digest); if (!node && anonymized_connection) { @@ -596,11 +651,9 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, directory_initiate_command_rend(address, &addr, status->or_port, status->dir_port, - status->version_supports_conditional_consensus, - status->version_supports_begindir, status->identity_digest, dir_purpose, router_purpose, - anonymized_connection, resource, + indirection, resource, payload, payload_len, if_modified_since, rend_query); } @@ -623,7 +676,7 @@ void directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -631,7 +684,7 @@ directory_initiate_command_routerstatus(const routerstatus_t *status, { directory_initiate_command_routerstatus_rend(status, dir_purpose, router_purpose, - anonymized_connection, resource, + indirection, resource, payload, payload_len, if_modified_since, NULL); } @@ -647,8 +700,8 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn) const routerinfo_t *me = router_get_my_routerinfo(); if (me && router_digest_is_me(conn->identity_digest) && - tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/ - me->dir_port == conn->_base.port) + tor_addr_eq_ipv4h(&conn->base_.addr, me->addr) && /*XXXX prop 118*/ + me->dir_port == conn->base_.port) return 1; } return 0; @@ -666,35 +719,35 @@ connection_dir_request_failed(dir_connection_t *conn) } 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) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) { log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", - conn->_base.address); + conn->base_.address); connection_dir_download_v2_networkstatus_failed(conn, -1); - } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || - conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { + } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || + conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from " "directory server at '%s'; retrying", - conn->_base.address); + 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) { + } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) { if (conn->requested_resource) networkstatus_consensus_download_failed(0, conn->requested_resource); - } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) { + } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) { log_info(LD_DIR, "Giving up on certificate fetch from directory server " "at '%s'; retrying", - conn->_base.address); + conn->base_.address); connection_dir_download_cert_failed(conn, 0); - } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) { + } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) { log_info(LD_DIR, "Giving up downloading detached signatures from '%s'", - conn->_base.address); - } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { + conn->base_.address); + } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { log_info(LD_DIR, "Giving up downloading votes from '%s'", - conn->_base.address); - } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) { + conn->base_.address); + } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) { log_info(LD_DIR, "Giving up on downloading microdescriptors from " - " directory server at '%s'; will retry", conn->_base.address); + " directory server at '%s'; will retry", conn->base_.address); connection_dir_download_routerdesc_failed(conn); } } @@ -717,10 +770,10 @@ connection_dir_download_v2_networkstatus_failed(dir_connection_t *conn, /* We're a non-authoritative directory cache; try again. Ignore status * code, since we don't want to keep trying forever in a tight loop * if all the authorities are shutting us out. */ - smartlist_t *trusted_dirs = router_get_trusted_dir_servers(); - SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds, + const smartlist_t *trusted_dirs = router_get_trusted_dir_servers(); + SMARTLIST_FOREACH(trusted_dirs, dir_server_t *, ds, download_status_failed(&ds->v2_ns_dl_status, 0)); - directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose, + directory_get_from_dirserver(conn->base_.purpose, conn->router_purpose, "all.z", 0 /* don't retry_if_no_servers */); } else if (!strcmpstart(conn->requested_resource, "fp/")) { /* We were trying to download by fingerprint; mark them all as having @@ -765,9 +818,9 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn) /* No need to relaunch descriptor downloads here: we already do it * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */ - tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || - conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || - conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC); + tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || + conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || + conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC); (void) conn; } @@ -791,7 +844,7 @@ connection_dir_bridge_routerdesc_failed(dir_connection_t *conn) + strlen("fp/"), which, NULL, 0); - tor_assert(conn->_base.purpose != DIR_PURPOSE_FETCH_EXTRAINFO); + 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)); @@ -803,19 +856,43 @@ connection_dir_bridge_routerdesc_failed(dir_connection_t *conn) static void connection_dir_download_cert_failed(dir_connection_t *conn, int status) { + const char *fp_pfx = "fp/"; + const char *fpsk_pfx = "fp-sk/"; smartlist_t *failed; - tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE); + tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE); if (!conn->requested_resource) return; failed = smartlist_new(); - dir_split_resource_into_fingerprints(conn->requested_resource+3, - failed, NULL, DSR_HEX); - SMARTLIST_FOREACH(failed, char *, cp, - { - authority_cert_dl_failed(cp, status); - tor_free(cp); - }); + /* + * We have two cases download by fingerprint (resource starts + * with "fp/") or download by fingerprint/signing key pair + * (resource starts with "fp-sk/"). + */ + if (!strcmpstart(conn->requested_resource, fp_pfx)) { + /* Download by fingerprint case */ + dir_split_resource_into_fingerprints(conn->requested_resource + + strlen(fp_pfx), + failed, NULL, DSR_HEX); + SMARTLIST_FOREACH_BEGIN(failed, char *, cp) { + /* Null signing key digest indicates download by fp only */ + authority_cert_dl_failed(cp, NULL, status); + tor_free(cp); + } SMARTLIST_FOREACH_END(cp); + } else if (!strcmpstart(conn->requested_resource, fpsk_pfx)) { + /* Download by (fp,sk) pairs */ + dir_split_resource_into_fingerprint_pairs(conn->requested_resource + + strlen(fpsk_pfx), failed); + SMARTLIST_FOREACH_BEGIN(failed, fp_pair_t *, cp) { + authority_cert_dl_failed(cp->first, cp->second, status); + tor_free(cp); + } SMARTLIST_FOREACH_END(cp); + } else { + log_warn(LD_DIR, + "Don't know what to do with failure for cert fetch %s", + conn->requested_resource); + } + smartlist_free(failed); update_certificate_downloads(time(NULL)); @@ -833,11 +910,13 @@ static int directory_command_should_use_begindir(const or_options_t *options, const tor_addr_t *addr, int or_port, uint8_t router_purpose, - int anonymized_connection) + dir_indirection_t indirection) { if (!or_port) return 0; /* We don't know an ORPort -- no chance. */ - if (!anonymized_connection) + if (indirection == DIRIND_DIRECT_CONN || indirection == DIRIND_ANON_DIRPORT) + return 0; + if (indirection == DIRIND_ONEHOP) if (!fascist_firewall_allows_address_or(addr, or_port) || directory_fetches_from_authorities(options)) return 0; /* We're firewalled or are acting like a relay -- also no. */ @@ -855,17 +934,15 @@ directory_command_should_use_begindir(const or_options_t *options, 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, + const char *digest, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, const char *resource, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since) { directory_initiate_command_rend(address, _addr, or_port, dir_port, - supports_conditional_consensus, - supports_begindir, digest, dir_purpose, - router_purpose, anonymized_connection, + digest, dir_purpose, + router_purpose, indirection, resource, payload, payload_len, if_modified_since, NULL); } @@ -889,10 +966,9 @@ is_sensitive_dir_purpose(uint8_t dir_purpose) static void directory_initiate_command_rend(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, + const char *digest, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since, @@ -901,9 +977,9 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, dir_connection_t *conn; const or_options_t *options = get_options(); int socket_error = 0; - int use_begindir = supports_begindir && - directory_command_should_use_begindir(options, _addr, - or_port, router_purpose, anonymized_connection); + int use_begindir = directory_command_should_use_begindir(options, _addr, + or_port, router_purpose, indirection); + const int anonymized_connection = dirind_is_anon(indirection); tor_addr_t addr; tor_assert(address); @@ -937,18 +1013,19 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, conn = dir_connection_new(tor_addr_family(&addr)); /* set up conn so it's got all the data we need to remember */ - tor_addr_copy(&conn->_base.addr, &addr); - conn->_base.port = use_begindir ? or_port : dir_port; - conn->_base.address = tor_strdup(address); + tor_addr_copy(&conn->base_.addr, &addr); + conn->base_.port = use_begindir ? or_port : dir_port; + conn->base_.address = tor_strdup(address); memcpy(conn->identity_digest, digest, DIGEST_LEN); - conn->_base.purpose = dir_purpose; + conn->base_.purpose = dir_purpose; conn->router_purpose = router_purpose; /* give it an initial state */ - conn->_base.state = DIR_CONN_STATE_CONNECTING; + conn->base_.state = DIR_CONN_STATE_CONNECTING; /* decide whether we can learn our IP address from this conn */ + /* XXXX This is a bad name for this field now. */ conn->dirconn_direct = !anonymized_connection; /* copy rendezvous data, if any */ @@ -963,7 +1040,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, dir_port = options->HTTPProxyPort; } - switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr, + switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr, dir_port, &socket_error)) { case -1: connection_dir_request_failed(conn); /* retry if we want */ @@ -973,13 +1050,12 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, return; case 1: /* start flushing conn */ - conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; + conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING; /* fall through */ case 0: /* queue the command on the outbuf */ directory_send_command(conn, dir_purpose, 1, resource, payload, payload_len, - supports_conditional_consensus, if_modified_since); connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT); /* writable indicates finish, readable indicates broken link, @@ -997,7 +1073,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, if (anonymized_connection && use_begindir) rep_hist_note_used_internal(time(NULL), 0, 1); else if (anonymized_connection && !use_begindir) - rep_hist_note_used_port(time(NULL), conn->_base.port); + rep_hist_note_used_port(time(NULL), conn->base_.port); /* make an AP connection * populate it and add it at the right state @@ -1005,7 +1081,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, */ linked_conn = connection_ap_make_link(TO_CONN(conn), - conn->_base.address, conn->_base.port, + conn->base_.address, conn->base_.port, digest, SESSION_GROUP_DIRCONN, iso_flags, use_begindir, conn->dirconn_direct); @@ -1020,11 +1096,10 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, connection_mark_for_close(TO_CONN(conn)); return; } - conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; + conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING; /* queue the command on the outbuf */ directory_send_command(conn, dir_purpose, 0, resource, payload, payload_len, - supports_conditional_consensus, if_modified_since); connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT); @@ -1054,7 +1129,7 @@ connection_dir_is_encrypted(dir_connection_t *conn) * sort strings alphabetically */ static int -_compare_strs(const void **a, const void **b) +compare_strs_(const void **a, const void **b) { const char *s1 = *a, *s2 = *b; return strcmp(s1, s2); @@ -1074,8 +1149,7 @@ _compare_strs(const void **a, const void **b) * If 'resource' is provided, it is the name of a consensus flavor to request. */ static char * -directory_get_consensus_url(int supports_conditional_consensus, - const char *resource) +directory_get_consensus_url(const char *resource) { char *url = NULL; const char *hyphen, *flavor; @@ -1087,12 +1161,12 @@ directory_get_consensus_url(int supports_conditional_consensus, hyphen = "-"; } - if (supports_conditional_consensus) { + { char *authority_id_list; smartlist_t *authority_digests = smartlist_new(); SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(), - trusted_dir_server_t *, ds) { + dir_server_t *, ds) { char *hex; if (!(ds->type & V3_DIRINFO)) continue; @@ -1102,7 +1176,7 @@ directory_get_consensus_url(int supports_conditional_consensus, ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN); smartlist_add(authority_digests, hex); } SMARTLIST_FOREACH_END(ds); - smartlist_sort(authority_digests, _compare_strs); + smartlist_sort(authority_digests, compare_strs_); authority_id_list = smartlist_join_strings(authority_digests, "+", 0, NULL); @@ -1112,9 +1186,6 @@ directory_get_consensus_url(int supports_conditional_consensus, SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp)); smartlist_free(authority_digests); tor_free(authority_id_list); - } else { - tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s.z", - hyphen, flavor); } return url; } @@ -1126,7 +1197,6 @@ static void directory_send_command(dir_connection_t *conn, int purpose, int direct, const char *resource, const char *payload, size_t payload_len, - int supports_conditional_consensus, time_t if_modified_since) { char proxystring[256]; @@ -1137,18 +1207,18 @@ directory_send_command(dir_connection_t *conn, const char *httpcommand = NULL; tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_DIR); + tor_assert(conn->base_.type == CONN_TYPE_DIR); tor_free(conn->requested_resource); if (resource) conn->requested_resource = tor_strdup(resource); /* come up with a string for which Host: we want */ - if (conn->_base.port == 80) { - strlcpy(hoststring, conn->_base.address, sizeof(hoststring)); + if (conn->base_.port == 80) { + strlcpy(hoststring, conn->base_.address, sizeof(hoststring)); } else { tor_snprintf(hoststring, sizeof(hoststring),"%s:%d", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); } /* Format if-modified-since */ @@ -1189,8 +1259,7 @@ directory_send_command(dir_connection_t *conn, /* resource is optional. If present, it's a flavor name */ tor_assert(!payload); httpcommand = "GET"; - url = directory_get_consensus_url(supports_conditional_consensus, - resource); + url = directory_get_consensus_url(resource); log_info(LD_DIR, "Downloading consensus from %s using %s", hoststring, url); break; @@ -1584,11 +1653,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn) compress_method_t compression; int plausible; int skewed=0; - int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || - conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || - conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC); + int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || + conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || + conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC); int was_compressed=0; time_t now = time(NULL); + int src_code; switch (connection_fetch_from_buf_http(TO_CONN(conn), &headers, MAX_HEADERS_SIZE, @@ -1597,7 +1667,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) case -1: /* overflow */ log_warn(LD_PROTOCOL, "'fetch' response too large (server '%s:%d'). Closing.", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); return -1; case 0: log_info(LD_HTTP, @@ -1610,7 +1680,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (parse_http_response(headers, &status_code, &date_header, &compression, &reason) < 0) { log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); tor_free(body); tor_free(headers); return -1; } @@ -1619,9 +1689,9 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_debug(LD_DIR, "Received response from directory server '%s:%d': %d %s " "(purpose: %d)", - conn->_base.address, conn->_base.port, status_code, + conn->base_.address, conn->base_.port, status_code, escaped(reason), - conn->_base.purpose); + conn->base_.purpose); /* now check if it's got any hints for us about our IP address. */ if (conn->dirconn_direct) { @@ -1638,7 +1708,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) * and the date header. (We used to check now-date_header, but that's * inaccurate if we spend a lot of time downloading.) */ - delta = conn->_base.timestamp_lastwritten - date_header; + delta = conn->base_.timestamp_lastwritten - date_header; if (labs(delta)>ALLOW_DIRECTORY_TIME_SKEW) { char dbuf[64]; int trusted = router_digest_is_trusted_dir(conn->identity_digest); @@ -1649,14 +1719,14 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "It seems that our clock is %s by %s, or that theirs is %s. " "Tor requires an accurate clock to work: please check your time, " "timezone, and date settings.", - conn->_base.address, conn->_base.port, + conn->base_.address, conn->base_.port, delta>0 ? "ahead" : "behind", dbuf, delta>0 ? "behind" : "ahead"); skewed = 1; /* don't check the recommended-versions line */ if (trusted) control_event_general_status(LOG_WARN, "CLOCK_SKEW SKEW=%ld SOURCE=DIRSERV:%s:%d", - delta, conn->_base.address, conn->_base.port); + delta, conn->base_.address, conn->base_.port); } else { log_debug(LD_HTTP, "Time on received directory is within tolerance; " "we are %ld seconds skewed. (That's okay.)", delta); @@ -1666,22 +1736,22 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (status_code == 503) { routerstatus_t *rs; - trusted_dir_server_t *ds; + dir_server_t *ds; const char *id_digest = conn->identity_digest; log_info(LD_DIR,"Received http status code %d (%s) from server " "'%s:%d'. I'll try again soon.", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); if ((rs = router_get_mutable_consensus_status_by_id(id_digest))) rs->last_dir_503_at = now; - if ((ds = router_get_trusteddirserver_by_digest(id_digest))) + if ((ds = router_get_fallback_dirserver_by_digest(id_digest))) ds->fake_status.last_dir_503_at = now; tor_free(body); tor_free(headers); tor_free(reason); return -1; } - plausible = body_is_plausible(body, body_len, conn->_base.purpose); + plausible = body_is_plausible(body, body_len, conn->base_.purpose); if (compression != NO_METHOD || !plausible) { char *new_body = NULL; size_t new_len = 0; @@ -1708,7 +1778,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, " "but it seems to be %s.%s", - conn->_base.address, conn->_base.port, description1, + conn->base_.address, conn->base_.port, description1, description2, (compression>0 && guessed>0)?" Trying both.":""); } @@ -1728,7 +1798,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (!plausible && !new_body) { log_fn(LOG_PROTOCOL_WARN, LD_HTTP, "Unable to decompress HTTP body (server '%s:%d').", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); tor_free(body); tor_free(headers); tor_free(reason); return -1; } @@ -1740,12 +1810,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn) } } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) { smartlist_t *which = NULL; 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) { static ratelim_t warning_limit = RATELIM_INIT(3600); char *m; @@ -1754,8 +1824,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "Received http status code %d (%s) from server " "'%s:%d' while fetching \"/tor/status/%s\". " "I'll try again soon.%s", - status_code, escaped(reason), conn->_base.address, - conn->_base.port, conn->requested_resource, m); + status_code, escaped(reason), conn->base_.address, + conn->base_.port, conn->requested_resource, m); tor_free(m); } tor_free(body); tor_free(headers); tor_free(reason); @@ -1773,7 +1843,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) source = NS_FROM_DIR_ALL; which = smartlist_new(); SMARTLIST_FOREACH(router_get_trusted_dir_servers(), - trusted_dir_server_t *, ds, + dir_server_t *, ds, { char *hex = tor_malloc(HEX_DIGEST_LEN+1); base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN); @@ -1811,27 +1881,27 @@ connection_dir_client_reached_eof(dir_connection_t *conn) } } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) { int r; const char *flavname = conn->requested_resource; if (status_code != 200) { int severity = (status_code == 304) ? LOG_INFO : LOG_WARN; - log(severity, LD_DIR, + tor_log(severity, LD_DIR, "Received http status code %d (%s) from server " "'%s:%d' while fetching consensus directory.", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); tor_free(body); tor_free(headers); tor_free(reason); networkstatus_consensus_download_failed(status_code, flavname); return -1; } log_info(LD_DIR,"Received consensus directory (size %d) from server " - "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port); + "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port); if ((r=networkstatus_set_current_consensus(body, flavname, 0))<0) { log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR, "Unable to load %s consensus directory downloaded from " "server '%s:%d'. I'll try again soon.", - flavname, conn->_base.address, conn->_base.port); + flavname, conn->base_.address, conn->base_.port); tor_free(body); tor_free(headers); tor_free(reason); networkstatus_consensus_download_failed(0, flavname); return -1; @@ -1844,40 +1914,60 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_DIR, "Successfully loaded consensus."); } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) { if (status_code != 200) { log_warn(LD_DIR, "Received http status code %d (%s) from server " "'%s:%d' while fetching \"/tor/keys/%s\".", - status_code, escaped(reason), conn->_base.address, - conn->_base.port, conn->requested_resource); + status_code, escaped(reason), conn->base_.address, + conn->base_.port, conn->requested_resource); connection_dir_download_cert_failed(conn, status_code); tor_free(body); tor_free(headers); tor_free(reason); return -1; } log_info(LD_DIR,"Received authority certificates (size %d) from server " - "'%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); + "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port); + + /* + * Tell trusted_dirs_load_certs_from_string() whether it was by fp + * or fp-sk pair. + */ + src_code = -1; + if (!strcmpstart(conn->requested_resource, "fp/")) { + src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST; + } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) { + src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST; + } + + if (src_code != -1) { + if (trusted_dirs_load_certs_from_string(body, src_code, 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); + log_info(LD_DIR, "Successfully loaded certificates from fetch."); + } } else { - directory_info_has_arrived(now, 0); - log_info(LD_DIR, "Successfully loaded certificates from fetch."); + log_warn(LD_DIR, + "Couldn't figure out what to do with fetched certificates for " + "unknown resource %s", + conn->requested_resource); + connection_dir_download_cert_failed(conn, status_code); } } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { 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 " "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".", - status_code, escaped(reason), conn->_base.address, - conn->_base.port, conn->requested_resource); + status_code, escaped(reason), conn->base_.address, + conn->base_.port, conn->requested_resource); tor_free(body); tor_free(headers); tor_free(reason); return -1; } @@ -1888,35 +1978,35 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg); } } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) { + 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/next/consensus-signatures.z\".", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); tor_free(body); tor_free(headers); tor_free(reason); return -1; } - if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) { + if (dirvote_add_signatures(body, conn->base_.address, &msg)<0) { log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s", - conn->_base.address, conn->_base.port, msg?msg:"???"); + conn->base_.address, conn->base_.port, msg?msg:"???"); } } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || - conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { - int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO; + if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || + conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { + int was_ei = conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO; smartlist_t *which = NULL; int n_asked_for = 0; int descriptor_digests = conn->requested_resource && !strcmpstart(conn->requested_resource,"d/"); log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'", was_ei ? "extra server info" : "server info", - (int)body_len, conn->_base.address, conn->_base.port); + (int)body_len, conn->base_.address, conn->base_.port); if (conn->requested_resource && (!strcmpstart(conn->requested_resource,"d/") || !strcmpstart(conn->requested_resource,"fp/"))) { @@ -1934,8 +2024,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR, "Received http status code %d (%s) from server '%s:%d' " "while fetching \"/tor/server/%s\". I'll try again soon.", - status_code, escaped(reason), conn->_base.address, - conn->_base.port, conn->requested_resource); + status_code, escaped(reason), conn->base_.address, + conn->base_.port, conn->requested_resource); if (!which) { connection_dir_download_routerdesc_failed(conn); } else { @@ -1969,7 +2059,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) // descriptor_digests, conn->router_purpose); if (load_downloaded_routers(body, which, descriptor_digests, conn->router_purpose, - conn->_base.address)) + conn->base_.address)) directory_info_has_arrived(now, 0); } } @@ -1977,7 +2067,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_DIR, "Received %d/%d %s requested from %s:%d", n_asked_for-smartlist_len(which), n_asked_for, was_ei ? "extra-info documents" : "router descriptors", - conn->_base.address, (int)conn->_base.port); + conn->base_.address, (int)conn->base_.port); if (smartlist_len(which)) { dir_routerdesc_download_failed(which, status_code, conn->router_purpose, @@ -1989,12 +2079,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (directory_conn_is_self_reachability_test(conn)) router_dirport_found_reachable(); } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) { smartlist_t *which = NULL; log_info(LD_DIR,"Received answer to microdescriptor request (status %d, " "size %d) from server '%s:%d'", - status_code, (int)body_len, conn->_base.address, - conn->_base.port); + status_code, (int)body_len, conn->base_.address, + conn->base_.port); tor_assert(conn->requested_resource && !strcmpstart(conn->requested_resource, "d/")); which = smartlist_new(); @@ -2005,8 +2095,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_DIR, "Received status code %d (%s) from server " "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again " "soon.", - status_code, escaped(reason), conn->_base.address, - (int)conn->_base.port, conn->requested_resource); + status_code, escaped(reason), conn->base_.address, + (int)conn->base_.port, conn->requested_resource); dir_microdesc_download_failed(which, status_code); SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); smartlist_free(which); @@ -2021,16 +2111,18 @@ connection_dir_client_reached_eof(dir_connection_t *conn) /* Mark remaining ones as failed. */ dir_microdesc_download_failed(which, status_code); } + control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS, + count_loading_descriptors_progress()); SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); smartlist_free(which); smartlist_free(mds); } } - if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) { + if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_DIR) { switch (status_code) { case 200: { - trusted_dir_server_t *ds = + dir_server_t *ds = router_get_trusteddirserver_by_digest(conn->identity_digest); char *rejected_hdr = http_get_header(headers, "X-Descriptor-Not-New: "); @@ -2053,7 +2145,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "descriptor: finished."); control_event_server_status( LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); ds->has_accepted_serverdesc = 1; if (directories_have_accepted_server_descriptor()) @@ -2063,72 +2155,72 @@ connection_dir_client_reached_eof(dir_connection_t *conn) case 400: log_warn(LD_GENERAL,"http status 400 (%s) response from " "dirserver '%s:%d'. Please correct.", - escaped(reason), conn->_base.address, conn->_base.port); + escaped(reason), conn->base_.address, conn->base_.port); control_event_server_status(LOG_WARN, "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"", - conn->_base.address, conn->_base.port, escaped(reason)); + conn->base_.address, conn->base_.port, escaped(reason)); break; default: log_warn(LD_GENERAL, "http status %d (%s) reason unexpected while uploading " "descriptor to server '%s:%d').", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); break; } /* return 0 in all cases, since we don't want to mark any * dirservers down just because they don't like us. */ } - if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) { + if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_VOTE) { switch (status_code) { case 200: { log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); } break; case 400: log_warn(LD_DIR,"http status 400 (%s) response after uploading " "vote to dirserver '%s:%d'. Please correct.", - escaped(reason), conn->_base.address, conn->_base.port); + escaped(reason), conn->base_.address, conn->base_.port); break; default: log_warn(LD_GENERAL, "http status %d (%s) reason unexpected while uploading " "vote to server '%s:%d').", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); break; } /* return 0 in all cases, since we don't want to mark any * dirservers down just because they don't like us. */ } - if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) { + if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) { switch (status_code) { case 200: { log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d", - conn->_base.address, conn->_base.port); + conn->base_.address, conn->base_.port); } break; case 400: log_warn(LD_DIR,"http status 400 (%s) response after uploading " "signatures to dirserver '%s:%d'. Please correct.", - escaped(reason), conn->_base.address, conn->_base.port); + escaped(reason), conn->base_.address, conn->base_.port); break; default: log_warn(LD_GENERAL, "http status %d (%s) reason unexpected while uploading " "signatures to server '%s:%d').", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); break; } /* return 0 in all cases, since we don't want to mark any * dirservers down just because they don't like us. */ } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC) { tor_assert(conn->rend_data); log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d " "(%s))", @@ -2146,7 +2238,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) } else { /* Success, or at least there's a v2 descriptor already * present. Notify pending connections about this. */ - conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; + conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; rend_client_desc_trynow(conn->rend_data->onion_address); } break; @@ -2162,13 +2254,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn) default: log_warn(LD_REND,"http status %d (%s) response unexpected while " "fetching hidden service descriptor (server '%s:%d').", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); break; } } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { tor_assert(conn->rend_data); log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d " "(%s))", @@ -2187,13 +2279,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn) * and _not_ performing another request. */ log_info(LD_REND, "Successfully fetched v2 rendezvous " "descriptor, but we already have a v0 descriptor."); - conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; + conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; break; default: /* success. notify pending connections about this. */ log_info(LD_REND, "Successfully fetched v2 rendezvous " "descriptor."); - conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; + conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; rend_client_desc_trynow(conn->rend_data->onion_address); break; } @@ -2215,14 +2307,14 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "http status %d (%s) response unexpected while " "fetching v2 hidden service descriptor (server '%s:%d'). " "Retrying at another directory.", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); break; } } - if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC || - conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) { + if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC || + conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) { log_info(LD_REND,"Uploaded rendezvous descriptor (status %d " "(%s))", status_code, escaped(reason)); @@ -2235,17 +2327,17 @@ connection_dir_client_reached_eof(dir_connection_t *conn) case 400: log_warn(LD_REND,"http status 400 (%s) response from dirserver " "'%s:%d'. Malformed rendezvous descriptor?", - escaped(reason), conn->_base.address, conn->_base.port); + escaped(reason), conn->base_.address, conn->base_.port); break; default: log_warn(LD_REND,"http status %d (%s) response unexpected (server " "'%s:%d').", - status_code, escaped(reason), conn->_base.address, - conn->_base.port); + status_code, escaped(reason), conn->base_.address, + conn->base_.port); break; } } - note_client_request(conn->_base.purpose, was_compressed, orig_len); + note_client_request(conn->base_.purpose, was_compressed, orig_len); tor_free(body); tor_free(headers); tor_free(reason); return 0; } @@ -2255,9 +2347,9 @@ int connection_dir_reached_eof(dir_connection_t *conn) { int retval; - if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) { + if (conn->base_.state != DIR_CONN_STATE_CLIENT_READING) { log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.", - conn->_base.state); + conn->base_.state); connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */ connection_mark_for_close(TO_CONN(conn)); return -1; @@ -2265,7 +2357,7 @@ connection_dir_reached_eof(dir_connection_t *conn) retval = connection_dir_client_reached_eof(conn); if (retval == 0) /* success */ - conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED; + conn->base_.state = DIR_CONN_STATE_CLIENT_FINISHED; connection_mark_for_close(TO_CONN(conn)); return retval; } @@ -2283,7 +2375,7 @@ int connection_dir_process_inbuf(dir_connection_t *conn) { tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_DIR); + tor_assert(conn->base_.type == CONN_TYPE_DIR); /* Directory clients write, then read data until they receive EOF; * directory servers read data until they get an HTTP command, then @@ -2292,7 +2384,7 @@ connection_dir_process_inbuf(dir_connection_t *conn) */ /* If we're on the dirserver side, look for a command. */ - if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) { + if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) { if (directory_handle_command(conn) < 0) { connection_mark_for_close(TO_CONN(conn)); return -1; @@ -2307,7 +2399,7 @@ connection_dir_process_inbuf(dir_connection_t *conn) return -1; } - if (!conn->_base.inbuf_reached_eof) + if (!conn->base_.inbuf_reached_eof) log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf."); return 0; } @@ -2380,12 +2472,12 @@ write_http_response_header_impl(dir_connection_t *conn, ssize_t length, tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type); cp += strlen(cp); } - if (!is_local_addr(&conn->_base.addr)) { + if (!is_local_addr(&conn->base_.addr)) { /* Don't report the source address for a nearby/private connection. * Otherwise we tend to mis-report in cases where incoming ports are * being forwarded to a Tor server running behind the firewall. */ tor_snprintf(cp, sizeof(tmp)-(cp-tmp), - X_ADDRESS_HEADER "%s\r\n", conn->_base.address); + X_ADDRESS_HEADER "%s\r\n", conn->base_.address); cp += strlen(cp); } if (encoding) { @@ -2637,7 +2729,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, log_debug(LD_DIRSERV,"Received GET command."); - conn->_base.state = DIR_CONN_STATE_SERVER_WRITING; + conn->base_.state = DIR_CONN_STATE_SERVER_WRITING; if (parse_http_url(headers, &url) < 0) { write_http_status_line(conn, 400, "Bad request"); @@ -2756,12 +2848,23 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, /* v2 or v3 network status fetch. */ smartlist_t *dir_fps = smartlist_new(); 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 (options->DisableV2DirectoryInfo_ && !is_v3) { + static ratelim_t reject_v2_ratelim = RATELIM_INIT(1800); + char *m; + write_http_status_line(conn, 404, "Not found"); + smartlist_free(dir_fps); + geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND); + if ((m = rate_limit_log(&reject_v2_ratelim, approx_time()))) { + log_notice(LD_DIR, "Rejected a v2 networkstatus request.%s", m); + tor_free(m); + } + goto done; + } + if (!is_v3) { dirserv_get_networkstatus_v2_fingerprints(dir_fps, key); if (!strcmpstart(key, "fp/")) @@ -2807,7 +2910,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, 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); + geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS); tor_free(flavor); goto done; } @@ -2826,7 +2929,8 @@ 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); + if (is_v3) + geoip_note_ns_response(GEOIP_REJECT_UNAVAILABLE); goto done; } @@ -2834,13 +2938,15 @@ 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); + if (is_v3) + geoip_note_ns_response(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); + if (is_v3) + geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED); goto done; } @@ -2852,24 +2958,24 @@ 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); + if (is_v3) + geoip_note_ns_response(GEOIP_REJECT_BUSY); goto done; } - { + if (is_v3) { struct in_addr in; tor_addr_t addr; if (tor_inet_aton((TO_CONN(conn))->address, &in)) { tor_addr_from_ipv4h(&addr, ntohl(in.s_addr)); - geoip_note_client_seen(act, &addr, time(NULL)); - geoip_note_ns_response(act, GEOIP_SUCCESS); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, time(NULL)); + geoip_note_ns_response(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); + if (conn->dirreq_id) + geoip_start_dirreq(conn->dirreq_id, dlen, DIRREQ_TUNNELED); else - geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen, act, + geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen, DIRREQ_DIRECT); } } @@ -3231,7 +3337,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, } if (options->BridgeAuthoritativeDir && - options->_BridgePassword_AuthDigest && + options->BridgePassword_AuthDigest_ && connection_dir_is_encrypted(conn) && !strcmp(url,"/tor/networkstatus-bridges")) { char *status; @@ -3244,7 +3350,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, /* now make sure the password is there and right */ if (!header || tor_memneq(digest, - options->_BridgePassword_AuthDigest, DIGEST256_LEN)) { + options->BridgePassword_AuthDigest_, DIGEST256_LEN)) { write_http_status_line(conn, 404, "Not found"); tor_free(header); goto done; @@ -3300,7 +3406,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, }while(0); if (!strcmp(url,"/tor/mallinfo.txt") && - (tor_addr_eq_ipv4h(&conn->_base.addr, 0x7f000001ul))) { + (tor_addr_eq_ipv4h(&conn->base_.addr, 0x7f000001ul))) { char *result; size_t len; struct mallinfo mi; @@ -3355,7 +3461,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, log_debug(LD_DIRSERV,"Received POST command."); - conn->_base.state = DIR_CONN_STATE_SERVER_WRITING; + conn->base_.state = DIR_CONN_STATE_SERVER_WRITING; if (parse_http_url(headers, &url) < 0) { write_http_status_line(conn, 400, "Bad request"); @@ -3371,13 +3477,13 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, case -2: log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s " "since we're not currently a hidden service directory.", - (int)body_len, conn->_base.address); + (int)body_len, conn->base_.address); write_http_status_line(conn, 503, "Currently not acting as v2 " "hidden service directory"); break; case -1: log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.", - (int)body_len, conn->_base.address); + (int)body_len, conn->base_.address); write_http_status_line(conn, 400, "Invalid v2 service descriptor rejected"); break; @@ -3402,7 +3508,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, uint8_t purpose = authdir_mode_bridge(options) ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL; was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose, - conn->_base.address, &msg); + conn->base_.address, &msg); tor_assert(msg); if (WRA_WAS_ADDED(r)) dirserv_get_directory(); /* rebuild and write to disk */ @@ -3412,7 +3518,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, log_info(LD_DIRSERV, "Problematic router descriptor or extra-info from %s " "(\"%s\").", - conn->_base.address, msg); + conn->base_.address, msg); write_http_status_line(conn, 400, msg); } else if (r == ROUTER_ADDED_SUCCESSFULLY) { write_http_status_line(conn, 200, msg); @@ -3423,7 +3529,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, log_info(LD_DIRSERV, "Rejected router descriptor or extra-info from %s " "(\"%s\").", - conn->_base.address, msg); + conn->base_.address, msg); write_http_status_line(conn, 400, msg); } goto done; @@ -3436,7 +3542,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, if (rend_cache_store(body, body_len, 1, NULL) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV, "Rejected rend descriptor (length %d) from %s.", - (int)body_len, conn->_base.address); + (int)body_len, conn->base_.address); write_http_status_line(conn, 400, "Invalid v0 service descriptor rejected"); } else { @@ -3454,7 +3560,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, } else { tor_assert(msg); log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").", - conn->_base.address, msg); + conn->base_.address, msg); write_http_status_line(conn, status, msg); } goto done; @@ -3463,11 +3569,11 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, if (authdir_mode_v3(options) && !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */ const char *msg = NULL; - if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) { + if (dirvote_add_signatures(body, conn->base_.address, &msg)>=0) { write_http_status_line(conn, 200, msg?msg:"Signatures stored"); } else { log_warn(LD_DIR, "Unable to store signatures posted by %s: %s", - conn->_base.address, msg?msg:"???"); + conn->base_.address, msg?msg:"???"); write_http_status_line(conn, 400, msg?msg:"Unable to store signatures"); } goto done; @@ -3494,7 +3600,7 @@ directory_handle_command(dir_connection_t *conn) int r; tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_DIR); + tor_assert(conn->base_.type == CONN_TYPE_DIR); switch (connection_fetch_from_buf_http(TO_CONN(conn), &headers, MAX_HEADERS_SIZE, @@ -3502,7 +3608,7 @@ directory_handle_command(dir_connection_t *conn) case -1: /* overflow */ log_warn(LD_DIRSERV, "Request too large from address '%s' to DirPort. Closing.", - safe_str(conn->_base.address)); + safe_str(conn->base_.address)); return -1; case 0: log_debug(LD_DIRSERV,"command not all here yet."); @@ -3536,23 +3642,23 @@ int connection_dir_finished_flushing(dir_connection_t *conn) { tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_DIR); + 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, + if (conn->dirreq_id) + geoip_change_dirreq_state(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) { + switch (conn->base_.state) { case DIR_CONN_STATE_CONNECTING: case DIR_CONN_STATE_CLIENT_SENDING: log_debug(LD_DIR,"client finished sending command."); - conn->_base.state = DIR_CONN_STATE_CLIENT_READING; + conn->base_.state = DIR_CONN_STATE_CLIENT_READING; return 0; case DIR_CONN_STATE_SERVER_WRITING: if (conn->dir_spool_src != DIR_SPOOL_NONE) { @@ -3573,7 +3679,7 @@ connection_dir_finished_flushing(dir_connection_t *conn) return 0; default: log_warn(LD_BUG,"called in unexpected state %d.", - conn->_base.state); + conn->base_.state); tor_fragile_assert(); return -1; } @@ -3586,13 +3692,13 @@ int connection_dir_finished_connecting(dir_connection_t *conn) { tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_DIR); - tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING); + tor_assert(conn->base_.type == CONN_TYPE_DIR); + tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING); log_debug(LD_HTTP,"Dir connection to router %s:%u established.", - conn->_base.address,conn->_base.port); + conn->base_.address,conn->base_.port); - conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */ + conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */ return 0; } @@ -3606,13 +3712,13 @@ dir_networkstatus_download_failed(smartlist_t *failed, int status_code) return; SMARTLIST_FOREACH_BEGIN(failed, const char *, fp) { char digest[DIGEST_LEN]; - trusted_dir_server_t *dir; + dir_server_t *dir; if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) { log_warn(LD_BUG, "Called with bad fingerprint in list: %s", escaped(fp)); continue; } - dir = router_get_trusteddirserver_by_digest(digest); + dir = router_get_fallback_dirserver_by_digest(digest); if (dir) download_status_failed(&dir->v2_ns_dl_status, status_code); @@ -3829,7 +3935,7 @@ dir_microdesc_download_failed(smartlist_t *failed, /** Helper. Compare two fp_pair_t objects, and return negative, 0, or * positive as appropriate. */ static int -_compare_pairs(const void **a, const void **b) +compare_pairs_(const void **a, const void **b) { const fp_pair_t *fp1 = *a, *fp2 = *b; int r; @@ -3880,8 +3986,8 @@ dir_split_resource_into_fingerprint_pairs(const char *res, smartlist_free(pairs_tmp); /* Uniq-and-sort */ - smartlist_sort(pairs_result, _compare_pairs); - smartlist_uniq(pairs_result, _compare_pairs, _tor_free); + smartlist_sort(pairs_result, compare_pairs_); + smartlist_uniq(pairs_result, compare_pairs_, tor_free_); smartlist_add_all(pairs_out, pairs_result); smartlist_free(pairs_result); diff --git a/src/or/directory.h b/src/or/directory.h index 1ca1c5a6e0..41f18a1725 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for directory.c. **/ -#ifndef _TOR_DIRECTORY_H -#define _TOR_DIRECTORY_H +#ifndef TOR_DIRECTORY_H +#define TOR_DIRECTORY_H int directories_have_accepted_server_descriptor(void); void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, @@ -22,10 +22,24 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, void directory_get_from_all_authorities(uint8_t dir_purpose, uint8_t router_purpose, const char *resource); + +/** Enumeration of ways to connect to a directory server */ +typedef enum { + /** Default: connect over a one-hop Tor circuit but fall back to direct + * connection */ + DIRIND_ONEHOP=0, + /** Connect over a multi-hop anonymizing Tor circuit */ + DIRIND_ANONYMOUS=1, + /** Conncet to the DirPort directly */ + DIRIND_DIRECT_CONN, + /** Connect over a multi-hop anonymizing Tor circuit to our dirport */ + DIRIND_ANON_DIRPORT, +} dir_indirection_t; + void directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -33,7 +47,7 @@ void directory_initiate_command_routerstatus(const routerstatus_t *status, void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -51,10 +65,9 @@ int connection_dir_finished_connecting(dir_connection_t *conn); void connection_dir_about_to_close(dir_connection_t *dir_conn); void directory_initiate_command(const char *address, const tor_addr_t *addr, uint16_t or_port, uint16_t dir_port, - int supports_conditional_consensus, - int supports_begindir, const char *digest, + const char *digest, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index f1c9c6232d..3e46153a55 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1,12 +1,16 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define DIRSERV_PRIVATE #include "or.h" #include "buffers.h" #include "config.h" +#include "confparse.h" +#include "channel.h" +#include "channeltls.h" +#include "command.h" #include "connection.h" #include "connection_or.h" #include "control.h" @@ -62,6 +66,13 @@ static cached_dir_t *the_directory = NULL; /** For authoritative directories: the current (v1) network status. */ static cached_dir_t the_runningrouters; +/** Total number of routers with measured bandwidth; this is set by + * dirserv_count_measured_bws() before the loop in + * dirserv_generate_networkstatus_vote_obj() and checked by + * dirserv_get_credible_bandwidth() and + * dirserv_compute_performance_thresholds() */ +static int routers_with_measured_bw = 0; + static void directory_remove_invalid(void); static cached_dir_t *dirserv_regenerate_directory(void); static char *format_versions_list(config_line_t *ln); @@ -79,10 +90,10 @@ static const signed_descriptor_t *get_signed_descriptor_by_fp( const char *fp, int extrainfo, time_t publish_cutoff); -static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg); - -/************** Measured Bandwidth parsing code ******/ -#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */ +static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei, + const char **msg); +static uint32_t dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri); +static uint32_t dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri); /************** Fingerprint handling code ************/ @@ -388,18 +399,18 @@ 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)); - /* Versions before Tor 0.2.1.30 have known security issues that + /* Versions before Tor 0.2.2.35 have known security issues that * make them unsuitable for the current network. */ - if (platform && !tor_version_as_new_as(platform,"0.2.1.30")) { + if (platform && !tor_version_as_new_as(platform,"0.2.2.35")) { if (msg) - *msg = "Tor version is insecure. Please upgrade!"; + *msg = "Tor version is insecure or unsupported. Please upgrade!"; return FP_REJECT; - } else if (platform && tor_version_as_new_as(platform,"0.2.2.1-alpha")) { - /* Versions from 0.2.2.1-alpha...0.2.2.20-alpha have known security + } else if (platform && tor_version_as_new_as(platform,"0.2.3.0-alpha")) { + /* Versions from 0.2.3-alpha...0.2.3.9-alpha have known security * issues that make them unusable for the current network */ - if (!tor_version_as_new_as(platform, "0.2.2.21-alpha")) { + if (!tor_version_as_new_as(platform, "0.2.3.10-alpha")) { if (msg) - *msg = "Tor version is insecure. Please upgrade!"; + *msg = "Tor version is insecure or unsupported. Please upgrade!"; return FP_REJECT; } } @@ -501,8 +512,8 @@ dirserv_free_fingerprint_list(void) if (!fingerprint_list) return; - strmap_free(fingerprint_list->fp_by_name, _tor_free); - digestmap_free(fingerprint_list->status_by_digest, _tor_free); + strmap_free(fingerprint_list->fp_by_name, tor_free_); + digestmap_free(fingerprint_list->status_by_digest, tor_free_); tor_free(fingerprint_list); } @@ -717,7 +728,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) "MAX_DESCRIPTOR_UPLOAD_SIZE (%d) constant is too low.", ri->nickname, source, (int)ri->cache_info.signed_descriptor_len, MAX_DESCRIPTOR_UPLOAD_SIZE); - *msg = "Router descriptor was too large"; + *msg = "Router descriptor was too large."; control_event_or_authdir_new_descriptor("REJECTED", ri->cache_info.signed_descriptor_body, ri->cache_info.signed_descriptor_len, *msg); @@ -980,6 +991,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) unreachable. */ int answer; + const or_options_t *options = get_options(); node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest); tor_assert(node); @@ -988,17 +1000,27 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) answer = ! we_are_hibernating(); } else if (router->is_hibernating && (router->cache_info.published_on + - HIBERNATION_PUBLICATION_SKEW) > router->last_reachable) { + HIBERNATION_PUBLICATION_SKEW) > node->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) { + } else if (options->AssumeReachable) { /* If AssumeReachable, everybody is up unless they say they are down! */ answer = 1; } 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); + /* Otherwise, a router counts as up if we found all announced OR + ports reachable in the last REACHABLE_TIMEOUT seconds. + + XXX prop186 For now there's always one IPv4 and at most one + IPv6 OR port. + + If we're not on IPv6, don't consider reachability of potential + IPv6 OR port since that'd kill all dual stack relays until a + majority of the dir auths have IPv6 connectivity. */ + answer = (now < node->last_reachable + REACHABLE_TIMEOUT && + (options->AuthDirHasIPv6Connectivity != 1 || + tor_addr_is_null(&router->ipv6_addr) || + now < node->last_reachable6 + REACHABLE_TIMEOUT)); } if (!answer && running_long_enough_to_decide_unreachable()) { @@ -1008,11 +1030,13 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) REACHABILITY_TEST_CYCLE_PERIOD seconds, then the router has probably been down since at least that time after we last successfully reached it. + + XXX ipv6 */ time_t when = now; - if (router->last_reachable && - router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD < now) - when = router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD; + if (node->last_reachable && + node->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD < now) + when = node->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD; rep_hist_note_router_unreachable(router->cache_info.identity_digest, when); } @@ -1117,6 +1141,8 @@ int dirserv_dump_directory_to_string(char **dir_out, crypto_pk_t *private_key) { + /* XXXX 024 Get rid of this function if we can confirm that nobody's + * fetching these any longer */ char *cp; char *identity_pkey; /* Identity key, DER64-encoded. */ char *recommended_versions; @@ -1399,7 +1425,7 @@ clear_cached_dir(cached_dir_t *d) /** Free all storage held by the cached_dir_t in <b>d</b>. */ static void -_free_cached_dir(void *_d) +free_cached_dir_(void *_d) { cached_dir_t *d; if (!_d) @@ -1417,21 +1443,12 @@ _free_cached_dir(void *_d) * If <b>is_running_routers</b>, this is really a v1 running_routers * document rather than a v1 directory. */ -void -dirserv_set_cached_directory(const char *directory, time_t published, - int is_running_routers) +static void +dirserv_set_cached_directory(const char *directory, time_t published) { - time_t now = time(NULL); - if (is_running_routers) { - if (published >= now - MAX_V1_RR_AGE) - set_cached_dir(&cached_runningrouters, tor_strdup(directory), published); - } else { - if (published >= now - MAX_V1_DIRECTORY_AGE) { - cached_dir_decref(cached_directory); - cached_directory = new_cached_dir(tor_strdup(directory), published); - } - } + cached_dir_decref(cached_directory); + cached_directory = new_cached_dir(tor_strdup(directory), published); } /** If <b>networkstatus</b> is non-NULL, we've just received a v2 @@ -1448,7 +1465,6 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus, time_t published) { cached_dir_t *d, *old_d; - smartlist_t *trusted_dirs; if (!cached_v2_networkstatus) cached_v2_networkstatus = digestmap_new(); @@ -1471,9 +1487,9 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus, } /* Now purge old entries. */ - trusted_dirs = router_get_trusted_dir_servers(); + if (digestmap_size(cached_v2_networkstatus) > - smartlist_len(trusted_dirs) + MAX_UNTRUSTED_NETWORKSTATUSES) { + get_n_authorities(V2_DIRINFO) + MAX_UNTRUSTED_NETWORKSTATUSES) { /* We need to remove the oldest untrusted networkstatus. */ const char *oldest = NULL; time_t oldest_published = TIME_MAX; @@ -1613,6 +1629,8 @@ dirserv_get_directory(void) static cached_dir_t * dirserv_regenerate_directory(void) { + /* XXXX 024 Get rid of this function if we can confirm that nobody's + * fetching these any longer */ char *new_directory=NULL; if (dirserv_dump_directory_to_string(&new_directory, @@ -1632,7 +1650,7 @@ dirserv_regenerate_directory(void) /* Save the directory to disk so we re-load it quickly on startup. */ - dirserv_set_cached_directory(the_directory->dir, time(NULL), 0); + dirserv_set_cached_directory(the_directory->dir, time(NULL)); return the_directory; } @@ -1758,17 +1776,13 @@ static double guard_wfu = 0.0; * many seconds. */ static long guard_tk = 0; /** Any router with a bandwidth at least this high is "Fast" */ -static uint32_t fast_bandwidth = 0; +static uint32_t fast_bandwidth_kb = 0; /** If exits can be guards, then all guards must have a bandwidth this * high. */ -static uint32_t guard_bandwidth_including_exits = 0; +static uint32_t guard_bandwidth_including_exits_kb = 0; /** If exits can't be guards, then all guards must have a bandwidth this * high. */ -static uint32_t guard_bandwidth_excluding_exits = 0; -/** Total bandwidth of all the routers we're considering. */ -static uint64_t total_bandwidth = 0; -/** Total bandwidth of all the exit routers we're considering. */ -static uint64_t total_exit_bandwidth = 0; +static uint32_t guard_bandwidth_excluding_exits_kb = 0; /** Helper: estimate the uptime of a router given its stated uptime and the * amount of time since it last stated its stated uptime. */ @@ -1812,8 +1826,8 @@ dirserv_thinks_router_is_unreliable(time_t now, } } if (need_capacity) { - uint32_t bw = router_get_advertised_bandwidth(router); - if (bw < fast_bandwidth) + uint32_t bw_kb = dirserv_get_credible_bandwidth_kb(router); + if (bw_kb < fast_bandwidth_kb) return 1; } return 0; @@ -1859,34 +1873,67 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, node->is_running); } +/** Don't consider routers with less bandwidth than this when computing + * thresholds. */ +#define ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB 4 + +/** Helper for dirserv_compute_performance_thresholds(): Decide whether to + * include a router in our calculations, and return true iff we should; the + * require_mbw parameter is passed in by + * dirserv_compute_performance_thresholds() and controls whether we ever + * count routers with only advertised bandwidths */ +static int +router_counts_toward_thresholds(const node_t *node, time_t now, + const digestmap_t *omit_as_sybil, + int require_mbw) +{ + /* Have measured bw? */ + int have_mbw = + dirserv_has_measured_bw(node->identity); + uint64_t min_bw_kb = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB; + const or_options_t *options = get_options(); + + if (options->TestingTorNetwork) { + min_bw_kb = (int64_t)options->TestingMinExitFlagThreshold / 1000; + } + + return node->ri && router_is_active(node->ri, node, now) && + !digestmap_get(omit_as_sybil, node->identity) && + (dirserv_get_credible_bandwidth_kb(node->ri) >= min_bw_kb) && + (have_mbw || !require_mbw); +} + /** Look through the routerlist, the Mean Time Between Failure history, and * the Weighted Fractional Uptime history, and use them to set thresholds for * the Stable, Fast, and Guard flags. Update the fields stable_uptime, * stable_mtbf, enough_mtbf_info, guard_wfu, guard_tk, fast_bandwidth, * guard_bandwidh_including_exits, guard_bandwidth_excluding_exits, - * total_bandwidth, and total_exit_bandwidth. * * Also, set the is_exit flag of each router appropriately. */ static void -dirserv_compute_performance_thresholds(routerlist_t *rl) +dirserv_compute_performance_thresholds(routerlist_t *rl, + digestmap_t *omit_as_sybil) { int n_active, n_active_nonexit, n_familiar; - uint32_t *uptimes, *bandwidths, *bandwidths_excluding_exits; + uint32_t *uptimes, *bandwidths_kb, *bandwidths_excluding_exits_kb; long *tks; double *mtbfs, *wfus; time_t now = time(NULL); const or_options_t *options = get_options(); + /* Require mbw? */ + int require_mbw = + (routers_with_measured_bw > + options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0; + /* initialize these all here, in case there are no routers */ stable_uptime = 0; stable_mtbf = 0; - fast_bandwidth = 0; - guard_bandwidth_including_exits = 0; - guard_bandwidth_excluding_exits = 0; + fast_bandwidth_kb = 0; + guard_bandwidth_including_exits_kb = 0; + guard_bandwidth_excluding_exits_kb = 0; guard_tk = 0; guard_wfu = 0; - total_bandwidth = 0; - total_exit_bandwidth = 0; /* Initialize arrays that will hold values for each router. We'll * sort them and use that to compute thresholds. */ @@ -1894,9 +1941,9 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) /* Uptime for every active router. */ uptimes = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); /* Bandwidth for every active router. */ - bandwidths = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); + bandwidths_kb = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); /* Bandwidth for every active non-exit router. */ - bandwidths_excluding_exits = + bandwidths_excluding_exits_kb = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers)); /* Weighted mean time between failure for each active router. */ mtbfs = tor_malloc(sizeof(double)*smartlist_len(rl->routers)); @@ -1909,21 +1956,19 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) /* Now, fill in the arrays. */ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) { - routerinfo_t *ri = node->ri; - if (ri && router_is_active(ri, node, now)) { - const char *id = ri->cache_info.identity_digest; - uint32_t bw; + if (router_counts_toward_thresholds(node, now, omit_as_sybil, + require_mbw)) { + routerinfo_t *ri = node->ri; + const char *id = node->identity; + uint32_t bw_kb; node->is_exit = (!router_exit_policy_rejects_all(ri) && exit_policy_is_general_exit(ri->exit_policy)); uptimes[n_active] = (uint32_t)real_uptime(ri, now); mtbfs[n_active] = rep_hist_get_stability(id, now); tks [n_active] = rep_hist_get_weighted_time_known(id, now); - bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri); - total_bandwidth += bw; - if (node->is_exit && !node->is_bad_exit) { - total_exit_bandwidth += bw; - } else { - bandwidths_excluding_exits[n_active_nonexit] = bw; + bandwidths_kb[n_active] = bw_kb = dirserv_get_credible_bandwidth_kb(ri); + if (!node->is_exit || node->is_bad_exit) { + bandwidths_excluding_exits_kb[n_active_nonexit] = bw_kb; ++n_active_nonexit; } ++n_active; @@ -1937,11 +1982,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) /* The median mtbf is stable, if we have enough mtbf info */ stable_mtbf = median_double(mtbfs, n_active); /* The 12.5th percentile bandwidth is fast. */ - fast_bandwidth = find_nth_uint32(bandwidths, n_active, n_active/8); + fast_bandwidth_kb = find_nth_uint32(bandwidths_kb, n_active, n_active/8); /* (Now bandwidths is sorted.) */ - if (fast_bandwidth < ROUTER_REQUIRED_MIN_BANDWIDTH/2) - fast_bandwidth = bandwidths[n_active/4]; - guard_bandwidth_including_exits = bandwidths[(n_active-1)/2]; + if (fast_bandwidth_kb < ROUTER_REQUIRED_MIN_BANDWIDTH/(2 * 1000)) + fast_bandwidth_kb = bandwidths_kb[n_active/4]; + guard_bandwidth_including_exits_kb = bandwidths_kb[(n_active-1)/2]; guard_tk = find_nth_long(tks, n_active, n_active/8); } @@ -1950,29 +1995,39 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) { /* We can vote on a parameter for the minimum and maximum. */ - int32_t min_fast, max_fast; +#define ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG 4 + int32_t min_fast_kb, max_fast_kb, min_fast, max_fast; min_fast = networkstatus_get_param(NULL, "FastFlagMinThreshold", - 0, 0, INT32_MAX); + ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG, + ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG, + INT32_MAX); + if (options->TestingTorNetwork) { + min_fast = (int32_t)options->TestingMinFastFlagThreshold; + } max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold", INT32_MAX, min_fast, INT32_MAX); - if (fast_bandwidth < (uint32_t)min_fast) - fast_bandwidth = min_fast; - if (fast_bandwidth > (uint32_t)max_fast) - fast_bandwidth = max_fast; + min_fast_kb = min_fast / 1000; + max_fast_kb = max_fast / 1000; + + if (fast_bandwidth_kb < (uint32_t)min_fast_kb) + fast_bandwidth_kb = min_fast_kb; + if (fast_bandwidth_kb > (uint32_t)max_fast_kb) + fast_bandwidth_kb = max_fast_kb; } /* Protect sufficiently fast nodes from being pushed out of the set * of Fast nodes. */ if (options->AuthDirFastGuarantee && - fast_bandwidth > options->AuthDirFastGuarantee) - fast_bandwidth = (uint32_t)options->AuthDirFastGuarantee; + fast_bandwidth_kb > options->AuthDirFastGuarantee/1000) + fast_bandwidth_kb = (uint32_t)options->AuthDirFastGuarantee/1000; /* Now that we have a time-known that 7/8 routers are known longer than, * fill wfus with the wfu of every such "familiar" router. */ n_familiar = 0; SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) { - routerinfo_t *ri = node->ri; - if (ri && router_is_active(ri, node, now)) { + if (router_counts_toward_thresholds(node, now, + omit_as_sybil, require_mbw)) { + routerinfo_t *ri = node->ri; const char *id = ri->cache_info.identity_digest; long tk = rep_hist_get_weighted_time_known(id, now); if (tk < guard_tk) @@ -1988,32 +2043,259 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) enough_mtbf_info = rep_hist_have_measured_enough_stability(); if (n_active_nonexit) { - guard_bandwidth_excluding_exits = - median_uint32(bandwidths_excluding_exits, n_active_nonexit); + guard_bandwidth_excluding_exits_kb = + median_uint32(bandwidths_excluding_exits_kb, n_active_nonexit); } - log(LOG_INFO, LD_DIRSERV, + log_info(LD_DIRSERV, "Cutoffs: For Stable, %lu sec uptime, %lu sec MTBF. " - "For Fast: %lu bytes/sec. " + "For Fast: %lu kilobytes/sec. " "For Guard: WFU %.03f%%, time-known %lu sec, " - "and bandwidth %lu or %lu bytes/sec. We%s have enough stability data.", + "and bandwidth %lu or %lu kilobytes/sec. " + "We%s have enough stability data.", (unsigned long)stable_uptime, (unsigned long)stable_mtbf, - (unsigned long)fast_bandwidth, + (unsigned long)fast_bandwidth_kb, guard_wfu*100, (unsigned long)guard_tk, - (unsigned long)guard_bandwidth_including_exits, - (unsigned long)guard_bandwidth_excluding_exits, + (unsigned long)guard_bandwidth_including_exits_kb, + (unsigned long)guard_bandwidth_excluding_exits_kb, enough_mtbf_info ? "" : " don't "); tor_free(uptimes); tor_free(mtbfs); - tor_free(bandwidths); - tor_free(bandwidths_excluding_exits); + tor_free(bandwidths_kb); + tor_free(bandwidths_excluding_exits_kb); tor_free(tks); tor_free(wfus); } +/** Measured bandwidth cache entry */ +typedef struct mbw_cache_entry_s { + long mbw_kb; + time_t as_of; +} mbw_cache_entry_t; + +/** Measured bandwidth cache - keys are identity_digests, values are + * mbw_cache_entry_t *. */ +static digestmap_t *mbw_cache = NULL; + +/** Store a measured bandwidth cache entry when reading the measured + * bandwidths file. */ +void +dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line, + time_t as_of) +{ + mbw_cache_entry_t *e = NULL; + + tor_assert(parsed_line); + + /* Allocate a cache if we need */ + if (!mbw_cache) mbw_cache = digestmap_new(); + + /* Check if we have an existing entry */ + e = digestmap_get(mbw_cache, parsed_line->node_id); + /* If we do, we can re-use it */ + if (e) { + /* Check that we really are newer, and update */ + if (as_of > e->as_of) { + e->mbw_kb = parsed_line->bw_kb; + e->as_of = as_of; + } + } else { + /* We'll have to insert a new entry */ + e = tor_malloc(sizeof(*e)); + e->mbw_kb = parsed_line->bw_kb; + e->as_of = as_of; + digestmap_set(mbw_cache, parsed_line->node_id, e); + } +} + +/** Clear and free the measured bandwidth cache */ +void +dirserv_clear_measured_bw_cache(void) +{ + if (mbw_cache) { + /* Free the map and all entries */ + digestmap_free(mbw_cache, tor_free_); + mbw_cache = NULL; + } +} + +/** Scan the measured bandwidth cache and remove expired entries */ +void +dirserv_expire_measured_bw_cache(time_t now) +{ + + if (mbw_cache) { + /* Iterate through the cache and check each entry */ + DIGESTMAP_FOREACH_MODIFY(mbw_cache, k, mbw_cache_entry_t *, e) { + if (now > e->as_of + MAX_MEASUREMENT_AGE) { + tor_free(e); + MAP_DEL_CURRENT(k); + } + } DIGESTMAP_FOREACH_END; + + /* Check if we cleared the whole thing and free if so */ + if (digestmap_size(mbw_cache) == 0) { + digestmap_free(mbw_cache, tor_free_); + mbw_cache = 0; + } + } +} + +/** Get the current size of the measured bandwidth cache */ +int +dirserv_get_measured_bw_cache_size(void) +{ + if (mbw_cache) return digestmap_size(mbw_cache); + else return 0; +} + +/** Query the cache by identity digest, return value indicates whether + * we found it. The bw_out and as_of_out pointers receive the cached + * bandwidth value and the time it was cached if not NULL. */ +int +dirserv_query_measured_bw_cache_kb(const char *node_id, long *bw_kb_out, + time_t *as_of_out) +{ + mbw_cache_entry_t *v = NULL; + int rv = 0; + + if (mbw_cache && node_id) { + v = digestmap_get(mbw_cache, node_id); + if (v) { + /* Found something */ + rv = 1; + if (bw_kb_out) *bw_kb_out = v->mbw_kb; + if (as_of_out) *as_of_out = v->as_of; + } + } + + return rv; +} + +/** Predicate wrapper for dirserv_query_measured_bw_cache() */ +int +dirserv_has_measured_bw(const char *node_id) +{ + return dirserv_query_measured_bw_cache_kb(node_id, NULL, NULL); +} + +/** Get the best estimate of a router's bandwidth for dirauth purposes, + * preferring measured to advertised values if available. */ + +static uint32_t +dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri) +{ + uint32_t bw_kb = 0; + /* + * Yeah, measured bandwidths in measured_bw_line_t are (implicitly + * signed) longs and the ones router_get_advertised_bandwidth() returns + * are uint32_t. + */ + long mbw_kb = 0; + + if (ri) { + /* + * * First try to see if we have a measured bandwidth; don't bother with + * as_of_out here, on the theory that a stale measured bandwidth is still + * better to trust than an advertised one. + */ + if (dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest, + &mbw_kb, NULL)) { + /* Got one! */ + bw_kb = (uint32_t)mbw_kb; + } else { + /* If not, fall back to advertised */ + bw_kb = router_get_advertised_bandwidth(ri) / 1000; + } + } + + return bw_kb; +} + +/** Look through the routerlist, and using the measured bandwidth cache count + * how many measured bandwidths we know. This is used to decide whether we + * ever trust advertised bandwidths for purposes of assigning flags. */ +static void +dirserv_count_measured_bws(routerlist_t *rl) +{ + /* Initialize this first */ + routers_with_measured_bw = 0; + + tor_assert(rl); + tor_assert(rl->routers); + + /* Iterate over the routerlist and count measured bandwidths */ + SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) { + /* Check if we know a measured bandwidth for this one */ + if (dirserv_has_measured_bw(ri->cache_info.identity_digest)) { + ++routers_with_measured_bw; + } + } SMARTLIST_FOREACH_END(ri); +} + +/** Return the bandwidth we believe for assigning flags; prefer measured + * over advertised, and if we have above a threshold quantity of measured + * bandwidths, we don't want to ever give flags to unmeasured routers, so + * return 0. */ +static uint32_t +dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri) +{ + int threshold; + uint32_t bw_kb = 0; + long mbw_kb; + + tor_assert(ri); + /* Check if we have a measured bandwidth, and check the threshold if not */ + if (!(dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest, + &mbw_kb, NULL))) { + threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; + if (routers_with_measured_bw > threshold) { + /* Return zero for unmeasured bandwidth if we are above threshold */ + bw_kb = 0; + } else { + /* Return an advertised bandwidth otherwise */ + bw_kb = router_get_advertised_bandwidth_capped(ri) / 1000; + } + } else { + /* We have the measured bandwidth in mbw */ + bw_kb = (uint32_t)mbw_kb; + } + + return bw_kb; +} + +/** Give a statement of our current performance thresholds for inclusion + * in a vote document. */ +char * +dirserv_get_flag_thresholds_line(void) +{ + char *result=NULL; + const int measured_threshold = + get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; + const int enough_measured_bw = routers_with_measured_bw > measured_threshold; + + tor_asprintf(&result, + "stable-uptime=%lu stable-mtbf=%lu " + "fast-speed=%lu " + "guard-wfu=%.03f%% guard-tk=%lu " + "guard-bw-inc-exits=%lu guard-bw-exc-exits=%lu " + "enough-mtbf=%d ignoring-advertised-bws=%d", + (unsigned long)stable_uptime, + (unsigned long)stable_mtbf, + (unsigned long)fast_bandwidth_kb*1000, + guard_wfu*100, + (unsigned long)guard_tk, + (unsigned long)guard_bandwidth_including_exits_kb*1000, + (unsigned long)guard_bandwidth_excluding_exits_kb*1000, + enough_mtbf_info ? 1 : 0, + enough_measured_bw ? 1 : 0); + + return result; +} + /** Given a platform string as in a routerinfo_t (possibly null), return a * newly allocated version string for a networkstatus document, or NULL if the * platform doesn't give a Tor version. */ @@ -2034,38 +2316,39 @@ version_from_platform(const char *platform) return NULL; } -/** Helper: write the router-status information in <b>rs</b> into <b>buf</b>, - * 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. +/** Helper: write the router-status information in <b>rs</b> into a newly + * allocated character buffer. 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. * - * The format argument has three possible values: + * The format argument has one of the following 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_V3_VOTE - Output a complete V3 NS vote. If <b>vrs</b> is present, + * it contains additional information for the vote. * NS_CONTROL_PORT - Output a NS document for the control port */ -int -routerstatus_format_entry(char *buf, size_t buf_len, - const routerstatus_t *rs, const char *version, - routerstatus_format_type_t format) +char * +routerstatus_format_entry(const routerstatus_t *rs, const char *version, + routerstatus_format_type_t format, + const vote_routerstatus_t *vrs) { - int r; - char *cp; char *summary; + char *result = NULL; char published[ISO_TIME_LEN+1]; char identity64[BASE64_DIGEST_LEN+1]; char digest64[BASE64_DIGEST_LEN+1]; + smartlist_t *chunks = NULL; format_iso_time(published, rs->published_on); digest_to_base64(identity64, rs->identity_digest); digest_to_base64(digest64, rs->descriptor_digest); - r = tor_snprintf(buf, buf_len, + chunks = smartlist_new(); + smartlist_add_asprintf(chunks, "r %s %s %s%s%s %s %d %d\n", rs->nickname, identity64, @@ -2075,21 +2358,26 @@ routerstatus_format_entry(char *buf, size_t buf_len, fmt_addr32(rs->addr), (int)rs->or_port, (int)rs->dir_port); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); - return -1; - } /* 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); - /* NOTE: Whenever this list expands, be sure to increase MAX_FLAG_LINE_LEN*/ - r = tor_snprintf(cp, buf_len - (cp-buf), + /* V3 microdesc consensuses don't have "a" lines. */ + if (format == NS_V3_CONSENSUS_MICRODESC) + goto done; + + /* Possible "a" line. At most one for now. */ + if (!tor_addr_is_null(&rs->ipv6_addr)) { + smartlist_add_asprintf(chunks, "a %s\n", + fmt_addrport(&rs->ipv6_addr, rs->ipv6_orport)); + } + + if (format == NS_V3_CONSENSUS) + goto done; + + smartlist_add_asprintf(chunks, "s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", @@ -2105,25 +2393,16 @@ routerstatus_format_entry(char *buf, size_t buf_len, rs->is_unnamed?" Unnamed":"", rs->is_v2_dir?" V2Dir":"", rs->is_valid?" Valid":""); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); - return -1; - } - cp += strlen(cp); /* length of "opt v \n" */ #define V_LINE_OVERHEAD 7 if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) { - if (tor_snprintf(cp, buf_len - (cp-buf), "opt v %s\n", version)<0) { - log_warn(LD_BUG, "Unable to print router version."); - return -1; - } - cp += strlen(cp); + smartlist_add_asprintf(chunks, "v %s\n", version); } if (format != NS_V2) { const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest); - uint32_t bw; + uint32_t bw_kb; if (format != NS_CONTROL_PORT) { /* Blow up more or less nicely if we didn't get anything or not the @@ -2138,12 +2417,13 @@ routerstatus_format_entry(char *buf, size_t buf_len, log_warn(LD_BUG, "Cannot get any descriptor for %s " "(wanted descriptor %s).", id, dd); - return -1; - }; + goto err; + } - /* This assert can fire for the control port, because + /* This assert could fire for the control port, because * it can request NS documents before all descriptors - * have been fetched. */ + * have been fetched. Therefore, we only do this test when + * format != NS_CONTROL_PORT. */ if (tor_memneq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { @@ -2163,48 +2443,41 @@ routerstatus_format_entry(char *buf, size_t buf_len, tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)); - }; + } } if (format == NS_CONTROL_PORT && rs->has_bandwidth) { - bw = rs->bandwidth; + bw_kb = rs->bandwidth_kb; } else { tor_assert(desc); - bw = router_get_advertised_bandwidth_capped(desc) / 1000; + bw_kb = router_get_advertised_bandwidth_capped(desc) / 1000; } - r = tor_snprintf(cp, buf_len - (cp-buf), - "w Bandwidth=%d\n", bw); + smartlist_add_asprintf(chunks, + "w Bandwidth=%d", bw_kb); - 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); + if (format == NS_V3_VOTE && vrs && vrs->has_measured_bw) { + smartlist_add_asprintf(chunks, + " Measured=%d", vrs->measured_bw_kb); } + smartlist_add(chunks, tor_strdup("\n")); 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); + summary = policy_summarize(desc->exit_policy, AF_INET); + smartlist_add_asprintf(chunks, "p %s\n", summary); tor_free(summary); } } - return 0; + done: + result = smartlist_join_strings(chunks, "", 0, NULL); + + err: + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + } + + return result; } /** Helper for sorting: compares two routerinfos first by address, and then by @@ -2213,11 +2486,11 @@ routerstatus_format_entry(char *buf, size_t buf_len, * and a router with more bandwidth is more useful than one with less.) **/ static int -_compare_routerinfo_by_ip_and_bw(const void **a, const void **b) +compare_routerinfo_by_ip_and_bw_(const void **a, const void **b) { routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; int first_is_auth, second_is_auth; - uint32_t bw_first, bw_second; + uint32_t bw_kb_first, bw_kb_second; const node_t *node_first, *node_second; int first_is_running, second_is_running; @@ -2228,7 +2501,7 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b) else if (first->addr > second->addr) return 1; - /* Potentially, this next bit could cause k n lg n memcmp calls. But in + /* Potentially, this next bit could cause k n lg n memeq calls. But in * reality, we will almost never get here, since addresses will usually be * different. */ @@ -2252,12 +2525,12 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b) else if (!first_is_running && second_is_running) return 1; - bw_first = router_get_advertised_bandwidth(first); - bw_second = router_get_advertised_bandwidth(second); + bw_kb_first = dirserv_get_bandwidth_for_router_kb(first); + bw_kb_second = dirserv_get_bandwidth_for_router_kb(second); - if (bw_first > bw_second) + if (bw_kb_first > bw_kb_second) return -1; - else if (bw_first < bw_second) + else if (bw_kb_first < bw_kb_second) return 1; /* They're equal! Compare by identity digest, so there's a @@ -2288,7 +2561,7 @@ get_possible_sybil_list(const smartlist_t *routers) max_with_same_addr_on_authority = INT_MAX; smartlist_add_all(routers_by_ip, routers); - smartlist_sort(routers_by_ip, _compare_routerinfo_by_ip_and_bw); + smartlist_sort(routers_by_ip, compare_routerinfo_by_ip_and_bw_); omit_as_sybil = digestmap_new(); last_addr = 0; @@ -2393,9 +2666,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, int listbaddirs, int vote_on_hsdirs) { const or_options_t *options = get_options(); - int unstable_version = - !tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs"); - uint32_t routerbw = router_get_advertised_bandwidth(ri); + uint32_t routerbw_kb = dirserv_get_credible_bandwidth_kb(ri); memset(rs, 0, sizeof(routerstatus_t)); @@ -2406,8 +2677,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_exit = node->is_exit; rs->is_stable = node->is_stable = router_is_active(ri, node, now) && - !dirserv_thinks_router_is_unreliable(now, ri, 1, 0) && - !unstable_version; + !dirserv_thinks_router_is_unreliable(now, ri, 1, 0); rs->is_fast = node->is_fast = router_is_active(ri, node, now) && !dirserv_thinks_router_is_unreliable(now, ri, 0, 1); @@ -2423,9 +2693,9 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, if (node->is_fast && ((options->AuthDirGuardBWGuarantee && - routerbw >= options->AuthDirGuardBWGuarantee) || - routerbw >= MIN(guard_bandwidth_including_exits, - guard_bandwidth_excluding_exits)) && + routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) || + routerbw_kb >= MIN(guard_bandwidth_including_exits_kb, + guard_bandwidth_excluding_exits_kb)) && is_router_version_good_for_possible_guard(ri->platform)) { long tk = rep_hist_get_weighted_time_known( node->identity, now); @@ -2453,6 +2723,14 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, strlcpy(rs->nickname, ri->nickname, sizeof(rs->nickname)); rs->or_port = ri->or_port; rs->dir_port = ri->dir_port; + if (options->AuthDirHasIPv6Connectivity == 1 && + !tor_addr_is_null(&ri->ipv6_addr) && + node->last_reachable6 >= now - REACHABLE_TIMEOUT) { + /* We're configured as having IPv6 connectivity. There's an IPv6 + OR port and it's reachable so copy it to the routerstatus. */ + tor_addr_copy(&rs->ipv6_addr, &ri->ipv6_addr); + rs->ipv6_orport = ri->ipv6_orport; + } } /** Routerstatus <b>rs</b> is part of a group of routers that are on @@ -2512,7 +2790,7 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line) } cp+=strlen("bw="); - out->bw = tor_parse_long(cp, 0, 0, LONG_MAX, &parse_ok, &endptr); + out->bw_kb = 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)); @@ -2561,16 +2839,16 @@ int measured_bw_line_apply(measured_bw_line_t *parsed_line, smartlist_t *routerstatuses) { - routerstatus_t *rs = NULL; + vote_routerstatus_t *rs = NULL; if (!routerstatuses) return 0; rs = smartlist_bsearch(routerstatuses, parsed_line->node_id, - compare_digest_to_routerstatus_entry); + compare_digest_to_vote_routerstatus_entry); if (rs) { rs->has_measured_bw = 1; - rs->measured_bw = (uint32_t)parsed_line->bw; + rs->measured_bw_kb = (uint32_t)parsed_line->bw_kb; } else { log_info(LD_DIRSERV, "Node ID %s not found in routerstatus list", parsed_line->node_hex); @@ -2581,7 +2859,7 @@ measured_bw_line_apply(measured_bw_line_t *parsed_line, /** * Read the measured bandwidth file and apply it to the list of - * routerstatuses. Returns -1 on error, 0 otherwise. + * vote_routerstatus_t. Returns -1 on error, 0 otherwise. */ int dirserv_read_measured_bandwidths(const char *from_file, @@ -2590,8 +2868,9 @@ dirserv_read_measured_bandwidths(const char *from_file, char line[256]; FILE *fp = tor_fopen_cloexec(from_file, "r"); int applied_lines = 0; - time_t file_time; + time_t file_time, now; int ok; + if (fp == NULL) { log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s", from_file); @@ -2615,7 +2894,8 @@ dirserv_read_measured_bandwidths(const char *from_file, return -1; } - if ((time(NULL) - file_time) > MAX_MEASUREMENT_AGE) { + now = time(NULL); + if ((now - file_time) > MAX_MEASUREMENT_AGE) { log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u", (unsigned)(time(NULL) - file_time)); fclose(fp); @@ -2623,18 +2903,23 @@ dirserv_read_measured_bandwidths(const char *from_file, } if (routerstatuses) - smartlist_sort(routerstatuses, compare_routerstatus_entries); + smartlist_sort(routerstatuses, compare_vote_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) { + /* Also cache the line for dirserv_get_bandwidth_for_router() */ + dirserv_cache_measured_bw(&parsed_line, file_time); if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0) applied_lines++; } } } + /* Now would be a nice time to clean the cache, too */ + dirserv_expire_measured_bw_cache(now); + fclose(fp); log_info(LD_DIRSERV, "Bandwidth measurement file successfully read. " @@ -2672,11 +2957,11 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, tor_assert(private_key); tor_assert(cert); - if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { + if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); return NULL; } - if (!strchr(hostname, '.')) { + if (!hostname || !strchr(hostname, '.')) { tor_free(hostname); hostname = tor_dup_ip(addr); } @@ -2698,19 +2983,44 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, if (!contact) contact = "(none)"; + /* + * Do this so dirserv_compute_performance_thresholds() and + * set_routerstatus_from_routerinfo() see up-to-date bandwidth info. + */ + if (options->V3BandwidthsFile) { + dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL); + } else { + /* + * No bandwidths file; clear the measured bandwidth cache in case we had + * one last time around. + */ + if (dirserv_get_measured_bw_cache_size() > 0) { + dirserv_clear_measured_bw_cache(); + } + } + /* precompute this part, since we need it to decide what "stable" * means. */ SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { dirserv_set_router_is_running(ri, now); }); - dirserv_compute_performance_thresholds(rl); - routers = smartlist_new(); smartlist_add_all(routers, rl->routers); routers_sort_by_identity(routers); omit_as_sybil = get_possible_sybil_list(routers); + DIGESTMAP_FOREACH(omit_as_sybil, sybil_id, void *, ignore) { + (void) ignore; + rep_hist_make_router_pessimal(sybil_id, now); + } DIGESTMAP_FOREACH_END; + + /* Count how many have measured bandwidths so we know how to assign flags; + * this must come before dirserv_compute_performance_thresholds() */ + dirserv_count_measured_bws(rl); + + dirserv_compute_performance_thresholds(rl, omit_as_sybil); + routerstatuses = smartlist_new(); microdescriptors = smartlist_new(); @@ -2718,7 +3028,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, if (ri->cache_info.published_on >= cutoff) { routerstatus_t *rs; vote_routerstatus_t *vrs; - microdesc_t *md; node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest); if (!node) continue; @@ -2736,18 +3045,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, rs->is_flagged_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); - } + vrs->microdesc = dirvote_format_all_microdesc_vote_lines(ri, now, + microdescriptors); smartlist_add(routerstatuses, vrs); } @@ -2764,9 +3063,18 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, smartlist_free(routers); digestmap_free(omit_as_sybil, NULL); + /* This pass through applies the measured bw lines to the routerstatuses */ if (options->V3BandwidthsFile) { dirserv_read_measured_bandwidths(options->V3BandwidthsFile, routerstatuses); + } else { + /* + * No bandwidths file; clear the measured bandwidth cache in case we had + * one last time around. + */ + if (dirserv_get_measured_bw_cache_size() > 0) { + dirserv_clear_measured_bw_cache(); + } } v3_out = tor_malloc_zero(sizeof(networkstatus_t)); @@ -2859,14 +3167,13 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, /** For v2 authoritative directories only: Replace the contents of * <b>the_v2_networkstatus</b> with a newly generated network status * object. */ -static cached_dir_t * +cached_dir_t * generate_v2_networkstatus_opinion(void) { cached_dir_t *r = NULL; - size_t len, identity_pkey_len; + size_t identity_pkey_len; char *status = NULL, *client_versions = NULL, *server_versions = NULL, *identity_pkey = NULL, *hostname = NULL; - char *outp, *endp; const or_options_t *options = get_options(); char fingerprint[FINGERPRINT_LEN+1]; char published[ISO_TIME_LEN+1]; @@ -2885,13 +3192,16 @@ generate_v2_networkstatus_opinion(void) char *version_lines = NULL; smartlist_t *routers = NULL; digestmap_t *omit_as_sybil = NULL; + smartlist_t *chunks = NULL; private_key = get_server_identity_key(); - if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { + if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); goto done; } + if (!hostname) + hostname = tor_dup_ip(addr); format_iso_time(published, now); @@ -2921,12 +3231,8 @@ generate_v2_networkstatus_opinion(void) version_lines = tor_strdup(""); } - len = 4096+strlen(client_versions)+strlen(server_versions); - len += identity_pkey_len*2; - len += (RS_ENTRY_LEN)*smartlist_len(rl->routers); - - status = tor_malloc(len); - tor_snprintf(status, len, + chunks = smartlist_new(); + smartlist_add_asprintf(chunks, "network-status-version 2\n" "dir-source %s %s %d\n" "fingerprint %s\n" @@ -2946,8 +3252,6 @@ generate_v2_networkstatus_opinion(void) versioning ? " Versions" : "", version_lines, identity_pkey); - outp = status + strlen(status); - endp = status + len; /* precompute this part, since we need it to decide what "stable" * means. */ @@ -2955,14 +3259,13 @@ generate_v2_networkstatus_opinion(void) dirserv_set_router_is_running(ri, now); }); - dirserv_compute_performance_thresholds(rl); - routers = smartlist_new(); smartlist_add_all(routers, rl->routers); routers_sort_by_identity(routers); - omit_as_sybil = get_possible_sybil_list(routers); + dirserv_compute_performance_thresholds(rl, omit_as_sybil); + SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) { if (ri->cache_info.published_on >= cutoff) { routerstatus_t rs; @@ -2979,34 +3282,33 @@ generate_v2_networkstatus_opinion(void) 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, NS_V2)) { - log_warn(LD_BUG, "Unable to print router status."); - tor_free(version); - goto done; + { + char *rsf = routerstatus_format_entry(&rs, version, NS_V2, NULL); + if (rsf) + smartlist_add(chunks, rsf); } tor_free(version); - outp += strlen(outp); } } SMARTLIST_FOREACH_END(ri); - if (tor_snprintf(outp, endp-outp, "directory-signature %s\n", - options->Nickname)<0) { - log_warn(LD_BUG, "Unable to write signature line."); - goto done; - } - if (router_get_networkstatus_v2_hash(status, digest)<0) { - log_warn(LD_BUG, "Unable to hash network status"); - goto done; - } - outp += strlen(outp); + smartlist_add_asprintf(chunks, "directory-signature %s\n", + options->Nickname); + + crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1); note_crypto_pk_op(SIGN_DIR); - 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; + { + char *sig; + if (!(sig = router_get_dirobj_signature(digest,DIGEST_LEN, + private_key))) { + log_warn(LD_BUG, "Unable to sign router status."); + goto done; + } + smartlist_add(chunks, sig); } + status = smartlist_join_strings(chunks, "", 0, NULL); + { networkstatus_v2_t *ns; if (!(ns = networkstatus_v2_parse_from_string(status))) { @@ -3028,6 +3330,10 @@ generate_v2_networkstatus_opinion(void) } done: + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + } tor_free(client_versions); tor_free(server_versions); tor_free(version_lines); @@ -3074,7 +3380,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, } } else { SMARTLIST_FOREACH(router_get_trusted_dir_servers(), - trusted_dir_server_t *, ds, + dir_server_t *, ds, if (ds->type & V2_DIRINFO) smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN))); } @@ -3273,36 +3579,42 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, * Inform the reachability checker that we could get to this guy. */ void -dirserv_orconn_tls_done(const char *address, +dirserv_orconn_tls_done(const tor_addr_t *addr, uint16_t or_port, const char *digest_rcvd) { - routerinfo_t *ri; + node_t *node = NULL; + tor_addr_port_t orport; + routerinfo_t *ri = NULL; time_t now = time(NULL); - tor_assert(address); + tor_assert(addr); tor_assert(digest_rcvd); - ri = router_get_mutable_by_digest(digest_rcvd); - - if (ri == NULL) + node = node_get_mutable_by_id(digest_rcvd); + if (node == NULL || node->ri == NULL) return; + ri = node->ri; - if (!strcasecmp(address, ri->address) && or_port == ri->or_port) { + tor_addr_copy(&orport.addr, addr); + orport.port = or_port; + if (router_has_orport(ri, &orport)) { /* Found the right router. */ if (!authdir_mode_bridge(get_options()) || ri->purpose == ROUTER_PURPOSE_BRIDGE) { + char addrstr[TOR_ADDR_BUF_LEN]; /* This is a bridge or we're not a bridge authorititative -- mark it as reachable. */ - tor_addr_t addr, *addrp=NULL; log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.", router_describe(ri), - address, ri->or_port); - if (tor_addr_parse(&addr, ri->address) != -1) - addrp = &addr; - else - log_warn(LD_BUG, "Couldn't parse IP address \"%s\"", ri->address); - rep_hist_note_router_reachable(digest_rcvd, addrp, or_port, now); - ri->last_reachable = now; + tor_addr_to_str(addrstr, addr, sizeof(addrstr), 1), + ri->or_port); + if (tor_addr_family(addr) == AF_INET) { + rep_hist_note_router_reachable(digest_rcvd, addr, or_port, now); + node->last_reachable = now; + } else if (tor_addr_family(addr) == AF_INET6) { + /* No rephist for IPv6. */ + node->last_reachable6 = now; + } } } } @@ -3325,7 +3637,7 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri, /* It just came out of hibernation; launch a reachability test */ return 1; } - if (! routers_have_same_or_addr(ri, ri_old)) { + if (! routers_have_same_or_addrs(ri, ri_old)) { /* Address or port changed; launch a reachability test */ return 1; } @@ -3338,15 +3650,35 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri, void dirserv_single_reachability_test(time_t now, routerinfo_t *router) { + channel_t *chan = NULL; + node_t *node = NULL; tor_addr_t router_addr; + (void) now; + + tor_assert(router); + node = node_get_mutable_by_id(router->cache_info.identity_digest); + tor_assert(node); + + /* IPv4. */ 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); + chan = channel_tls_connect(&router_addr, router->or_port, + router->cache_info.identity_digest); + if (chan) command_setup_channel(chan); + + /* Possible IPv6. */ + if (get_options()->AuthDirHasIPv6Connectivity == 1 && + !tor_addr_is_null(&router->ipv6_addr)) { + char addrstr[TOR_ADDR_BUF_LEN]; + log_debug(LD_OR, "Testing reachability of %s at %s:%u.", + router->nickname, + tor_addr_to_str(addrstr, &router->ipv6_addr, sizeof(addrstr), 1), + router->ipv6_orport); + chan = channel_tls_connect(&router->ipv6_addr, router->ipv6_orport, + router->cache_info.identity_digest); + if (chan) command_setup_channel(chan); + } } /** Auth dir server only: load balance such that we only @@ -3649,7 +3981,7 @@ connection_dirserv_add_microdescs_to_outbuf(dir_connection_t *conn) char *fp256 = smartlist_pop_last(conn->fingerprint_stack); microdesc_t *md = microdesc_cache_lookup_by_digest256(cache, fp256); tor_free(fp256); - if (!md) + if (!md || !md->body) continue; if (conn->zlib_state) { /* XXXX024 This 'last' business should actually happen on the last @@ -3767,7 +4099,7 @@ connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn) int connection_dirserv_flushed_some(dir_connection_t *conn) { - tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING); + tor_assert(conn->base_.state == DIR_CONN_STATE_SERVER_WRITING); if (connection_get_outbuf_len(TO_CONN(conn)) >= DIRSERV_BUFFER_MIN) return 0; @@ -3802,9 +4134,11 @@ dirserv_free_all(void) cached_dir_decref(cached_directory); clear_cached_dir(&cached_runningrouters); - digestmap_free(cached_v2_networkstatus, _free_cached_dir); + digestmap_free(cached_v2_networkstatus, free_cached_dir_); cached_v2_networkstatus = NULL; - strmap_free(cached_consensuses, _free_cached_dir); + strmap_free(cached_consensuses, free_cached_dir_); cached_consensuses = NULL; + + dirserv_clear_measured_bw_cache(); } diff --git a/src/or/dirserv.h b/src/or/dirserv.h index 22269b2009..f9d36d760f 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for dirserv.c. **/ -#ifndef _TOR_DIRSERV_H -#define _TOR_DIRSERV_H +#ifndef TOR_DIRSERV_H +#define TOR_DIRSERV_H /** What fraction (1 over this number) of the relay ID space do we * (as a directory authority) launch connections to at each reachability @@ -29,28 +29,6 @@ /** 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 \ - ) int connection_dirserv_flushed_some(dir_connection_t *conn); @@ -70,12 +48,12 @@ 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_t *private_key); +char *dirserv_get_flag_thresholds_line(void); int directory_fetches_from_authorities(const or_options_t *options); int directory_fetches_dir_info_early(const or_options_t *options); int directory_fetches_dir_info_later(const or_options_t *options); int directory_caches_v2_dir_info(const or_options_t *options); -#define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o) int directory_caches_unknown_auth_certs(const or_options_t *options); int directory_caches_dir_info(const or_options_t *options); int directory_permits_begindir_requests(const or_options_t *options); @@ -87,8 +65,6 @@ 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); @@ -107,7 +83,7 @@ int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key, 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, +void dirserv_orconn_tls_done(const tor_addr_t *addr, uint16_t or_port, const char *digest_rcvd); int dirserv_should_launch_reachability_test(const routerinfo_t *ri, @@ -130,18 +106,33 @@ 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, +char *routerstatus_format_entry( const routerstatus_t *rs, const char *platform, - routerstatus_format_type_t format); + routerstatus_format_type_t format, + const vote_routerstatus_t *vrs); 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 + +/* Put the MAX_MEASUREMENT_AGE #define here so unit tests can see it */ +#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */ + 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); + +void dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line, + time_t as_of); +void dirserv_clear_measured_bw_cache(void); +void dirserv_expire_measured_bw_cache(time_t now); +int dirserv_get_measured_bw_cache_size(void); +int dirserv_query_measured_bw_cache_kb(const char *node_id, long *bw_out, + time_t *as_of_out); +int dirserv_has_measured_bw(const char *node_id); +cached_dir_t *generate_v2_networkstatus_opinion(void); #endif int dirserv_read_measured_bandwidths(const char *from_file, diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 144859ae04..c6d1244902 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define DIRVOTE_PRIVATE @@ -53,36 +53,10 @@ 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 13 - -/** 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 - -/** Lowest consensus method that ensures a majority of authorities voted - * for a param. */ -#define MIN_METHOD_FOR_MAJORITY_PARAMS 12 - -/** Lowest consensus method where microdesc consensuses omit any entry - * with no microdesc. */ -#define MIN_METHOD_FOR_MANDATORY_MICRODESC 13 - /* ===== * 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. */ @@ -90,17 +64,14 @@ char * format_networkstatus_vote(crypto_pk_t *private_signing_key, networkstatus_t *v3_ns) { - size_t len; - char *status = NULL; + smartlist_t *chunks; const char *client_versions = NULL, *server_versions = NULL; - char *outp, *endp; char fingerprint[FINGERPRINT_LEN+1]; char digest[DIGEST_LEN]; uint32_t addr; - routerlist_t *rl = router_get_routerlist(); - char *version_lines = NULL; - int r; + char *client_versions_line = NULL, *server_versions_line = NULL; networkstatus_voter_info_t *voter; + char *status = NULL; tor_assert(private_signing_key); tor_assert(v3_ns->type == NS_TYPE_VOTE || v3_ns->type == NS_TYPE_OPINION); @@ -114,49 +85,28 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, client_versions = v3_ns->client_versions; server_versions = v3_ns->server_versions; - if (client_versions || server_versions) { - size_t v_len = 64; - char *cp; - if (client_versions) - v_len += strlen(client_versions); - if (server_versions) - v_len += strlen(server_versions); - version_lines = tor_malloc(v_len); - cp = version_lines; - if (client_versions) { - 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) { - 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); - } - } + if (client_versions) { + tor_asprintf(&client_versions_line, "client-versions %s\n", + client_versions); } else { - version_lines = tor_strdup(""); + client_versions_line = tor_strdup(""); + } + if (server_versions) { + tor_asprintf(&server_versions_line, "server-versions %s\n", + server_versions); + } else { + server_versions_line = tor_strdup(""); } - len = 8192; - len += strlen(version_lines); - 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); + chunks = smartlist_new(); { char published[ISO_TIME_LEN+1]; char va[ISO_TIME_LEN+1]; char fu[ISO_TIME_LEN+1]; char vu[ISO_TIME_LEN+1]; char *flags = smartlist_join_strings(v3_ns->known_flags, " ", 0, NULL); + /* XXXX Abstraction violation: should be pulling a field out of v3_ns.*/ + char *flag_thresholds = dirserv_get_flag_thresholds_line(); char *params; authority_cert_t *cert = v3_ns->cert; char *methods = @@ -172,7 +122,7 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, params = tor_strdup(""); tor_assert(cert); - r = tor_snprintf(status, len, + smartlist_add_asprintf(chunks, "network-status-version 3\n" "vote-status %s\n" "consensus-methods %s\n" @@ -181,8 +131,9 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, "fresh-until %s\n" "valid-until %s\n" "voting-delay %d %d\n" - "%s" /* versions */ + "%s%s" /* versions */ "known-flags %s\n" + "flag-thresholds %s\n" "params %s\n" "dir-source %s %s %s %s %d %d\n" "contact %s\n", @@ -190,99 +141,76 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, methods, published, va, fu, vu, v3_ns->vote_seconds, v3_ns->dist_seconds, - version_lines, + client_versions_line, + server_versions_line, flags, + flag_thresholds, params, voter->nickname, fingerprint, voter->address, fmt_addr32(addr), 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(flag_thresholds); 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); - 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); + smartlist_add_asprintf(chunks, "legacy-dir-key %s\n", fpbuf); } - tor_assert(outp + cert->cache_info.signed_descriptor_len < endp); - memcpy(outp, cert->cache_info.signed_descriptor_body, - cert->cache_info.signed_descriptor_len); - - outp += cert->cache_info.signed_descriptor_len; + smartlist_add(chunks, tor_strndup(cert->cache_info.signed_descriptor_body, + cert->cache_info.signed_descriptor_len)); } SMARTLIST_FOREACH_BEGIN(v3_ns->routerstatus_list, vote_routerstatus_t *, vrs) { + char *rsf; vote_microdesc_hash_t *h; - if (routerstatus_format_entry(outp, endp-outp, &vrs->status, - vrs->version, NS_V3_VOTE) < 0) { - log_warn(LD_BUG, "Unable to print router status."); - goto err; - } - outp += strlen(outp); + rsf = routerstatus_format_entry(&vrs->status, + vrs->version, NS_V3_VOTE, vrs); + if (rsf) + smartlist_add(chunks, rsf); 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_add(chunks, tor_strdup(h->microdesc_hash_line)); } } 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); + smartlist_add(chunks, tor_strdup("directory-footer\n")); + + /* The digest includes everything up through the space after + * directory-signature. (Yuck.) */ + crypto_digest_smartlist(digest, DIGEST_LEN, chunks, + "directory-signature ", DIGEST_SHA1); { char signing_key_fingerprint[FINGERPRINT_LEN+1]; - if (tor_snprintf(outp, endp-outp, "directory-signature ")<0) { - log_warn(LD_BUG, "Unable to start signature line."); - goto err; - } - outp += strlen(outp); - if (crypto_pk_get_fingerprint(private_signing_key, signing_key_fingerprint, 0)<0) { log_warn(LD_BUG, "Unable to get fingerprint for signing key"); goto err; } - if (tor_snprintf(outp, endp-outp, "%s %s\n", fingerprint, - signing_key_fingerprint)<0) { - log_warn(LD_BUG, "Unable to end signature line."); - goto err; - } - outp += strlen(outp); + + smartlist_add_asprintf(chunks, "directory-signature %s %s\n", fingerprint, + signing_key_fingerprint); } - 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, DIGEST_LEN, - private_signing_key)<0) { - log_warn(LD_BUG, "Unable to sign networkstatus vote."); - goto err; + { + char *sig = router_get_dirobj_signature(digest, DIGEST_LEN, + private_signing_key); + if (!sig) { + log_warn(LD_BUG, "Unable to sign networkstatus vote."); + goto err; + } + smartlist_add(chunks, sig); } + status = smartlist_join_strings(chunks, "", 0, NULL); + { networkstatus_t *v; if (!(v = networkstatus_parse_vote_from_string(status, NULL, @@ -300,7 +228,12 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, err: tor_free(status); done: - tor_free(version_lines); + tor_free(client_versions_line); + tor_free(server_versions_line); + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + } return status; } @@ -346,7 +279,7 @@ typedef struct dir_src_ent_t { /** Helper for sorting networkstatus_t votes (not consensuses) by the * hash of their voters' identity digests. */ static int -_compare_votes_by_authority_id(const void **_a, const void **_b) +compare_votes_by_authority_id_(const void **_a, const void **_b) { const networkstatus_t *a = *_a, *b = *_b; return fast_memcmp(get_voter(a)->identity_digest, @@ -357,7 +290,7 @@ _compare_votes_by_authority_id(const void **_a, const void **_b) * their identity digests, and return -1, 0, or 1 depending on their * ordering */ static int -_compare_dir_src_ents_by_authority_id(const void **_a, const void **_b) +compare_dir_src_ents_by_authority_id_(const void **_a, const void **_b) { const dir_src_ent_t *a = *_a, *b = *_b; const networkstatus_voter_info_t *a_v = get_voter(a->v), @@ -424,12 +357,27 @@ compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b) /** Helper for sorting routerlists based on compare_vote_rs. */ static int -_compare_vote_rs(const void **_a, const void **_b) +compare_vote_rs_(const void **_a, const void **_b) { const vote_routerstatus_t *a = *_a, *b = *_b; return compare_vote_rs(a,b); } +/** Helper for sorting OR ports. */ +static int +compare_orports_(const void **_a, const void **_b) +{ + const tor_addr_port_t *a = *_a, *b = *_b; + int r; + + if ((r = tor_addr_compare(&a->addr, &b->addr, CMP_EXACT))) + return r; + if ((r = (((int) b->port) - ((int) a->port)))) + return r; + + return 0; +} + /** Given a list of vote_routerstatus_t, all for the same router identity, * return whichever is most frequent, breaking ties in favor of more * recently published vote_routerstatus_t and in case of ties there, @@ -437,17 +385,18 @@ _compare_vote_rs(const void **_a, const void **_b) */ static vote_routerstatus_t * compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, - char *microdesc_digest256_out) + char *microdesc_digest256_out, + tor_addr_port_t *best_alt_orport_out) { vote_routerstatus_t *most = NULL, *cur = NULL; int most_n = 0, cur_n = 0; time_t most_published = 0; - /* _compare_vote_rs() sorts the items by identity digest (all the same), + /* compare_vote_rs_() sorts the items by identity digest (all the same), * then by SD digest. That way, if we have a tie that the published_on * date cannot tie, we use the descriptor with the smaller digest. */ - smartlist_sort(votes, _compare_vote_rs); + smartlist_sort(votes, compare_vote_rs_); SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) { if (cur && !compare_vote_rs(cur, rs)) { ++cur_n; @@ -473,6 +422,38 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, tor_assert(most); + /* If we're producing "a" lines, vote on potential alternative (sets + * of) OR port(s) in the winning routerstatuses. + * + * XXX prop186 There's at most one alternative OR port (_the_ IPv6 + * port) for now. */ + if (consensus_method >= MIN_METHOD_FOR_A_LINES && best_alt_orport_out) { + smartlist_t *alt_orports = smartlist_new(); + const tor_addr_port_t *most_alt_orport = NULL; + + SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) { + if (compare_vote_rs(most, rs) == 0 && + !tor_addr_is_null(&rs->status.ipv6_addr) + && rs->status.ipv6_orport) { + smartlist_add(alt_orports, tor_addr_port_new(&rs->status.ipv6_addr, + rs->status.ipv6_orport)); + } + } SMARTLIST_FOREACH_END(rs); + + smartlist_sort(alt_orports, compare_orports_); + most_alt_orport = smartlist_get_most_frequent(alt_orports, + compare_orports_); + if (most_alt_orport) { + memcpy(best_alt_orport_out, most_alt_orport, sizeof(tor_addr_port_t)); + log_debug(LD_DIR, "\"a\" line winner for %s is %s", + most->status.nickname, + fmt_addrport(&most_alt_orport->addr, most_alt_orport->port)); + } + + SMARTLIST_FOREACH(alt_orports, tor_addr_port_t *, ap, tor_free(ap)); + smartlist_free(alt_orports); + } + if (consensus_method >= MIN_METHOD_FOR_MICRODESC && microdesc_digest256_out) { smartlist_t *digests = smartlist_new(); @@ -496,29 +477,11 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, return most; } -/** 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, size_t len_out, - smartlist_t *lst, digest_algorithm_t alg) -{ - crypto_digest_t *d; - if (alg == DIGEST_SHA1) - d = crypto_digest_new(); - else - d = crypto_digest256_new(alg); - SMARTLIST_FOREACH(lst, const char *, cp, - crypto_digest_add_bytes(d, cp, strlen(cp))); - crypto_digest_get_digest(d, digest_out, len_out); - crypto_digest_free(d); -} - /** Sorting helper: compare two strings based on their values as base-ten * positive integers. (Non-integers are treated as prior to all integers, and * compared lexically.) */ static int -_cmp_int_strings(const void **_a, const void **_b) +cmp_int_strings_(const void **_a, const void **_b) { const char *a = *_a, *b = *_b; int ai = (int)tor_parse_long(a, 10, 1, INT_MAX, NULL, NULL); @@ -549,13 +512,13 @@ compute_consensus_method(smartlist_t *votes) { tor_assert(vote->supported_methods); smartlist_add_all(tmp, vote->supported_methods); - smartlist_sort(tmp, _cmp_int_strings); - smartlist_uniq(tmp, _cmp_int_strings, NULL); + smartlist_sort(tmp, cmp_int_strings_); + smartlist_uniq(tmp, cmp_int_strings_, NULL); smartlist_add_all(all_methods, tmp); smartlist_clear(tmp); }); - smartlist_sort(all_methods, _cmp_int_strings); + smartlist_sort(all_methods, cmp_int_strings_); get_frequent_members(acceptable_methods, all_methods, min); n_ok = smartlist_len(acceptable_methods); if (n_ok) { @@ -1358,6 +1321,7 @@ networkstatus_compute_consensus(smartlist_t *votes, char *client_versions = NULL, *server_versions = NULL; smartlist_t *flags; const char *flavor_name; + uint32_t max_unmeasured_bw_kb = DEFAULT_MAX_UNMEASURED_BW_KB; 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; @@ -1504,7 +1468,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* Sort the votes. */ - smartlist_sort(votes, _compare_votes_by_authority_id); + smartlist_sort(votes, compare_votes_by_authority_id_); /* Add the authority sections. */ { smartlist_t *dir_sources = smartlist_new(); @@ -1523,7 +1487,7 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_add(dir_sources, e_legacy); } } SMARTLIST_FOREACH_END(v); - smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id); + smartlist_sort(dir_sources, compare_dir_src_ents_by_authority_id_); SMARTLIST_FOREACH_BEGIN(dir_sources, const dir_src_ent_t *, e) { char fingerprint[HEX_DIGEST_LEN+1]; @@ -1556,6 +1520,30 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_free(dir_sources); } + if (consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW) { + char *max_unmeasured_param = NULL; + /* XXXX Extract this code into a common function */ + if (params) { + if (strcmpstart(params, "maxunmeasuredbw=") == 0) + max_unmeasured_param = params; + else + max_unmeasured_param = strstr(params, " maxunmeasuredbw="); + } + if (max_unmeasured_param) { + int ok = 0; + char *eq = strchr(max_unmeasured_param, '='); + if (eq) { + max_unmeasured_bw_kb = (uint32_t) + tor_parse_ulong(eq+1, 10, 1, UINT32_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_DIR, "Bad element '%s' in max unmeasured bw param", + escaped(max_unmeasured_param)); + max_unmeasured_bw_kb = DEFAULT_MAX_UNMEASURED_BW_KB; + } + } + } + } + /* Add the actual router entries. */ { int *index; /* index[j] is the current index into votes[j]. */ @@ -1567,9 +1555,10 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_t *chosen_flags = smartlist_new(); smartlist_t *versions = smartlist_new(); smartlist_t *exitsummaries = smartlist_new(); - uint32_t *bandwidths = tor_malloc(sizeof(uint32_t) * smartlist_len(votes)); - uint32_t *measured_bws = tor_malloc(sizeof(uint32_t) * - smartlist_len(votes)); + uint32_t *bandwidths_kb = tor_malloc(sizeof(uint32_t) * + smartlist_len(votes)); + uint32_t *measured_bws_kb = tor_malloc(sizeof(uint32_t) * + smartlist_len(votes)); int num_bandwidths; int num_mbws; @@ -1582,6 +1571,7 @@ networkstatus_compute_consensus(smartlist_t *votes, int *named_flag; /* Index of the flag "Named" for votes[j] */ int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */ int chosen_named_idx; + int n_authorities_measuring_bandwidth; strmap_t *name_to_id_map = strmap_new(); char conflict[DIGEST_LEN]; @@ -1600,10 +1590,19 @@ networkstatus_compute_consensus(smartlist_t *votes, unnamed_flag[i] = named_flag[i] = -1; chosen_named_idx = smartlist_string_pos(flags, "Named"); - /* Build the flag index. */ + /* Build the flag indexes. Note that no vote can have more than 64 members + * for known_flags, so no value will be greater than 63, so it's safe to + * do U64_LITERAL(1) << index on these values. But note also that + * named_flag and unnamed_flag are initialized to -1, so we need to check + * that they're actually set before doing U64_LITERAL(1) << index with + * them.*/ SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) { flag_map[v_sl_idx] = tor_malloc_zero( sizeof(int)*smartlist_len(v->known_flags)); + if (smartlist_len(v->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) { + log_warn(LD_BUG, "Somehow, a vote has %d entries in known_flags", + smartlist_len(v->known_flags)); + } SMARTLIST_FOREACH_BEGIN(v->known_flags, const char *, fl) { int p = smartlist_string_pos(flags, fl); tor_assert(p >= 0); @@ -1670,6 +1669,14 @@ networkstatus_compute_consensus(smartlist_t *votes, } SMARTLIST_FOREACH_END(v); } + /* We need to know how many votes measure bandwidth. */ + n_authorities_measuring_bandwidth = 0; + SMARTLIST_FOREACH(votes, networkstatus_t *, v, + if (v->has_measured_bws) { + ++n_authorities_measuring_bandwidth; + } + ); + /* Now go through all the votes */ flag_counts = tor_malloc(sizeof(int) * smartlist_len(flags)); while (1) { @@ -1685,6 +1692,7 @@ networkstatus_compute_consensus(smartlist_t *votes, int n_listing = 0; int i; char microdesc_digest[DIGEST256_LEN]; + tor_addr_port_t alt_orport = {TOR_ADDR_NULL, 0}; /* Of the next-to-be-considered digest in each voter, which is first? */ SMARTLIST_FOREACH(votes, networkstatus_t *, v, { @@ -1728,7 +1736,8 @@ networkstatus_compute_consensus(smartlist_t *votes, if (rs->flags & (U64_LITERAL(1) << i)) ++flag_counts[flag_map[v_sl_idx][i]]; } - if (rs->flags & (U64_LITERAL(1) << named_flag[v_sl_idx])) { + if (named_flag[v_sl_idx] >= 0 && + (rs->flags & (U64_LITERAL(1) << named_flag[v_sl_idx]))) { if (chosen_name && strcmp(chosen_name, rs->status.nickname)) { log_notice(LD_DIR, "Conflict on naming for router: %s vs %s", chosen_name, rs->status.nickname); @@ -1738,11 +1747,11 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* count bandwidths */ - if (rs->status.has_measured_bw) - measured_bws[num_mbws++] = rs->status.measured_bw; + if (rs->has_measured_bw) + measured_bws_kb[num_mbws++] = rs->measured_bw_kb; if (rs->status.has_bandwidth) - bandwidths[num_bandwidths++] = rs->status.bandwidth; + bandwidths_kb[num_bandwidths++] = rs->status.bandwidth_kb; } SMARTLIST_FOREACH_END(v); /* We don't include this router at all unless more than half of @@ -1754,7 +1763,7 @@ networkstatus_compute_consensus(smartlist_t *votes, * routerinfo and its contents are. */ memset(microdesc_digest, 0, sizeof(microdesc_digest)); rs = compute_routerstatus_consensus(matching_descs, consensus_method, - microdesc_digest); + microdesc_digest, &alt_orport); /* Copy bits of that into rs_out. */ memset(&rs_out, 0, sizeof(rs_out)); tor_assert(fast_memeq(lowest_id, rs->status.identity_digest,DIGEST_LEN)); @@ -1765,6 +1774,10 @@ networkstatus_compute_consensus(smartlist_t *votes, rs_out.published_on = rs->status.published_on; rs_out.dir_port = rs->status.dir_port; rs_out.or_port = rs->status.or_port; + if (consensus_method >= MIN_METHOD_FOR_A_LINES) { + tor_addr_copy(&rs_out.ipv6_addr, &alt_orport.addr); + rs_out.ipv6_orport = alt_orport.port; + } rs_out.has_bandwidth = 0; rs_out.has_exitsummary = 0; @@ -1828,28 +1841,37 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Pick a bandwidth */ if (consensus_method >= 6 && num_mbws > 2) { rs_out.has_bandwidth = 1; - rs_out.bandwidth = median_uint32(measured_bws, num_mbws); + rs_out.bw_is_unmeasured = 0; + rs_out.bandwidth_kb = median_uint32(measured_bws_kb, num_mbws); } else if (consensus_method >= 5 && num_bandwidths > 0) { rs_out.has_bandwidth = 1; - rs_out.bandwidth = median_uint32(bandwidths, num_bandwidths); + rs_out.bw_is_unmeasured = 1; + rs_out.bandwidth_kb = median_uint32(bandwidths_kb, num_bandwidths); + if (consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW && + n_authorities_measuring_bandwidth > 2) { + /* Cap non-measured bandwidths. */ + if (rs_out.bandwidth_kb > max_unmeasured_bw_kb) { + rs_out.bandwidth_kb = max_unmeasured_bw_kb; + } + } } /* Fix bug 2203: Do not count BadExit nodes as Exits for bw weights */ - if (consensus_method >= 11) { + if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) { is_exit = is_exit && !is_bad_exit; } if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS) { if (rs_out.has_bandwidth) { - T += rs_out.bandwidth; + T += rs_out.bandwidth_kb; if (is_exit && is_guard) - D += rs_out.bandwidth; + D += rs_out.bandwidth_kb; else if (is_exit) - E += rs_out.bandwidth; + E += rs_out.bandwidth_kb; else if (is_guard) - G += rs_out.bandwidth; + G += rs_out.bandwidth_kb; else - M += rs_out.bandwidth; + M += rs_out.bandwidth_kb; } else { log_warn(LD_BUG, "Missing consensus bandwidth for router %s", rs_out.nickname); @@ -1862,7 +1884,7 @@ networkstatus_compute_consensus(smartlist_t *votes, * listed that descriptor will have the same summary. If not then * something is fishy and we'll use the most common one (breaking * ties in favor of lexicographically larger one (only because it - * lets me reuse more existing code. + * lets me reuse more existing code)). * * The other case that can happen is that no authority that voted * for that descriptor has an exit policy summary. That's @@ -1948,12 +1970,12 @@ networkstatus_compute_consensus(smartlist_t *votes, } { - char buf[4096]; + char *buf; /* 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)); + buf = routerstatus_format_entry(&rs_out, NULL, rs_format, NULL); + if (buf) + smartlist_add(chunks, buf); } /* Now an m line, if applicable. */ if (flavor == FLAV_MICRODESC && @@ -1973,7 +1995,11 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_add(chunks, tor_strdup("\n")); /* Now the weight line. */ if (rs_out.has_bandwidth) { - smartlist_add_asprintf(chunks, "w Bandwidth=%d\n", rs_out.bandwidth); + int unmeasured = rs_out.bw_is_unmeasured && + consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW; + smartlist_add_asprintf(chunks, "w Bandwidth=%d%s\n", + rs_out.bandwidth_kb, + unmeasured?" Unmeasured=1":""); } /* Now the exitpolicy summary line. */ @@ -1999,8 +2025,8 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_free(chosen_flags); smartlist_free(versions); smartlist_free(exitsummaries); - tor_free(bandwidths); - tor_free(measured_bws); + tor_free(bandwidths_kb); + tor_free(measured_bws_kb); } if (consensus_method >= MIN_METHOD_FOR_FOOTER) { @@ -2016,6 +2042,7 @@ networkstatus_compute_consensus(smartlist_t *votes, // 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! + /* XXXX Extract this code into a common function */ if (params) { if (strcmpstart(params, "bwweightscale=") == 0) bw_weight_param = params; @@ -2060,12 +2087,12 @@ networkstatus_compute_consensus(smartlist_t *votes, size_t digest_len = flavor == FLAV_NS ? DIGEST_LEN : DIGEST256_LEN; const char *algname = crypto_digest_algorithm_get_name(digest_alg); - char sigbuf[4096]; + char *signature; smartlist_add(chunks, tor_strdup("directory-signature ")); /* Compute the hash of the chunks. */ - hash_list_members(digest, digest_len, chunks, digest_alg); + crypto_digest_smartlist(digest, digest_len, chunks, "", digest_alg); /* Get the fingerprints */ crypto_pk_get_fingerprint(identity_key, fingerprint, 0); @@ -2081,14 +2108,12 @@ networkstatus_compute_consensus(smartlist_t *votes, signing_key_fingerprint); } /* And the signature. */ - sigbuf[0] = '\0'; - if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf), - digest, digest_len, - signing_key)) { + if (!(signature = router_get_dirobj_signature(digest, digest_len, + signing_key))) { log_warn(LD_BUG, "Couldn't sign consensus networkstatus."); - return NULL; /* This leaks, but it should never happen. */ + goto done; } - smartlist_add(chunks, tor_strdup(sigbuf)); + smartlist_add(chunks, signature); if (legacy_id_key_digest && legacy_signing_key && consensus_method >= 3) { smartlist_add(chunks, tor_strdup("directory-signature ")); @@ -2104,26 +2129,18 @@ networkstatus_compute_consensus(smartlist_t *votes, algname, fingerprint, signing_key_fingerprint); } - sigbuf[0] = '\0'; - if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf), - digest, digest_len, - legacy_signing_key)) { + + if (!(signature = router_get_dirobj_signature(digest, digest_len, + legacy_signing_key))) { log_warn(LD_BUG, "Couldn't sign consensus networkstatus."); - return NULL; /* This leaks, but it should never happen. */ + goto done; } - smartlist_add(chunks, tor_strdup(sigbuf)); + smartlist_add(chunks, signature); } } result = smartlist_join_strings(chunks, "", 0, NULL); - tor_free(client_versions); - tor_free(server_versions); - SMARTLIST_FOREACH(flags, char *, cp, tor_free(cp)); - smartlist_free(flags); - SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); - smartlist_free(chunks); - { networkstatus_t *c; if (!(c = networkstatus_parse_vote_from_string(result, NULL, @@ -2131,15 +2148,24 @@ networkstatus_compute_consensus(smartlist_t *votes, log_err(LD_BUG, "Generated a networkstatus consensus we couldn't " "parse."); tor_free(result); - return NULL; + goto done; } // Verify balancing parameters if (consensus_method >= MIN_METHOD_FOR_BW_WEIGHTS && added_weights) { - networkstatus_verify_bw_weights(c); + networkstatus_verify_bw_weights(c, consensus_method); } networkstatus_vote_free(c); } + done: + + tor_free(client_versions); + tor_free(server_versions); + SMARTLIST_FOREACH(flags, char *, cp, tor_free(cp)); + smartlist_free(flags); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + return result; } @@ -2193,7 +2219,7 @@ networkstatus_add_detached_signatures(networkstatus_t *target, { digests_t *digests = strmap_get(sigs->digests, flavor); int n_matches = 0; - digest_algorithm_t alg; + int alg; if (!digests) { *msg_out = "No digests for given consensus flavor"; return -1; @@ -2258,7 +2284,7 @@ networkstatus_add_detached_signatures(networkstatus_t *target, if (sig->good_signature || !old_sig || old_sig->bad_signature) { log_info(LD_DIR, "Adding signature from %s with %s", voter_identity, algorithm); - log(severity, LD_DIR, "Added a signature for %s from %s.", + tor_log(severity, LD_DIR, "Added a signature for %s from %s.", target_voter->nickname, source); ++r; if (old_sig) { @@ -2457,7 +2483,7 @@ ns_detached_signatures_free(ns_detached_signatures_t *s) smartlist_free(sigs); } STRMAP_FOREACH_END; strmap_free(s->signatures, NULL); - strmap_free(s->digests, _tor_free); + strmap_free(s->digests, tor_free_); } tor_free(s); @@ -2757,7 +2783,7 @@ dirvote_fetch_missing_votes(void) char *resource; SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(), - trusted_dir_server_t *, ds) { + dir_server_t *, ds) { if (!(ds->type & V3_DIRINFO)) continue; if (!dirvote_get_vote(ds->v3_identity_digest, @@ -2875,7 +2901,7 @@ list_v3_auth_ids(void) smartlist_t *known_v3_keys = smartlist_new(); char *keys; SMARTLIST_FOREACH(router_get_trusted_dir_servers(), - trusted_dir_server_t *, ds, + dir_server_t *, ds, if ((ds->type & V3_DIRINFO) && !tor_digest_is_zero(ds->v3_identity_digest)) smartlist_add(known_v3_keys, @@ -2896,7 +2922,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) { networkstatus_t *vote; networkstatus_voter_info_t *vi; - trusted_dir_server_t *ds; + dir_server_t *ds; pending_vote_t *pending_vote = NULL; const char *end_of_vote = NULL; int any_failed = 0; @@ -2947,7 +2973,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) /* Hey, it's a new cert! */ trusted_dirs_load_certs_from_string( vote->cert->cache_info.signed_descriptor_body, - 0 /* from_store */, 1 /*flush*/); + TRUSTED_DIRS_CERTS_SRC_FROM_VOTE, 1 /*flush*/); if (!authority_cert_get_by_digests(vote->cert->cache_info.identity_digest, vote->cert->signing_key_digest)) { log_warn(LD_BUG, "We added a cert, but still couldn't find it."); @@ -3080,7 +3106,7 @@ dirvote_compute_consensuses(void) } tor_assert(pending_vote_list); SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { - if (smartlist_string_isin(v->vote->known_flags, "Running")) + if (smartlist_contains_string(v->vote->known_flags, "Running")) n_vote_running++; }); if (!n_vote_running) { @@ -3441,7 +3467,7 @@ dirvote_free_all(void) const char * dirvote_get_pending_consensus(consensus_flavor_t flav) { - tor_assert(((int)flav) >= 0 && flav < N_CONSENSUS_FLAVORS); + tor_assert(((int)flav) >= 0 && (int)flav < N_CONSENSUS_FLAVORS); return pending_consensuses[flav].body; } @@ -3504,15 +3530,11 @@ dirvote_get_vote(const char *fp, int flags) 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. +/** Construct and return a new microdescriptor from a routerinfo <b>ri</b> + * according to <b>consensus_method</b>. **/ microdesc_t * -dirvote_create_microdescriptor(const routerinfo_t *ri) +dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) { microdesc_t *result = NULL; char *key = NULL, *summary = NULL, *family = NULL; @@ -3522,23 +3544,49 @@ dirvote_create_microdescriptor(const routerinfo_t *ri) if (crypto_pk_write_public_key_to_string(ri->onion_pkey, &key, &keylen)<0) goto done; - summary = policy_summarize(ri->exit_policy); + summary = policy_summarize(ri->exit_policy, AF_INET); if (ri->declared_family) family = smartlist_join_strings(ri->declared_family, " ", 0, NULL); smartlist_add_asprintf(chunks, "onion-key\n%s", key); + if (consensus_method >= MIN_METHOD_FOR_NTOR_KEY && + ri->onion_curve25519_pkey) { + char kbuf[128]; + base64_encode(kbuf, sizeof(kbuf), + (const char*)ri->onion_curve25519_pkey->public_key, + CURVE25519_PUBKEY_LEN); + smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf); + } + + if (consensus_method >= MIN_METHOD_FOR_A_LINES && + !tor_addr_is_null(&ri->ipv6_addr) && ri->ipv6_orport) + smartlist_add_asprintf(chunks, "a %s\n", + fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport)); + if (family) smartlist_add_asprintf(chunks, "family %s\n", family); if (summary && strcmp(summary, "reject 1-65535")) smartlist_add_asprintf(chunks, "p %s\n", summary); + if (consensus_method >= MIN_METHOD_FOR_P6_LINES && + ri->ipv6_exit_policy) { + /* XXXX024 This doesn't match proposal 208, which says these should + * be taken unchanged from the routerinfo. That's bogosity, IMO: + * the proposal should have said to do this instead.*/ + char *p6 = write_short_policy(ri->ipv6_exit_policy); + if (p6 && strcmp(p6, "reject 1-65535")) + smartlist_add_asprintf(chunks, "p6 %s\n", p6); + tor_free(p6); + } + output = smartlist_join_strings(chunks, "", 0, NULL); { smartlist_t *lst = microdescs_parse_from_string(output, - output+strlen(output), 0, 1); + output+strlen(output), 0, + SAVED_NOWHERE); 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)); @@ -3561,33 +3609,117 @@ dirvote_create_microdescriptor(const routerinfo_t *ri) 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) +dirvote_format_microdesc_vote_line(char *out_buf, size_t out_buf_len, + const microdesc_t *md, + int consensus_method_low, + int consensus_method_high) { + ssize_t ret = -1; 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); - } + char *microdesc_consensus_methods = + make_consensus_method_list(consensus_method_low, + consensus_method_high, + ","); + tor_assert(microdesc_consensus_methods); + if (digest256_to_base64(d64, md->digest)<0) - return -1; + goto out; - if (tor_snprintf(out, out_len, "m %s sha256=%s\n", + if (tor_snprintf(out_buf, out_buf_len, "m %s sha256=%s\n", microdesc_consensus_methods, d64)<0) - return -1; + goto out; + + ret = strlen(out_buf); + + out: + tor_free(microdesc_consensus_methods); + return ret; +} + +/** Array of start and end of consensus methods used for supported + microdescriptor formats. */ +static const struct consensus_method_range_t { + int low; + int high; +} microdesc_consensus_methods[] = { + {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1}, + {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1}, + {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1}, + {MIN_METHOD_FOR_NTOR_KEY, MAX_SUPPORTED_CONSENSUS_METHOD}, + {-1, -1} +}; + +/** Helper type used when generating the microdescriptor lines in a directory + * vote. */ +typedef struct microdesc_vote_line_t { + int low; + int high; + microdesc_t *md; + struct microdesc_vote_line_t *next; +} microdesc_vote_line_t; + +/** Generate and return a linked list of all the lines that should appear to + * describe a router's microdescriptor versions in a directory vote. + * Add the generated microdescriptors to <b>microdescriptors_out</b>. */ +vote_microdesc_hash_t * +dirvote_format_all_microdesc_vote_lines(const routerinfo_t *ri, time_t now, + smartlist_t *microdescriptors_out) +{ + const struct consensus_method_range_t *cmr; + microdesc_vote_line_t *entries = NULL, *ep; + vote_microdesc_hash_t *result = NULL; + + /* Generate the microdescriptors. */ + for (cmr = microdesc_consensus_methods; + cmr->low != -1 && cmr->high != -1; + cmr++) { + microdesc_t *md = dirvote_create_microdescriptor(ri, cmr->low); + if (md) { + microdesc_vote_line_t *e = + tor_malloc_zero(sizeof(microdesc_vote_line_t)); + e->md = md; + e->low = cmr->low; + e->high = cmr->high; + e->next = entries; + entries = e; + } + } + + /* Compress adjacent identical ones */ + for (ep = entries; ep; ep = ep->next) { + while (ep->next && + fast_memeq(ep->md->digest, ep->next->md->digest, DIGEST256_LEN) && + ep->low == ep->next->high + 1) { + microdesc_vote_line_t *next = ep->next; + ep->low = next->low; + microdesc_free(next->md); + ep->next = next->next; + tor_free(next); + } + } - return strlen(out); + /* Format them into vote_microdesc_hash_t, and add to microdescriptors_out.*/ + while ((ep = entries)) { + char buf[128]; + vote_microdesc_hash_t *h; + dirvote_format_microdesc_vote_line(buf, sizeof(buf), ep->md, + ep->low, ep->high); + h = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); + h->microdesc_hash_line = tor_strdup(buf); + h->next = result; + result = h; + ep->md->last_listed = now; + smartlist_add(microdescriptors_out, ep->md); + entries = ep->next; + tor_free(ep); + } + + return result; } /** If <b>vrs</b> has a hash made for the consensus method <b>method</b> with diff --git a/src/or/dirvote.h b/src/or/dirvote.h index e6f9700614..b236452122 100644 --- a/src/or/dirvote.h +++ b/src/or/dirvote.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for dirvote.c. **/ -#ifndef _TOR_DIRVOTE_H -#define _TOR_DIRVOTE_H +#ifndef TOR_DIRVOTE_H +#define TOR_DIRVOTE_H /** Lowest allowable value for VoteSeconds. */ #define MIN_VOTE_SECONDS 20 @@ -19,6 +19,50 @@ /** Smallest allowable voting interval. */ #define MIN_VOTE_INTERVAL 300 +/** The highest consensus method that we currently support. */ +#define MAX_SUPPORTED_CONSENSUS_METHOD 17 + +/** 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 + +/** Lowest consensus method that doesn't count bad exits as exits for weight */ +#define MIN_METHOD_TO_CUT_BADEXIT_WEIGHT 11 + +/** Lowest consensus method that ensures a majority of authorities voted + * for a param. */ +#define MIN_METHOD_FOR_MAJORITY_PARAMS 12 + +/** Lowest consensus method where microdesc consensuses omit any entry + * with no microdesc. */ +#define MIN_METHOD_FOR_MANDATORY_MICRODESC 13 + +/** Lowest consensus method that contains "a" lines. */ +#define MIN_METHOD_FOR_A_LINES 14 + +/** Lowest consensus method where microdescs may include a "p6" line. */ +#define MIN_METHOD_FOR_P6_LINES 15 + +/** Lowest consensus method where microdescs may include an onion-key-ntor + * line */ +#define MIN_METHOD_FOR_NTOR_KEY 16 + +/** Lowest consensus method that ensures that authorities output an + * Unmeasured=1 flag for unmeasured bandwidths */ +#define MIN_METHOD_TO_CLIP_UNMEASURED_BW 17 + +/** Default bandwidth to clip unmeasured bandwidths to using method >= + * MIN_METHOD_TO_CLIP_UNMEASURED_BW */ +#define DEFAULT_MAX_UNMEASURED_BW_KB 20 + void dirvote_free_all(void); /* vote manipulation */ @@ -70,9 +114,16 @@ networkstatus_t * dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, authority_cert_t *cert); -microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri); +microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri, + int consensus_method); ssize_t dirvote_format_microdesc_vote_line(char *out, size_t out_len, - const microdesc_t *md); + const microdesc_t *md, + int consensus_method_low, + int consensus_method_high); +vote_microdesc_hash_t *dirvote_format_all_microdesc_vote_lines( + const routerinfo_t *ri, + time_t now, + smartlist_t *microdescriptors_out); int vote_routerstatus_find_microdesc_hash(char *digest256_out, const vote_routerstatus_t *vrs, diff --git a/src/or/dns.c b/src/or/dns.c index 78893bfbed..fb1b10d82c 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -61,6 +61,9 @@ struct evdns_request; #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_ipv6(base, addr, options, cb, ptr) \ + ((evdns_resolve_ipv6((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)) @@ -84,12 +87,6 @@ struct evdns_request; * that the resolver is wedged? */ #define RESOLVE_MAX_TIMEOUT 300 -/** Possible outcomes from hostname lookup: permanent failure, - * transient (retryable) failure, and success. */ -#define DNS_RESOLVE_FAILED_TRANSIENT 1 -#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; @@ -117,7 +114,7 @@ typedef struct pending_connection_t { /* Possible states for a cached resolve_t */ /** We are waiting for the resolver system to tell us an answer here. * When we get one, or when we time out, the state of this cached_resolve_t - * will become "DONE" and we'll possibly add a CACHED_VALID or a CACHED_FAILED + * will become "DONE" and we'll possibly add a CACHED * entry. This cached_resolve_t will be in the hash table so that we will * know not to launch more requests for this addr, but rather to add more * connections to the pending list for the addr. */ @@ -128,10 +125,18 @@ typedef struct pending_connection_t { #define CACHE_STATE_DONE 1 /** We are caching an answer for this address. This should have no pending * connections, and should appear in the hash table. */ -#define CACHE_STATE_CACHED_VALID 2 -/** We are caching a failure for this address. This should have no pending - * connections, and should appear in the hash table */ -#define CACHE_STATE_CACHED_FAILED 3 +#define CACHE_STATE_CACHED 2 + +/** @name status values for a single DNS request. + * + * @{ */ +/** The DNS request is in progress. */ +#define RES_STATUS_INFLIGHT 1 +/** The DNS request finished and gave an answer */ +#define RES_STATUS_DONE_OK 2 +/** The DNS request finished and gave an error */ +#define RES_STATUS_DONE_ERR 3 +/**@}*/ /** A DNS request: possibly completed, possibly pending; cached_resolve * structs are stored at the OR side in a hash table, and as a linked @@ -139,19 +144,39 @@ typedef struct pending_connection_t { */ typedef struct cached_resolve_t { HT_ENTRY(cached_resolve_t) node; - uint32_t magic; + uint32_t magic; /**< Must be CACHED_RESOLVE_MAGIC */ char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */ + + union { + uint32_t addr_ipv4; /**< IPv4 addr for <b>address</b>, if successful. + * (In host order.) */ + int err_ipv4; /**< One of DNS_ERR_*, if IPv4 lookup failed. */ + } result_ipv4; /**< Outcome of IPv4 lookup */ + union { + struct in6_addr addr_ipv6; /**< IPv6 addr for <b>address</b>, if + * successful */ + int err_ipv6; /**< One of DNS_ERR_*, if IPv6 lookup failed. */ + } result_ipv6; /**< Outcome of IPv6 lookup, if any */ union { - struct { - struct in6_addr addr6; /**< IPv6 addr for <b>address</b>. */ - uint32_t addr; /**< IPv4 addr for <b>address</b>. */ - } a; - char *hostname; /**< Hostname for <b>address</b> (if a reverse lookup) */ - } result; - uint8_t state; /**< Is this cached entry pending/done/valid/failed? */ - uint8_t is_reverse; /**< Is this a reverse (addr-to-hostname) lookup? */ + char *hostname; /** A hostname, if PTR lookup happened successfully*/ + int err_hostname; /** One of DNS_ERR_*, if PTR lookup failed. */ + } result_ptr; + /** @name Status fields + * + * These take one of the RES_STATUS_* values, depending on the state + * of the corresponding lookup. + * + * @{ */ + unsigned int res_status_ipv4 : 2; + unsigned int res_status_ipv6 : 2; + unsigned int res_status_hostname : 2; + /**@}*/ + uint8_t state; /**< Is this cached entry pending/done/informative? */ + time_t expire; /**< Remove items from cache after this time. */ - uint32_t ttl; /**< What TTL did the nameserver tell us? */ + uint32_t ttl_ipv4; /**< What TTL did the nameserver tell us? */ + uint32_t ttl_ipv6; /**< What TTL did the nameserver tell us? */ + uint32_t ttl_hostname; /**< 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*/ @@ -159,20 +184,31 @@ typedef struct cached_resolve_t { } cached_resolve_t; static void purge_expired_resolves(time_t now); -static void dns_found_answer(const char *address, uint8_t is_reverse, - uint32_t addr, const char *hostname, char outcome, +static void dns_found_answer(const char *address, uint8_t query_type, + int dns_answer, + const tor_addr_t *addr, + const char *hostname, uint32_t ttl); -static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type); -static int launch_resolve(edge_connection_t *exitconn); +static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type, + const cached_resolve_t *resolve); +static int launch_resolve(cached_resolve_t *resolve); static void add_wildcarded_test_address(const char *address); static int configure_nameservers(int force); static int answer_is_wildcarded(const char *ip); static int dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, or_circuit_t *oncirc, char **resolved_to_hostname, - int *made_connection_pending_out); + int *made_connection_pending_out, + cached_resolve_t **resolve_out); +static int set_exitconn_info_from_resolve(edge_connection_t *exitconn, + const cached_resolve_t *resolve, + char **hostname_out); +static int evdns_err_is_transient(int err); +static void inform_pending_connections(cached_resolve_t *resolve); +static void make_pending_resolve_cached(cached_resolve_t *cached); + #ifdef DEBUG_DNS_CACHE -static void _assert_cache_ok(void); -#define assert_cache_ok() _assert_cache_ok() +static void assert_cache_ok_(void); +#define assert_cache_ok() assert_cache_ok_() #else #define assert_cache_ok() STMT_NIL #endif @@ -181,6 +217,13 @@ static void assert_resolve_ok(cached_resolve_t *resolve); /** Hash table of cached_resolve objects. */ static HT_HEAD(cache_map, cached_resolve_t) cache_root; +/** Global: how many IPv6 requests have we made in all? */ +static uint64_t n_ipv6_requests_made = 0; +/** Global: how many IPv6 requests have timed out? */ +static uint64_t n_ipv6_timeouts = 0; +/** Global: Do we think that IPv6 DNS is broken? */ +static int dns_is_broken_for_ipv6 = 0; + /** Function to compare hashed resolves on their addresses; used to * implement hash tables. */ static INLINE int @@ -219,7 +262,7 @@ evdns_log_cb(int warn, const char *msg) int severity = warn ? LOG_WARN : LOG_INFO; if (!strcmpstart(msg, "Resolve requested for") && get_options()->SafeLogging) { - log(LOG_INFO, LD_EXIT, "eventdns: Resolve requested."); + log_info(LD_EXIT, "eventdns: Resolve requested."); return; } else if (!strcmpstart(msg, "Search: ")) { return; @@ -248,13 +291,13 @@ evdns_log_cb(int warn, const char *msg) control_event_server_status(LOG_WARN, "NAMESERVER_ALL_DOWN"); all_down = 1; } - log(severity, LD_EXIT, "eventdns: %s", msg); + tor_log(severity, LD_EXIT, "eventdns: %s", msg); } /** Helper: passed to eventdns.c as a callback so it can generate random * numbers for transaction IDs and 0x20-hack coding. */ static void -_dns_randfn(char *b, size_t n) +dns_randfn_(char *b, size_t n) { crypto_rand(b,n); } @@ -264,7 +307,7 @@ int dns_init(void) { init_cache_map(); - evdns_set_random_bytes_fn(_dns_randfn); + evdns_set_random_bytes_fn(dns_randfn_); if (server_mode(get_options())) { int r = configure_nameservers(1); return r; @@ -336,7 +379,7 @@ dns_get_expiry_ttl(uint32_t ttl) /** Helper: free storage held by an entry in the DNS cache. */ static void -_free_cached_resolve(cached_resolve_t *r) +free_cached_resolve_(cached_resolve_t *r) { if (!r) return; @@ -345,8 +388,8 @@ _free_cached_resolve(cached_resolve_t *r) r->pending_connections = victim->next; tor_free(victim); } - if (r->is_reverse) - tor_free(r->result.hostname); + if (r->res_status_hostname == RES_STATUS_DONE_OK) + tor_free(r->result_ptr.hostname); r->magic = 0xFF00FF00; tor_free(r); } @@ -355,7 +398,7 @@ _free_cached_resolve(cached_resolve_t *r) * less-than-zero, zero, or greater-than-zero as appropriate. Used for * the priority queue implementation. */ static int -_compare_cached_resolves_by_expiry(const void *_a, const void *_b) +compare_cached_resolves_by_expiry_(const void *_a, const void *_b) { const cached_resolve_t *a = _a, *b = _b; if (a->expire < b->expire) @@ -370,6 +413,65 @@ _compare_cached_resolves_by_expiry(const void *_a, const void *_b) * will expire. */ static smartlist_t *cached_resolve_pqueue = NULL; +static void +cached_resolve_add_answer(cached_resolve_t *resolve, + int query_type, + int dns_result, + const tor_addr_t *answer_addr, + const char *answer_hostname, + uint32_t ttl) +{ + if (query_type == DNS_PTR) { + if (resolve->res_status_hostname != RES_STATUS_INFLIGHT) + return; + + if (dns_result == DNS_ERR_NONE && answer_hostname) { + resolve->result_ptr.hostname = tor_strdup(answer_hostname); + resolve->res_status_hostname = RES_STATUS_DONE_OK; + } else { + resolve->result_ptr.err_hostname = dns_result; + resolve->res_status_hostname = RES_STATUS_DONE_ERR; + } + resolve->ttl_hostname = ttl; + } else if (query_type == DNS_IPv4_A) { + if (resolve->res_status_ipv4 != RES_STATUS_INFLIGHT) + return; + + if (dns_result == DNS_ERR_NONE && answer_addr && + tor_addr_family(answer_addr) == AF_INET) { + resolve->result_ipv4.addr_ipv4 = tor_addr_to_ipv4h(answer_addr); + resolve->res_status_ipv4 = RES_STATUS_DONE_OK; + } else { + resolve->result_ipv4.err_ipv4 = dns_result; + resolve->res_status_ipv4 = RES_STATUS_DONE_ERR; + } + + } else if (query_type == DNS_IPv6_AAAA) { + if (resolve->res_status_ipv6 != RES_STATUS_INFLIGHT) + return; + + if (dns_result == DNS_ERR_NONE && answer_addr && + tor_addr_family(answer_addr) == AF_INET6) { + memcpy(&resolve->result_ipv6.addr_ipv6, + tor_addr_to_in6(answer_addr), + sizeof(struct in6_addr)); + resolve->res_status_ipv6 = RES_STATUS_DONE_OK; + } else { + resolve->result_ipv6.err_ipv6 = dns_result; + resolve->res_status_ipv6 = RES_STATUS_DONE_ERR; + } + } +} + +/** Return true iff there are no in-flight requests for <b>resolve</b>. */ +static int +cached_resolve_have_all_answers(const cached_resolve_t *resolve) +{ + return (resolve->res_status_ipv4 != RES_STATUS_INFLIGHT && + resolve->res_status_ipv6 != RES_STATUS_INFLIGHT && + resolve->res_status_hostname != RES_STATUS_INFLIGHT); +} + /** Set an expiry time for a cached_resolve_t, and add it to the expiry * priority queue */ static void @@ -380,7 +482,7 @@ set_expiry(cached_resolve_t *resolve, time_t expires) cached_resolve_pqueue = smartlist_new(); resolve->expire = expires; smartlist_pqueue_add(cached_resolve_pqueue, - _compare_cached_resolves_by_expiry, + compare_cached_resolves_by_expiry_, STRUCT_OFFSET(cached_resolve_t, minheap_idx), resolve); } @@ -395,13 +497,13 @@ dns_free_all(void) SMARTLIST_FOREACH(cached_resolve_pqueue, cached_resolve_t *, res, { if (res->state == CACHE_STATE_DONE) - _free_cached_resolve(res); + free_cached_resolve_(res); }); } for (ptr = HT_START(cache_map, &cache_root); ptr != NULL; ptr = next) { item = *ptr; next = HT_NEXT_RMV(cache_map, &cache_root, ptr); - _free_cached_resolve(item); + free_cached_resolve_(item); } HT_CLEAR(cache_map, &cache_root); smartlist_free(cached_resolve_pqueue); @@ -427,7 +529,7 @@ 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) { @@ -435,8 +537,7 @@ purge_expired_resolves(time_t now) "Expiring a dns resolve %s that's still pending. Forgot to " "cull it? DNS resolve didn't tell us about the timeout?", escaped_safe_str(resolve->address)); - } else if (resolve->state == CACHE_STATE_CACHED_VALID || - resolve->state == CACHE_STATE_CACHED_FAILED) { + } else if (resolve->state == CACHE_STATE_CACHED) { log_debug(LD_EXIT, "Forgetting old cached resolve (address %s, expires %lu)", escaped_safe_str(resolve->address), @@ -454,9 +555,9 @@ purge_expired_resolves(time_t now) pend = resolve->pending_connections; resolve->pending_connections = pend->next; /* Connections should only be pending if they have no socket. */ - tor_assert(!SOCKET_OK(pend->conn->_base.s)); + tor_assert(!SOCKET_OK(pend->conn->base_.s)); pendconn = pend->conn; - if (!pendconn->_base.marked_for_close) { + if (!pendconn->base_.marked_for_close) { connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT); circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); connection_free(TO_CONN(pendconn)); @@ -465,8 +566,7 @@ purge_expired_resolves(time_t now) } } - if (resolve->state == CACHE_STATE_CACHED_VALID || - resolve->state == CACHE_STATE_CACHED_FAILED || + if (resolve->state == CACHE_STATE_CACHED || resolve->state == CACHE_STATE_PENDING) { removed = HT_REMOVE(cache_map, &cache_root, resolve); if (removed != resolve) { @@ -481,8 +581,8 @@ purge_expired_resolves(time_t now) cached_resolve_t *tmp = HT_FIND(cache_map, &cache_root, resolve); tor_assert(tmp != resolve); } - if (resolve->is_reverse) - tor_free(resolve->result.hostname); + if (resolve->res_status_hostname == RES_STATUS_DONE_OK) + tor_free(resolve->result_ptr.hostname); resolve->magic = 0xF0BBF0BB; tor_free(resolve); } @@ -490,19 +590,24 @@ purge_expired_resolves(time_t now) assert_cache_ok(); } +/* argument for send_resolved_cell only, meaning "let the answer type be ipv4 + * or ipv6 depending on the connection's address". */ +#define RESOLVED_TYPE_AUTO 0xff + /** Send a response to the RESOLVE request of a connection. * <b>answer_type</b> must be one of - * RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT). + * RESOLVED_TYPE_(AUTO|ERROR|ERROR_TRANSIENT|). * * If <b>circ</b> is provided, and we have a cached answer, send the * answer back along circ; otherwise, send the answer back along * <b>conn</b>'s attached circuit. */ static void -send_resolved_cell(edge_connection_t *conn, uint8_t answer_type) +send_resolved_cell(edge_connection_t *conn, uint8_t answer_type, + const cached_resolve_t *resolved) { - char buf[RELAY_PAYLOAD_SIZE]; - size_t buflen; + char buf[RELAY_PAYLOAD_SIZE], *cp = buf; + size_t buflen = 0; uint32_t ttl; buf[0] = answer_type; @@ -510,19 +615,36 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type) switch (answer_type) { - case RESOLVED_TYPE_IPV4: - buf[1] = 4; - set_uint32(buf+2, tor_addr_to_ipv4n(&conn->_base.addr)); - set_uint32(buf+6, htonl(ttl)); - buflen = 10; - break; - /*XXXX IP6 need ipv6 implementation */ + case RESOLVED_TYPE_AUTO: + if (resolved && resolved->res_status_ipv4 == RES_STATUS_DONE_OK) { + cp[0] = RESOLVED_TYPE_IPV4; + cp[1] = 4; + set_uint32(cp+2, htonl(resolved->result_ipv4.addr_ipv4)); + set_uint32(cp+6, htonl(ttl)); + cp += 10; + } + if (resolved && resolved->res_status_ipv6 == RES_STATUS_DONE_OK) { + const uint8_t *bytes = resolved->result_ipv6.addr_ipv6.s6_addr; + cp[0] = RESOLVED_TYPE_IPV6; + cp[1] = 16; + memcpy(cp+2, bytes, 16); + set_uint32(cp+18, htonl(ttl)); + cp += 22; + } + if (cp != buf) { + buflen = cp - buf; + break; + } else { + answer_type = RESOLVED_TYPE_ERROR; + /* fall through. */ + } case RESOLVED_TYPE_ERROR_TRANSIENT: case RESOLVED_TYPE_ERROR: { const char *errmsg = "Error resolving hostname"; size_t msglen = strlen(errmsg); + buf[0] = answer_type; buf[1] = msglen; strlcpy(buf+2, errmsg, sizeof(buf)-2); set_uint32(buf+2+msglen, htonl(ttl)); @@ -600,10 +722,11 @@ dns_resolve(edge_connection_t *exitconn) int is_resolve, r; int made_connection_pending = 0; char *hostname = NULL; - is_resolve = exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE; + cached_resolve_t *resolve = NULL; + is_resolve = exitconn->base_.purpose == EXIT_PURPOSE_RESOLVE; r = dns_resolve_impl(exitconn, is_resolve, oncirc, &hostname, - &made_connection_pending); + &made_connection_pending, &resolve); switch (r) { case 1: @@ -614,7 +737,7 @@ dns_resolve(edge_connection_t *exitconn) if (hostname) send_resolved_hostname_cell(exitconn, hostname); else - send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); + send_resolved_cell(exitconn, RESOLVED_TYPE_AUTO, resolve); exitconn->on_circuit = NULL; } else { /* Add to the n_streams list; the calling function will send back a @@ -626,7 +749,7 @@ dns_resolve(edge_connection_t *exitconn) case 0: /* The request is pending: add the connection into the linked list of * resolving_streams on this circuit. */ - exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; + exitconn->base_.state = EXIT_CONN_STATE_RESOLVING; exitconn->next_stream = oncirc->resolving_streams; oncirc->resolving_streams = exitconn; break; @@ -636,14 +759,15 @@ dns_resolve(edge_connection_t *exitconn) * and stop everybody waiting for the same connection. */ if (is_resolve) { send_resolved_cell(exitconn, - (r == -1) ? RESOLVED_TYPE_ERROR : RESOLVED_TYPE_ERROR_TRANSIENT); + (r == -1) ? RESOLVED_TYPE_ERROR : RESOLVED_TYPE_ERROR_TRANSIENT, + NULL); } exitconn->on_circuit = NULL; - dns_cancel_pending_resolve(exitconn->_base.address); + dns_cancel_pending_resolve(exitconn->base_.address); - if (!made_connection_pending && !exitconn->_base.marked_for_close) { + if (!made_connection_pending && !exitconn->base_.marked_for_close) { /* If we made the connection pending, then we freed it already in * dns_cancel_pending_resolve(). If we marked it for close, it'll * get freed from the main loop. Otherwise, can free it now. */ @@ -670,48 +794,50 @@ dns_resolve(edge_connection_t *exitconn) * Set *<b>made_connection_pending_out</b> to true if we have placed * <b>exitconn</b> on the list of pending connections for some resolve; set it * to false otherwise. + * + * Set *<b>resolve_out</b> to a cached resolve, if we found one. */ static int dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, or_circuit_t *oncirc, char **hostname_out, - int *made_connection_pending_out) + int *made_connection_pending_out, + cached_resolve_t **resolve_out) { cached_resolve_t *resolve; cached_resolve_t search; pending_connection_t *pending_connection; - const routerinfo_t *me; + int is_reverse = 0; tor_addr_t addr; time_t now = time(NULL); - uint8_t is_reverse = 0; int r; assert_connection_ok(TO_CONN(exitconn), 0); - tor_assert(!SOCKET_OK(exitconn->_base.s)); + tor_assert(!SOCKET_OK(exitconn->base_.s)); assert_cache_ok(); tor_assert(oncirc); *made_connection_pending_out = 0; - /* first check if exitconn->_base.address is an IP. If so, we already + /* first check if exitconn->base_.address is an IP. If so, we already * know the answer. */ - if (tor_addr_parse(&addr, exitconn->_base.address) >= 0) { - if (tor_addr_family(&addr) == AF_INET) { - tor_addr_copy(&exitconn->_base.addr, &addr); + if (tor_addr_parse(&addr, exitconn->base_.address) >= 0) { + if (tor_addr_family(&addr) == AF_INET || + tor_addr_family(&addr) == AF_INET6) { + tor_addr_copy(&exitconn->base_.addr, &addr); exitconn->address_ttl = DEFAULT_DNS_TTL; return 1; } else { - /* XXXX IPv6 */ + /* XXXX unspec? Bogus? */ return -1; } } /* If we're a non-exit, don't even do DNS lookups. */ - if (!(me = router_get_my_routerinfo()) || - policy_is_reject_star(me->exit_policy)) { + if (router_my_exit_policy_is_reject_star()) return -1; - } - if (address_is_invalid_destination(exitconn->_base.address, 0)) { - log(LOG_PROTOCOL_WARN, LD_EXIT, + + if (address_is_invalid_destination(exitconn->base_.address, 0)) { + tor_log(LOG_PROTOCOL_WARN, LD_EXIT, "Rejecting invalid destination address %s", - escaped_safe_str(exitconn->_base.address)); + escaped_safe_str(exitconn->base_.address)); return -1; } @@ -719,14 +845,14 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, * resolves in the hash table. */ purge_expired_resolves(now); - /* lower-case exitconn->_base.address, so it's in canonical form */ - tor_strlower(exitconn->_base.address); + /* lower-case exitconn->base_.address, so it's in canonical form */ + tor_strlower(exitconn->base_.address); /* Check whether this is a reverse lookup. If it's malformed, or it's a * .in-addr.arpa address but this isn't a resolve request, kill the * connection. */ - if ((r = tor_addr_parse_PTR_name(&addr, exitconn->_base.address, + if ((r = tor_addr_parse_PTR_name(&addr, exitconn->base_.address, AF_UNSPEC, 0)) != 0) { if (r == 1) { is_reverse = 1; @@ -737,21 +863,22 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, if (!is_reverse || !is_resolve) { if (!is_reverse) log_info(LD_EXIT, "Bad .in-addr.arpa address \"%s\"; sending error.", - escaped_safe_str(exitconn->_base.address)); + escaped_safe_str(exitconn->base_.address)); else if (!is_resolve) log_info(LD_EXIT, "Attempt to connect to a .in-addr.arpa address \"%s\"; " "sending error.", - escaped_safe_str(exitconn->_base.address)); + escaped_safe_str(exitconn->base_.address)); return -1; } //log_notice(LD_EXIT, "Looks like an address %s", - //exitconn->_base.address); + //exitconn->base_.address); } + exitconn->is_reverse_dns_lookup = is_reverse; /* now check the hash table to see if 'address' is already there. */ - strlcpy(search.address, exitconn->_base.address, sizeof(search.address)); + strlcpy(search.address, exitconn->base_.address, sizeof(search.address)); resolve = HT_FIND(cache_map, &cache_root, &search); if (resolve && resolve->expire > now) { /* already there */ switch (resolve->state) { @@ -763,27 +890,19 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, pending_connection->next = resolve->pending_connections; resolve->pending_connections = pending_connection; *made_connection_pending_out = 1; - log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS " - "resolve of %s", exitconn->_base.s, - escaped_safe_str(exitconn->_base.address)); + log_debug(LD_EXIT,"Connection (fd "TOR_SOCKET_T_FORMAT") waiting " + "for pending DNS resolve of %s", exitconn->base_.s, + escaped_safe_str(exitconn->base_.address)); return 0; - case CACHE_STATE_CACHED_VALID: - log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s", - exitconn->_base.s, + case CACHE_STATE_CACHED: + log_debug(LD_EXIT,"Connection (fd "TOR_SOCKET_T_FORMAT") found " + "cached answer for %s", + exitconn->base_.s, escaped_safe_str(resolve->address)); - exitconn->address_ttl = resolve->ttl; - if (resolve->is_reverse) { - tor_assert(is_resolve); - *hostname_out = tor_strdup(resolve->result.hostname); - } else { - tor_addr_from_ipv4h(&exitconn->_base.addr, resolve->result.a.addr); - } - return 1; - case CACHE_STATE_CACHED_FAILED: - log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s", - exitconn->_base.s, - escaped_safe_str(exitconn->_base.address)); - return -1; + + *resolve_out = resolve; + + return set_exitconn_info_from_resolve(exitconn, resolve, hostname_out); case CACHE_STATE_DONE: log_err(LD_BUG, "Found a 'DONE' dns resolve still in the cache."); tor_fragile_assert(); @@ -796,8 +915,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, 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)); + strlcpy(resolve->address, exitconn->base_.address, sizeof(resolve->address)); /* add this connection to the pending list */ pending_connection = tor_malloc_zero(sizeof(pending_connection_t)); @@ -810,10 +928,115 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, set_expiry(resolve, now + RESOLVE_MAX_TIMEOUT); log_debug(LD_EXIT,"Launching %s.", - escaped_safe_str(exitconn->_base.address)); + escaped_safe_str(exitconn->base_.address)); assert_cache_ok(); - return launch_resolve(exitconn); + return launch_resolve(resolve); +} + +/** Given an exit connection <b>exitconn</b>, and a cached_resolve_t + * <b>resolve</b> whose DNS lookups have all succeeded or failed, update the + * appropriate fields (address_ttl and addr) of <b>exitconn</b>. + * + * If this is a reverse lookup, set *<b>hostname_out</b> to a newly allocated + * copy of the name resulting hostname. + * + * Return -2 on a transient error, -1 on a permenent error, and 1 on + * a successful lookup. + */ +static int +set_exitconn_info_from_resolve(edge_connection_t *exitconn, + const cached_resolve_t *resolve, + char **hostname_out) +{ + int ipv4_ok, ipv6_ok, answer_with_ipv4, r; + uint32_t begincell_flags; + const int is_resolve = exitconn->base_.purpose == EXIT_PURPOSE_RESOLVE; + tor_assert(exitconn); + tor_assert(resolve); + + if (exitconn->is_reverse_dns_lookup) { + exitconn->address_ttl = resolve->ttl_hostname; + if (resolve->res_status_hostname == RES_STATUS_DONE_OK) { + *hostname_out = tor_strdup(resolve->result_ptr.hostname); + return 1; + } else { + return -1; + } + } + + /* If we're here then the connection wants one or either of ipv4, ipv6, and + * we can give it one or both. */ + if (is_resolve) { + begincell_flags = BEGIN_FLAG_IPV6_OK; + } else { + begincell_flags = exitconn->begincell_flags; + } + + ipv4_ok = (resolve->res_status_ipv4 == RES_STATUS_DONE_OK) && + ! (begincell_flags & BEGIN_FLAG_IPV4_NOT_OK); + ipv6_ok = (resolve->res_status_ipv6 == RES_STATUS_DONE_OK) && + (begincell_flags & BEGIN_FLAG_IPV6_OK) && + get_options()->IPv6Exit; + + /* Now decide which one to actually give. */ + if (ipv4_ok && ipv6_ok && is_resolve) { + answer_with_ipv4 = 1; + } else if (ipv4_ok && ipv6_ok) { + /* If we have both, see if our exit policy has an opinion. */ + const uint16_t port = exitconn->base_.port; + int ipv4_allowed, ipv6_allowed; + tor_addr_t a4, a6; + tor_addr_from_ipv4h(&a4, resolve->result_ipv4.addr_ipv4); + tor_addr_from_in6(&a6, &resolve->result_ipv6.addr_ipv6); + ipv4_allowed = !router_compare_to_my_exit_policy(&a4, port); + ipv6_allowed = !router_compare_to_my_exit_policy(&a6, port); + if (ipv4_allowed && !ipv6_allowed) { + answer_with_ipv4 = 1; + } else if (ipv6_allowed && !ipv4_allowed) { + answer_with_ipv4 = 0; + } else { + /* Our exit policy would permit both. Answer with whichever the user + * prefers */ + answer_with_ipv4 = !(begincell_flags & + BEGIN_FLAG_IPV6_PREFERRED); + } + } else { + /* Otherwise if one is okay, send it back. */ + if (ipv4_ok) { + answer_with_ipv4 = 1; + } else if (ipv6_ok) { + answer_with_ipv4 = 0; + } else { + /* Neither one was okay. Choose based on user preference. */ + answer_with_ipv4 = !(begincell_flags & + BEGIN_FLAG_IPV6_PREFERRED); + } + } + + /* Finally, we write the answer back. */ + r = 1; + if (answer_with_ipv4) { + if (resolve->res_status_ipv4 == RES_STATUS_DONE_OK) { + tor_addr_from_ipv4h(&exitconn->base_.addr, + resolve->result_ipv4.addr_ipv4); + } else { + r = evdns_err_is_transient(resolve->result_ipv4.err_ipv4) ? -2 : -1; + } + + exitconn->address_ttl = resolve->ttl_ipv4; + } else { + if (resolve->res_status_ipv6 == RES_STATUS_DONE_OK) { + tor_addr_from_in6(&exitconn->base_.addr, + &resolve->result_ipv6.addr_ipv6); + } else { + r = evdns_err_is_transient(resolve->result_ipv6.err_ipv6) ? -2 : -1; + } + + exitconn->address_ttl = resolve->ttl_ipv6; + } + + return r; } /** Log an error and abort if conn is waiting for a DNS resolve. @@ -826,7 +1049,7 @@ assert_connection_edge_not_dns_pending(edge_connection_t *conn) #if 1 cached_resolve_t *resolve; - strlcpy(search.address, conn->_base.address, sizeof(search.address)); + strlcpy(search.address, conn->base_.address, sizeof(search.address)); resolve = HT_FIND(cache_map, &cache_root, &search); if (!resolve) return; @@ -856,7 +1079,7 @@ assert_all_pending_dns_resolves_ok(void) pend; pend = pend->next) { assert_connection_ok(TO_CONN(pend->conn), 0); - tor_assert(!SOCKET_OK(pend->conn->_base.s)); + tor_assert(!SOCKET_OK(pend->conn->base_.s)); tor_assert(!connection_in_array(TO_CONN(pend->conn))); } } @@ -871,15 +1094,15 @@ connection_dns_remove(edge_connection_t *conn) cached_resolve_t search; cached_resolve_t *resolve; - tor_assert(conn->_base.type == CONN_TYPE_EXIT); - tor_assert(conn->_base.state == EXIT_CONN_STATE_RESOLVING); + tor_assert(conn->base_.type == CONN_TYPE_EXIT); + tor_assert(conn->base_.state == EXIT_CONN_STATE_RESOLVING); - strlcpy(search.address, conn->_base.address, sizeof(search.address)); + strlcpy(search.address, conn->base_.address, sizeof(search.address)); resolve = HT_FIND(cache_map, &cache_root, &search); if (!resolve) { log_notice(LD_BUG, "Address %s is not pending. Dropping.", - escaped_safe_str(conn->_base.address)); + escaped_safe_str(conn->base_.address)); return; } @@ -891,10 +1114,10 @@ connection_dns_remove(edge_connection_t *conn) if (pend->conn == conn) { resolve->pending_connections = pend->next; 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)); + log_debug(LD_EXIT, "First connection (fd "TOR_SOCKET_T_FORMAT") no " + "longer waiting for resolve of %s", + conn->base_.s, + escaped_safe_str(conn->base_.address)); return; } else { for ( ; pend->next; pend = pend->next) { @@ -903,8 +1126,9 @@ connection_dns_remove(edge_connection_t *conn) pend->next = victim->next; tor_free(victim); log_debug(LD_EXIT, - "Connection (fd %d) no longer waiting for resolve of %s", - conn->_base.s, escaped_safe_str(conn->_base.address)); + "Connection (fd "TOR_SOCKET_T_FORMAT") no longer waiting " + "for resolve of %s", + conn->base_.s, escaped_safe_str(conn->base_.address)); return; /* more are pending */ } } @@ -959,17 +1183,17 @@ dns_cancel_pending_resolve(const char *address) escaped_safe_str(address)); while (resolve->pending_connections) { pend = resolve->pending_connections; - pend->conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; + pend->conn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; pendconn = pend->conn; assert_connection_ok(TO_CONN(pendconn), 0); - tor_assert(!SOCKET_OK(pendconn->_base.s)); - if (!pendconn->_base.marked_for_close) { + tor_assert(!SOCKET_OK(pendconn->base_.s)); + if (!pendconn->base_.marked_for_close) { connection_edge_end(pendconn, END_STREAM_REASON_RESOLVEFAILED); } circ = circuit_get_by_edge_conn(pendconn); if (circ) circuit_detach_stream(circ, pendconn); - if (!pendconn->_base.marked_for_close) + if (!pendconn->base_.marked_for_close) connection_free(TO_CONN(pendconn)); resolve->pending_connections = pend->next; tor_free(pend); @@ -987,47 +1211,6 @@ dns_cancel_pending_resolve(const char *address) resolve->state = CACHE_STATE_DONE; } -/** Helper: adds an entry to the DNS cache mapping <b>address</b> to the ipv4 - * address <b>addr</b> (if is_reverse is 0) or the hostname <b>hostname</b> (if - * is_reverse is 1). <b>ttl</b> is a cache ttl; <b>outcome</b> is one of - * DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}. - **/ -static void -add_answer_to_cache(const char *address, uint8_t is_reverse, uint32_t addr, - const char *hostname, char outcome, uint32_t ttl) -{ - cached_resolve_t *resolve; - if (outcome == DNS_RESOLVE_FAILED_TRANSIENT) - return; - - //log_notice(LD_EXIT, "Adding to cache: %s -> %s (%lx, %s), %d", - // address, is_reverse?"(reverse)":"", (unsigned long)addr, - // hostname?hostname:"NULL",(int)outcome); - - resolve = tor_malloc_zero(sizeof(cached_resolve_t)); - resolve->magic = CACHED_RESOLVE_MAGIC; - resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ? - CACHE_STATE_CACHED_VALID : CACHE_STATE_CACHED_FAILED; - strlcpy(resolve->address, address, sizeof(resolve->address)); - resolve->is_reverse = is_reverse; - if (is_reverse) { - if (outcome == DNS_RESOLVE_SUCCEEDED) { - tor_assert(hostname); - resolve->result.hostname = tor_strdup(hostname); - } else { - tor_assert(! hostname); - resolve->result.hostname = NULL; - } - } else { - tor_assert(!hostname); - resolve->result.a.addr = addr; - } - resolve->ttl = ttl; - assert_resolve_ok(resolve); - HT_INSERT(cache_map, &cache_root, resolve); - set_expiry(resolve, time(NULL) + dns_get_expiry_ttl(ttl)); -} - /** Return true iff <b>address</b> is one of the addresses we use to verify * that well-known sites aren't being hijacked by our DNS servers. */ static INLINE int @@ -1035,25 +1218,26 @@ is_test_address(const char *address) { const or_options_t *options = get_options(); return options->ServerDNSTestAddresses && - smartlist_string_isin_case(options->ServerDNSTestAddresses, address); + smartlist_contains_string_case(options->ServerDNSTestAddresses, address); } -/** Called on the OR side when a DNS worker or the eventdns library tells us - * the outcome of a DNS resolve: tell all pending connections about the result - * of the lookup, and cache the value. (<b>address</b> is a NUL-terminated - * string containing the address to look up; <b>addr</b> is an IPv4 address in - * host order; <b>outcome</b> is one of - * DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}. +/** Called on the OR side when the eventdns library tells us the outcome of a + * single DNS resolve: remember the answer, and tell all pending connections + * about the result of the lookup if the lookup is now done. (<b>address</b> + * is a NUL-terminated string containing the address to look up; + * <b>query_type</b> is one of DNS_{IPv4_A,IPv6_AAAA,PTR}; <b>dns_answer</b> + * is DNS_OK or one of DNS_ERR_*, <b>addr</b> is an IPv4 or IPv6 address if we + * got one; <b>hostname</b> is a hostname fora PTR request if we got one, and + * <b>ttl</b> is the time-to-live of this answer, in seconds.) */ static void -dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, - const char *hostname, char outcome, uint32_t ttl) +dns_found_answer(const char *address, uint8_t query_type, + int dns_answer, + const tor_addr_t *addr, + const char *hostname, uint32_t ttl) { - pending_connection_t *pend; cached_resolve_t search; - cached_resolve_t *resolve, *removed; - edge_connection_t *pendconn; - circuit_t *circ; + cached_resolve_t *resolve; assert_cache_ok(); @@ -1063,9 +1247,8 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, if (!resolve) { int is_test_addr = is_test_address(address); if (!is_test_addr) - log_info(LD_EXIT,"Resolved unasked address %s; caching anyway.", + log_info(LD_EXIT,"Resolved unasked address %s; ignoring.", escaped_safe_str(address)); - add_answer_to_cache(address, is_reverse, addr, hostname, outcome, ttl); return; } assert_resolve_ok(resolve); @@ -1081,46 +1264,66 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, tor_assert(resolve->pending_connections == NULL); return; } - /* Removed this assertion: in fact, we'll sometimes get a double answer - * to the same question. This can happen when we ask one worker to resolve - * X.Y.Z., then we cancel the request, and then we ask another worker to - * resolve X.Y.Z. */ - /* tor_assert(resolve->state == CACHE_STATE_PENDING); */ + + cached_resolve_add_answer(resolve, query_type, dns_answer, + addr, hostname, ttl); + + if (cached_resolve_have_all_answers(resolve)) { + inform_pending_connections(resolve); + + make_pending_resolve_cached(resolve); + } +} + +/** Given a pending cached_resolve_t that we just finished resolving, + * inform every connection that was waiting for the outcome of that + * resolution. */ +static void +inform_pending_connections(cached_resolve_t *resolve) +{ + pending_connection_t *pend; + edge_connection_t *pendconn; + int r; while (resolve->pending_connections) { + char *hostname = NULL; pend = resolve->pending_connections; pendconn = pend->conn; /* don't pass complex things to the connection_mark_for_close macro */ assert_connection_ok(TO_CONN(pendconn),time(NULL)); - if (pendconn->_base.marked_for_close) { + + if (pendconn->base_.marked_for_close) { /* prevent double-remove. */ - pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; + pendconn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; resolve->pending_connections = pend->next; tor_free(pend); continue; } - tor_addr_from_ipv4h(&pendconn->_base.addr, addr); - pendconn->address_ttl = ttl; - if (outcome != DNS_RESOLVE_SUCCEEDED) { + r = set_exitconn_info_from_resolve(pendconn, + resolve, + &hostname); + + if (r < 0) { /* prevent double-remove. */ - pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; - if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) { + pendconn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; + if (pendconn->base_.purpose == EXIT_PURPOSE_CONNECT) { connection_edge_end(pendconn, END_STREAM_REASON_RESOLVEFAILED); /* This detach must happen after we send the end cell. */ circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); } else { - send_resolved_cell(pendconn, outcome == DNS_RESOLVE_FAILED_PERMANENT ? - RESOLVED_TYPE_ERROR : RESOLVED_TYPE_ERROR_TRANSIENT); + send_resolved_cell(pendconn, r == -1 ? + RESOLVED_TYPE_ERROR : RESOLVED_TYPE_ERROR_TRANSIENT, + NULL); /* This detach must happen after we send the resolved cell. */ circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); } connection_free(TO_CONN(pendconn)); } else { - if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) { - tor_assert(!is_reverse); + circuit_t *circ; + if (pendconn->base_.purpose == EXIT_PURPOSE_CONNECT) { /* prevent double-remove. */ - pend->conn->_base.state = EXIT_CONN_STATE_CONNECTING; + pend->conn->base_.state = EXIT_CONN_STATE_CONNECTING; circ = circuit_get_by_edge_conn(pend->conn); tor_assert(circ); @@ -1136,11 +1339,11 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, } else { /* prevent double-remove. This isn't really an accurate state, * but it does the right thing. */ - pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; - if (is_reverse) + pendconn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; + if (pendconn->is_reverse_dns_lookup) send_resolved_hostname_cell(pendconn, hostname); else - send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4); + send_resolved_cell(pendconn, RESOLVED_TYPE_AUTO, resolve); circ = circuit_get_by_edge_conn(pendconn); tor_assert(circ); circuit_detach_stream(circ, pendconn); @@ -1149,10 +1352,23 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, } resolve->pending_connections = pend->next; tor_free(pend); + tor_free(hostname); } +} + +/** Remove a pending cached_resolve_t from the hashtable, and add a + * corresponding cached cached_resolve_t. + * + * This function is only necessary because of the perversity of our + * cache timeout code; see inline comment for ideas on eliminating it. + **/ +static void +make_pending_resolve_cached(cached_resolve_t *resolve) +{ + cached_resolve_t *removed; resolve->state = CACHE_STATE_DONE; - removed = HT_REMOVE(cache_map, &cache_root, &search); + removed = HT_REMOVE(cache_map, &cache_root, resolve); if (removed != resolve) { log_err(LD_BUG, "The pending resolve we found wasn't removable from" " the cache. Tried to purge %s (%p); instead got %s (%p).", @@ -1161,8 +1377,42 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, } assert_resolve_ok(resolve); assert_cache_ok(); + /* The resolve will eventually just hit the time-out in the expiry queue and + * expire. See fd0bafb0dedc7e2 for a brief explanation of how this got that + * way. XXXXX we could do better!*/ + + { + cached_resolve_t *new_resolve = tor_memdup(resolve, + sizeof(cached_resolve_t)); + uint32_t ttl = UINT32_MAX; + new_resolve->expire = 0; /* So that set_expiry won't croak. */ + if (resolve->res_status_hostname == RES_STATUS_DONE_OK) + new_resolve->result_ptr.hostname = + tor_strdup(resolve->result_ptr.hostname); + + new_resolve->state = CACHE_STATE_CACHED; + + assert_resolve_ok(new_resolve); + HT_INSERT(cache_map, &cache_root, new_resolve); + + if ((resolve->res_status_ipv4 == RES_STATUS_DONE_OK || + resolve->res_status_ipv4 == RES_STATUS_DONE_ERR) && + resolve->ttl_ipv4 < ttl) + ttl = resolve->ttl_ipv4; + + if ((resolve->res_status_ipv6 == RES_STATUS_DONE_OK || + resolve->res_status_ipv6 == RES_STATUS_DONE_ERR) && + resolve->ttl_ipv6 < ttl) + ttl = resolve->ttl_ipv6; + + if ((resolve->res_status_hostname == RES_STATUS_DONE_OK || + resolve->res_status_hostname == RES_STATUS_DONE_ERR) && + resolve->ttl_hostname < ttl) + ttl = resolve->ttl_hostname; + + set_expiry(new_resolve, time(NULL) + dns_get_expiry_ttl(ttl)); + } - add_answer_to_cache(address, is_reverse, addr, hostname, outcome, ttl); assert_cache_ok(); } @@ -1210,24 +1460,18 @@ configure_nameservers(int force) } #ifdef HAVE_EVDNS_SET_DEFAULT_OUTGOING_BIND_ADDRESS - if (options->OutboundBindAddress) { - tor_addr_t addr; - if (tor_addr_parse(&addr, options->OutboundBindAddress) < 0) { - log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.", - options->OutboundBindAddress); + if (! tor_addr_is_null(&options->OutboundBindAddressIPv4_)) { + int socklen; + struct sockaddr_storage ss; + socklen = tor_addr_to_sockaddr(&options->OutboundBindAddressIPv4_, 0, + (struct sockaddr *)&ss, sizeof(ss)); + if (socklen <= 0) { + log_warn(LD_BUG, "Couldn't convert outbound bind address to sockaddr." + " Ignoring."); } else { - int socklen; - struct sockaddr_storage ss; - socklen = tor_addr_to_sockaddr(&addr, 0, - (struct sockaddr *)&ss, sizeof(ss)); - if (socklen <= 0) { - log_warn(LD_BUG, "Couldn't convert outbound bind address to sockaddr." - " Ignoring."); - } else { - evdns_base_set_default_outgoing_bind_address(the_evdns_base, - (struct sockaddr *)&ss, - socklen); - } + evdns_base_set_default_outgoing_bind_address(the_evdns_base, + (struct sockaddr *)&ss, + socklen); } } #endif @@ -1331,23 +1575,40 @@ static void evdns_callback(int result, char type, int count, int ttl, void *addresses, void *arg) { - char *string_address = arg; - uint8_t is_reverse = 0; - int status = DNS_RESOLVE_FAILED_PERMANENT; - uint32_t addr = 0; + char *arg_ = arg; + uint8_t orig_query_type = arg_[0]; + char *string_address = arg_ + 1; + tor_addr_t addr; const char *hostname = NULL; int was_wildcarded = 0; + tor_addr_make_unspec(&addr); + + /* Keep track of whether IPv6 is working */ + if (type == DNS_IPv6_AAAA) { + if (result == DNS_ERR_TIMEOUT) { + ++n_ipv6_timeouts; + } + + if (n_ipv6_timeouts > 10 && + n_ipv6_timeouts > n_ipv6_requests_made / 2) { + if (! dns_is_broken_for_ipv6) { + log_notice(LD_EXIT, "More than half of our IPv6 requests seem to " + "have timed out. I'm going to assume I can't get AAAA " + "responses."); + dns_is_broken_for_ipv6 = 1; + } + } + } + if (result == DNS_ERR_NONE) { if (type == DNS_IPv4_A && count) { char answer_buf[INET_NTOA_BUF_LEN+1]; - struct in_addr in; char *escaped_address; uint32_t *addrs = addresses; - in.s_addr = addrs[0]; - addr = ntohl(addrs[0]); - status = DNS_RESOLVE_SUCCEEDED; - tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf)); + tor_addr_from_ipv4n(&addr, addrs[0]); + + tor_addr_to_str(answer_buf, &addr, sizeof(answer_buf), 0); escaped_address = esc_for_log(string_address); if (answer_is_wildcarded(answer_buf)) { @@ -1356,8 +1617,30 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, safe_str(escaped_address), escaped_safe_str(answer_buf)); was_wildcarded = 1; - addr = 0; - status = DNS_RESOLVE_FAILED_PERMANENT; + tor_addr_make_unspec(&addr); + result = DNS_ERR_NOTEXIST; + } else { + log_debug(LD_EXIT, "eventdns said that %s resolves to %s", + safe_str(escaped_address), + escaped_safe_str(answer_buf)); + } + tor_free(escaped_address); + } else if (type == DNS_IPv6_AAAA && count) { + char answer_buf[TOR_ADDR_BUF_LEN]; + char *escaped_address; + struct in6_addr *addrs = addresses; + tor_addr_from_in6(&addr, &addrs[0]); + tor_inet_ntop(AF_INET6, &addrs[0], answer_buf, sizeof(answer_buf)); + escaped_address = esc_for_log(string_address); + + if (answer_is_wildcarded(answer_buf)) { + log_debug(LD_EXIT, "eventdns said that %s resolves to ISP-hijacked " + "address %s; treating as a failure.", + safe_str(escaped_address), + escaped_safe_str(answer_buf)); + was_wildcarded = 1; + tor_addr_make_unspec(&addr); + result = DNS_ERR_NOTEXIST; } else { log_debug(LD_EXIT, "eventdns said that %s resolves to %s", safe_str(escaped_address), @@ -1366,9 +1649,7 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, tor_free(escaped_address); } else if (type == DNS_PTR && count) { char *escaped_address; - is_reverse = 1; hostname = ((char**)addresses)[0]; - status = DNS_RESOLVE_SUCCEEDED; escaped_address = esc_for_log(string_address); log_debug(LD_EXIT, "eventdns said that %s resolves to %s", safe_str(escaped_address), @@ -1381,9 +1662,6 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, log_warn(LD_BUG, "eventdns returned no addresses or error for %s!", escaped_safe_str(string_address)); } - } else { - if (evdns_err_is_transient(result)) - status = DNS_RESOLVE_FAILED_TRANSIENT; } if (was_wildcarded) { if (is_test_address(string_address)) { @@ -1392,23 +1670,78 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, add_wildcarded_test_address(string_address); } } + + if (orig_query_type && type && orig_query_type != type) { + log_warn(LD_BUG, "Weird; orig_query_type == %d but type == %d", + (int)orig_query_type, (int)type); + } if (result != DNS_ERR_SHUTDOWN) - dns_found_answer(string_address, is_reverse, addr, hostname, status, ttl); - tor_free(string_address); + dns_found_answer(string_address, orig_query_type, + result, &addr, hostname, ttl); + + tor_free(arg_); +} + +/** Start a single DNS resolve for <b>address</b> (if <b>query_type</b> is + * DNS_IPv4_A or DNS_IPv6_AAAA) <b>ptr_address</b> (if <b>query_type</b> is + * DNS_PTR). Return 0 if we launched the request, -1 otherwise. */ +static int +launch_one_resolve(const char *address, uint8_t query_type, + const tor_addr_t *ptr_address) +{ + const int options = get_options()->ServerDNSSearchDomains ? 0 + : DNS_QUERY_NO_SEARCH; + const size_t addr_len = strlen(address); + struct evdns_request *req = 0; + char *addr = tor_malloc(addr_len + 2); + addr[0] = (char) query_type; + memcpy(addr+1, address, addr_len + 1); + + switch (query_type) { + case DNS_IPv4_A: + req = evdns_base_resolve_ipv4(the_evdns_base, + address, options, evdns_callback, addr); + break; + case DNS_IPv6_AAAA: + req = evdns_base_resolve_ipv6(the_evdns_base, + address, options, evdns_callback, addr); + ++n_ipv6_requests_made; + break; + case DNS_PTR: + if (tor_addr_family(ptr_address) == AF_INET) + req = evdns_base_resolve_reverse(the_evdns_base, + tor_addr_to_in(ptr_address), + DNS_QUERY_NO_SEARCH, + evdns_callback, addr); + else if (tor_addr_family(ptr_address) == AF_INET6) + req = evdns_base_resolve_reverse_ipv6(the_evdns_base, + tor_addr_to_in6(ptr_address), + DNS_QUERY_NO_SEARCH, + evdns_callback, addr); + else + log_warn(LD_BUG, "Called with PTR query and unexpected address family"); + break; + default: + log_warn(LD_BUG, "Called with unexpectd query type %d", (int)query_type); + break; + } + + if (req) { + return 0; + } else { + tor_free(addr); + return -1; + } } /** For eventdns: start resolving as necessary to find the target for * <b>exitconn</b>. Returns -1 on error, -2 on transient error, * 0 on "resolve launched." */ static int -launch_resolve(edge_connection_t *exitconn) +launch_resolve(cached_resolve_t *resolve) { - char *addr; - struct evdns_request *req = NULL; tor_addr_t a; int r; - int options = get_options()->ServerDNSSearchDomains ? 0 - : DNS_QUERY_NO_SEARCH; if (get_options()->DisableNetwork) return -1; @@ -1422,40 +1755,45 @@ launch_resolve(edge_connection_t *exitconn) } } - addr = tor_strdup(exitconn->_base.address); - r = tor_addr_parse_PTR_name( - &a, exitconn->_base.address, AF_UNSPEC, 0); + &a, resolve->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)); - req = evdns_base_resolve_ipv4(the_evdns_base, - exitconn->_base.address, options, - evdns_callback, addr); + escaped_safe_str(resolve->address)); + resolve->res_status_ipv4 = RES_STATUS_INFLIGHT; + if (get_options()->IPv6Exit) + resolve->res_status_ipv6 = RES_STATUS_INFLIGHT; + + if (launch_one_resolve(resolve->address, DNS_IPv4_A, NULL) < 0) { + resolve->res_status_ipv4 = 0; + r = -1; + } + + if (r==0 && get_options()->IPv6Exit) { + /* We ask for an IPv6 address for *everything*. */ + if (launch_one_resolve(resolve->address, DNS_IPv6_AAAA, NULL) < 0) { + resolve->res_status_ipv6 = 0; + r = -1; + } + } } else if (r == 1) { + r = 0; log_info(LD_EXIT, "Launching eventdns reverse request for %s", - escaped_safe_str(exitconn->_base.address)); - if (tor_addr_family(&a) == AF_INET) - req = evdns_base_resolve_reverse(the_evdns_base, - tor_addr_to_in(&a), DNS_QUERY_NO_SEARCH, - evdns_callback, addr); - else - req = evdns_base_resolve_reverse_ipv6(the_evdns_base, - tor_addr_to_in6(&a), DNS_QUERY_NO_SEARCH, - evdns_callback, addr); + escaped_safe_str(resolve->address)); + resolve->res_status_hostname = RES_STATUS_INFLIGHT; + if (launch_one_resolve(resolve->address, DNS_PTR, &a) < 0) { + resolve->res_status_hostname = 0; + r = -1; + } } else if (r == -1) { log_warn(LD_BUG, "Somehow a malformed in-addr.arpa address reached here."); } - r = 0; - if (!req) { + if (r < 0) { log_fn(LOG_PROTOCOL_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. */ + escaped_safe_str(resolve->address)); } return r; } @@ -1488,8 +1826,8 @@ static int dns_wildcarded_test_address_notice_given = 0; /** True iff all addresses seem to be getting wildcarded. */ static int dns_is_completely_invalid = 0; -/** Called when we see <b>id</b> (a dotted quad) in response to a request for - * a hopefully bogus address. */ +/** Called when we see <b>id</b> (a dotted quad or IPv6 address) in response + * to a request for a hopefully bogus address. */ static void wildcard_increment_answer(const char *id) { @@ -1506,8 +1844,8 @@ wildcard_increment_answer(const char *id) if (*ip > 5 && n_wildcard_requests > 10) { if (!dns_wildcard_list) dns_wildcard_list = smartlist_new(); - if (!smartlist_string_isin(dns_wildcard_list, id)) { - log(dns_wildcard_notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, + if (!smartlist_contains_string(dns_wildcard_list, id)) { + tor_log(dns_wildcard_notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, "Your DNS provider has given \"%s\" as an answer for %d different " "invalid addresses. Apparently they are hijacking DNS failures. " "I'll try to correct for this by treating future occurrences of " @@ -1529,7 +1867,8 @@ add_wildcarded_test_address(const char *address) if (!dns_wildcarded_test_address_list) dns_wildcarded_test_address_list = smartlist_new(); - if (smartlist_string_isin_case(dns_wildcarded_test_address_list, address)) + if (smartlist_contains_string_case(dns_wildcarded_test_address_list, + address)) return; n_test_addrs = get_options()->ServerDNSTestAddresses ? @@ -1538,7 +1877,7 @@ add_wildcarded_test_address(const char *address) smartlist_add(dns_wildcarded_test_address_list, tor_strdup(address)); n = smartlist_len(dns_wildcarded_test_address_list); if (n > n_test_addrs/2) { - log(dns_wildcarded_test_address_notice_given ? LOG_INFO : LOG_NOTICE, + tor_log(dns_wildcarded_test_address_notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, "Your DNS provider tried to redirect \"%s\" to a junk " "address. It has done this with %d test addresses so far. I'm " "going to stop being an exit node for now, since our DNS seems so " @@ -1561,18 +1900,28 @@ evdns_wildcard_check_callback(int result, char type, int count, int ttl, { (void)ttl; ++n_wildcard_requests; - if (result == DNS_ERR_NONE && type == DNS_IPv4_A && count) { - uint32_t *addrs = addresses; - int i; + if (result == DNS_ERR_NONE && count) { char *string_address = arg; - for (i = 0; i < count; ++i) { - char answer_buf[INET_NTOA_BUF_LEN+1]; - struct in_addr in; - in.s_addr = addrs[i]; - tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf)); - wildcard_increment_answer(answer_buf); + int i; + if (type == DNS_IPv4_A) { + const uint32_t *addrs = addresses; + for (i = 0; i < count; ++i) { + char answer_buf[INET_NTOA_BUF_LEN+1]; + struct in_addr in; + in.s_addr = addrs[i]; + tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf)); + wildcard_increment_answer(answer_buf); + } + } else if (type == DNS_IPv6_AAAA) { + const struct in6_addr *addrs = addresses; + for (i = 0; i < count; ++i) { + char answer_buf[TOR_ADDR_BUF_LEN+1]; + tor_inet_ntop(AF_INET6, &addrs[i], answer_buf, sizeof(answer_buf)); + wildcard_increment_answer(answer_buf); + } } - log(dns_wildcard_one_notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, + + tor_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 " @@ -1588,7 +1937,8 @@ evdns_wildcard_check_callback(int result, char type, int count, int ttl, * <b>min_len</b> and <b>max_len</b> random (plausible) characters followed by * <b>suffix</b> */ static void -launch_wildcard_check(int min_len, int max_len, const char *suffix) +launch_wildcard_check(int min_len, int max_len, int is_ipv6, + const char *suffix) { char *addr; struct evdns_request *req; @@ -1598,7 +1948,15 @@ launch_wildcard_check(int min_len, int max_len, const char *suffix) "domains with request for bogus hostname \"%s\"", addr); tor_assert(the_evdns_base); - req = evdns_base_resolve_ipv4( + if (is_ipv6) + req = evdns_base_resolve_ipv6( + 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); + else + req = evdns_base_resolve_ipv4( the_evdns_base, /* This "addr" tells us which address to resolve */ addr, @@ -1613,10 +1971,9 @@ launch_wildcard_check(int min_len, int max_len, const char *suffix) /** Launch attempts to resolve a bunch of known-good addresses (configured in * ServerDNSTestAddresses). [Callback for a libevent timer] */ static void -launch_test_addresses(int fd, short event, void *args) +launch_test_addresses(evutil_socket_t fd, short event, void *args) { const or_options_t *options = get_options(); - struct evdns_request *req; (void)fd; (void)event; (void)args; @@ -1629,21 +1986,22 @@ launch_test_addresses(int fd, short event, void *args) /* This situation is worse than the failure-hijacking situation. When this * happens, we're no good for DNS requests at all, and we shouldn't really * be an exit server.*/ - if (!options->ServerDNSTestAddresses) - return; - 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 (options->ServerDNSTestAddresses) { - if (!req) { - log_info(LD_EXIT, "eventdns rejected test address %s", - escaped_safe_str(address)); - tor_free(a); - } - } SMARTLIST_FOREACH_END(address); + tor_assert(the_evdns_base); + SMARTLIST_FOREACH_BEGIN(options->ServerDNSTestAddresses, + const char *, address) { + if (launch_one_resolve(address, DNS_IPv4_A, NULL) < 0) { + log_info(LD_EXIT, "eventdns rejected test address %s", + escaped_safe_str(address)); + } + + if (launch_one_resolve(address, DNS_IPv6_AAAA, NULL) < 0) { + log_info(LD_EXIT, "eventdns rejected test address %s", + escaped_safe_str(address)); + } + } SMARTLIST_FOREACH_END(address); + } } #define N_WILDCARD_CHECKS 2 @@ -1655,27 +2013,29 @@ launch_test_addresses(int fd, short event, void *args) static void dns_launch_wildcard_checks(void) { - int i; + int i, ipv6; log_info(LD_EXIT, "Launching checks to see whether our nameservers like " "to hijack DNS failures."); - for (i = 0; i < N_WILDCARD_CHECKS; ++i) { - /* RFC2606 reserves these. Sadly, some DNS hijackers, in a silly attempt - * to 'comply' with rfc2606, refrain from giving A records for these. - * This is the standards-compliance equivalent of making sure that your - * crackhouse's elevator inspection certificate is up to date. - */ - launch_wildcard_check(2, 16, ".invalid"); - launch_wildcard_check(2, 16, ".test"); - - /* These will break specs if there are ever any number of - * 8+-character top-level domains. */ - launch_wildcard_check(8, 16, ""); - - /* Try some random .com/org/net domains. This will work fine so long as - * not too many resolve to the same place. */ - launch_wildcard_check(8, 16, ".com"); - launch_wildcard_check(8, 16, ".org"); - launch_wildcard_check(8, 16, ".net"); + for (ipv6 = 0; ipv6 <= 1; ++ipv6) { + for (i = 0; i < N_WILDCARD_CHECKS; ++i) { + /* RFC2606 reserves these. Sadly, some DNS hijackers, in a silly + * attempt to 'comply' with rfc2606, refrain from giving A records for + * these. This is the standards-compliance equivalent of making sure + * that your crackhouse's elevator inspection certificate is up to date. + */ + launch_wildcard_check(2, 16, ipv6, ".invalid"); + launch_wildcard_check(2, 16, ipv6, ".test"); + + /* These will break specs if there are ever any number of + * 8+-character top-level domains. */ + launch_wildcard_check(8, 16, ipv6, ""); + + /* Try some random .com/org/net domains. This will work fine so long as + * not too many resolve to the same place. */ + launch_wildcard_check(8, 16, ipv6, ".com"); + launch_wildcard_check(8, 16, ipv6, ".org"); + launch_wildcard_check(8, 16, ipv6, ".net"); + } } } @@ -1709,15 +2069,24 @@ dns_seems_to_be_broken(void) return dns_is_completely_invalid; } +/** Return true iff we think that IPv6 hostname lookup is broken */ +int +dns_seems_to_be_broken_for_ipv6(void) +{ + return dns_is_broken_for_ipv6; +} + /** Forget what we've previously learned about our DNS servers' correctness. */ void dns_reset_correctness_checks(void) { - strmap_free(dns_wildcard_response_count, _tor_free); + strmap_free(dns_wildcard_response_count, tor_free_); dns_wildcard_response_count = NULL; n_wildcard_requests = 0; + n_ipv6_requests_made = n_ipv6_timeouts = 0; + if (dns_wildcard_list) { SMARTLIST_FOREACH(dns_wildcard_list, char *, cp, tor_free(cp)); smartlist_clear(dns_wildcard_list); @@ -1728,7 +2097,8 @@ dns_reset_correctness_checks(void) smartlist_clear(dns_wildcarded_test_address_list); } dns_wildcard_one_notice_given = dns_wildcard_notice_given = - dns_wildcarded_test_address_notice_given = dns_is_completely_invalid = 0; + dns_wildcarded_test_address_notice_given = dns_is_completely_invalid = + dns_is_broken_for_ipv6 = 0; } /** Return true iff we have noticed that the dotted-quad <b>ip</b> has been @@ -1736,7 +2106,7 @@ dns_reset_correctness_checks(void) static int answer_is_wildcarded(const char *ip) { - return dns_wildcard_list && smartlist_string_isin(dns_wildcard_list, ip); + return dns_wildcard_list && smartlist_contains_string(dns_wildcard_list, ip); } /** Exit with an assertion if <b>resolve</b> is corrupt. */ @@ -1752,11 +2122,14 @@ assert_resolve_ok(cached_resolve_t *resolve) } if (resolve->state == CACHE_STATE_PENDING || resolve->state == CACHE_STATE_DONE) { +#if 0 tor_assert(!resolve->ttl); if (resolve->is_reverse) - tor_assert(!resolve->result.hostname); + tor_assert(!resolve->hostname); else - tor_assert(!resolve->result.a.addr); + tor_assert(!resolve->result_ipv4.addr_ipv4); +#endif + /*XXXXX ADD MORE */ } } @@ -1779,15 +2152,15 @@ dump_dns_mem_usage(int severity) /* 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.", + tor_log(severity, LD_MM, "Our DNS cache has %d entries.", hash_count); + tor_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 -_assert_cache_ok(void) +assert_cache_ok_(void) { cached_resolve_t **resolve; int bad_rep = _cache_map_HT_REP_IS_BAD(&cache_root); @@ -1804,7 +2177,7 @@ _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 index 8c8b476ac8..022cd4ac63 100644 --- a/src/or/dns.h +++ b/src/or/dns.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for dns.c. **/ -#ifndef _TOR_DNS_H -#define _TOR_DNS_H +#ifndef TOR_DNS_H +#define TOR_DNS_H int dns_init(void); int has_dns_init_failed(void); @@ -24,6 +24,7 @@ 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); +int dns_seems_to_be_broken_for_ipv6(void); void dns_reset_correctness_checks(void); void dump_dns_mem_usage(int severity); diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index 69adcef9ea..ebff7b524c 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2012, The Tor Project, Inc. */ +/* Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -89,6 +89,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) continue; switch (req->questions[i]->type) { case EVDNS_TYPE_A: + case EVDNS_TYPE_AAAA: case EVDNS_TYPE_PTR: q = req->questions[i]; default: @@ -101,7 +102,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) evdns_server_request_respond(req, DNS_ERR_NOTIMPL); return; } - if (q->type != EVDNS_TYPE_A) { + if (q->type != EVDNS_TYPE_A && q->type != EVDNS_TYPE_AAAA) { tor_assert(q->type == EVDNS_TYPE_PTR); } @@ -125,7 +126,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) TO_CONN(conn)->port = port; TO_CONN(conn)->address = tor_dup_addr(&tor_addr); - if (q->type == EVDNS_TYPE_A) + if (q->type == EVDNS_TYPE_A || q->type == EVDNS_TYPE_AAAA) entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE; else entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; @@ -133,7 +134,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) strlcpy(entry_conn->socks_request->address, q->name, sizeof(entry_conn->socks_request->address)); - entry_conn->socks_request->listener_type = listener->_base.type; + entry_conn->socks_request->listener_type = listener->base_.type; entry_conn->dns_server_request = req; entry_conn->isolation_flags = listener->isolation_flags; entry_conn->session_group = listener->session_group; @@ -146,7 +147,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) return; } - control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0); + control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0); /* Now, unless a controller asked us to leave streams unattached, * throw the connection over to get rewritten (which will @@ -169,7 +170,8 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) * response; -1 if we couldn't launch the request. */ int -dnsserv_launch_request(const char *name, int reverse) +dnsserv_launch_request(const char *name, int reverse, + control_connection_t *control_conn) { entry_connection_t *entry_conn; edge_connection_t *conn; @@ -178,7 +180,26 @@ dnsserv_launch_request(const char *name, int reverse) /* Make a new dummy AP connection, and attach the request to it. */ entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET); conn = ENTRY_TO_EDGE_CONN(entry_conn); - conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; + conn->base_.state = AP_CONN_STATE_RESOLVE_WAIT; + + tor_addr_copy(&TO_CONN(conn)->addr, &control_conn->base_.addr); +#ifdef AF_UNIX + /* + * The control connection can be AF_UNIX and if so tor_dup_addr will + * unhelpfully say "<unknown address type>"; say "(Tor_internal)" + * instead. + */ + if (control_conn->base_.socket_family == AF_UNIX) { + TO_CONN(conn)->port = 0; + TO_CONN(conn)->address = tor_strdup("(Tor_internal)"); + } else { + TO_CONN(conn)->port = control_conn->base_.port; + TO_CONN(conn)->address = tor_dup_addr(&control_conn->base_.addr); + } +#else + TO_CONN(conn)->port = control_conn->base_.port; + TO_CONN(conn)->address = tor_dup_addr(&control_conn->base_.addr); +#endif if (reverse) entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; @@ -202,6 +223,8 @@ dnsserv_launch_request(const char *name, int reverse) return -1; } + control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0); + /* 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 @@ -289,8 +312,9 @@ dnsserv_resolved(entry_connection_t *conn, * or more of the questions in the request); then, call * evdns_server_request_respond. */ if (answer_type == RESOLVED_TYPE_IPV6) { - log_info(LD_APP, "Got an IPv6 answer; that's not implemented."); - err = DNS_ERR_NOTIMPL; + evdns_server_request_add_aaaa_reply(req, + name, + 1, answer, ttl); } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4 && conn->socks_request->command == SOCKS_COMMAND_RESOLVE) { evdns_server_request_add_a_reply(req, diff --git a/src/or/dnsserv.h b/src/or/dnsserv.h index 3aaa038d2b..687a77e59e 100644 --- a/src/or/dnsserv.h +++ b/src/or/dnsserv.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for dnsserv.c. **/ -#ifndef _TOR_DNSSERV_H -#define _TOR_DNSSERV_H +#ifndef TOR_DNSSERV_H +#define TOR_DNSSERV_H void dnsserv_configure_listener(connection_t *conn); void dnsserv_close_listener(connection_t *conn); @@ -20,7 +20,8 @@ void dnsserv_resolved(entry_connection_t *conn, const char *answer, int ttl); void dnsserv_reject_request(entry_connection_t *conn); -int dnsserv_launch_request(const char *name, int is_reverse); +int dnsserv_launch_request(const char *name, int is_reverse, + control_connection_t *control_conn); #endif diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c new file mode 100644 index 0000000000..59770fa658 --- /dev/null +++ b/src/or/entrynodes.c @@ -0,0 +1,2259 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file entrynodes.c + * \brief Code to manage our fixed first nodes for various functions. + * + * Entry nodes can be guards (for general use) or bridges (for censorship + * circumvention). + **/ + +#include "or.h" +#include "circuitbuild.h" +#include "circuitstats.h" +#include "config.h" +#include "confparse.h" +#include "connection.h" +#include "connection_or.h" +#include "control.h" +#include "directory.h" +#include "entrynodes.h" +#include "main.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "nodelist.h" +#include "policies.h" +#include "router.h" +#include "routerlist.h" +#include "routerparse.h" +#include "routerset.h" +#include "transports.h" +#include "statefile.h" + +/** Information about a configured bridge. Currently this just matches the + * ones in the torrc file, but one day we may be able to learn about new + * bridges on our own, and remember them in the state file. */ +typedef struct { + /** Address of the bridge. */ + tor_addr_t addr; + /** TLS port for the bridge. */ + uint16_t port; + /** Boolean: We are re-parsing our bridge list, and we are going to remove + * this one if we don't find it in the list of configured bridges. */ + unsigned marked_for_removal : 1; + /** Expected identity digest, or all zero bytes if we don't know what the + * digest should be. */ + char identity[DIGEST_LEN]; + + /** Name of pluggable transport protocol taken from its config line. */ + char *transport_name; + + /** When should we next try to fetch a descriptor for this bridge? */ + download_status_t fetch_status; +} bridge_info_t; + +/** A list of our chosen entry guards. */ +static smartlist_t *entry_guards = NULL; +/** A value of 1 means that the entry_guards list has changed + * and those changes need to be flushed to disk. */ +static int entry_guards_dirty = 0; + +static void bridge_free(bridge_info_t *bridge); +static const node_t *choose_random_entry_impl(cpath_build_state_t *state, + int for_directory, + dirinfo_type_t dirtype); + +/** Return the list of entry guards, creating it if necessary. */ +const smartlist_t * +get_entry_guards(void) +{ + if (! entry_guards) + entry_guards = smartlist_new(); + return entry_guards; +} + +/** Check whether the entry guard <b>e</b> is usable, given the directory + * authorities' opinion about the router (stored in <b>ri</b>) and the user's + * configuration (in <b>options</b>). Set <b>e</b>->bad_since + * accordingly. Return true iff the entry guard's status changes. + * + * If it's not usable, set *<b>reason</b> to a static string explaining why. + */ +static int +entry_guard_set_status(entry_guard_t *e, const node_t *node, + time_t now, const or_options_t *options, + const char **reason) +{ + char buf[HEX_DIGEST_LEN+1]; + int changed = 0; + + *reason = NULL; + + /* Do we want to mark this guard as bad? */ + if (!node) + *reason = "unlisted"; + else if (!node->is_running) + *reason = "down"; + else if (options->UseBridges && (!node->ri || + node->ri->purpose != ROUTER_PURPOSE_BRIDGE)) + *reason = "not a bridge"; + else if (options->UseBridges && !node_is_a_configured_bridge(node)) + *reason = "not a configured bridge"; + else if (!options->UseBridges && !node->is_possible_guard && + !routerset_contains_node(options->EntryNodes,node)) + *reason = "not recommended as a guard"; + else if (routerset_contains_node(options->ExcludeNodes, node)) + *reason = "excluded"; + else if (e->path_bias_disabled) + *reason = "path-biased"; + + if (*reason && ! e->bad_since) { + /* Router is newly bad. */ + base16_encode(buf, sizeof(buf), e->identity, DIGEST_LEN); + log_info(LD_CIRC, "Entry guard %s (%s) is %s: marking as unusable.", + e->nickname, buf, *reason); + + e->bad_since = now; + control_event_guard(e->nickname, e->identity, "BAD"); + changed = 1; + } else if (!*reason && e->bad_since) { + /* There's nothing wrong with the router any more. */ + base16_encode(buf, sizeof(buf), e->identity, DIGEST_LEN); + log_info(LD_CIRC, "Entry guard %s (%s) is no longer unusable: " + "marking as ok.", e->nickname, buf); + + e->bad_since = 0; + control_event_guard(e->nickname, e->identity, "GOOD"); + changed = 1; + } + + if (node) { + int is_dir = node_is_dir(node) && node->rs && + node->rs->version_supports_microdesc_cache; + if (options->UseBridges && node_is_a_configured_bridge(node)) + is_dir = 1; + if (e->is_dir_cache != is_dir) { + e->is_dir_cache = is_dir; + changed = 1; + } + } + + return changed; +} + +/** Return true iff enough time has passed since we last tried to connect + * to the unreachable guard <b>e</b> that we're willing to try again. */ +static int +entry_is_time_to_retry(entry_guard_t *e, time_t now) +{ + long diff; + if (e->last_attempted < e->unreachable_since) + return 1; + diff = now - e->unreachable_since; + if (diff < 6*60*60) + return now > (e->last_attempted + 60*60); + else if (diff < 3*24*60*60) + return now > (e->last_attempted + 4*60*60); + else if (diff < 7*24*60*60) + return now > (e->last_attempted + 18*60*60); + else + return now > (e->last_attempted + 36*60*60); +} + +/** Return the node corresponding to <b>e</b>, if <b>e</b> is + * working well enough that we are willing to use it as an entry + * right now. (Else return NULL.) In particular, it must be + * - Listed as either up or never yet contacted; + * - 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> + * (unless it's a configured EntryNode); + * - Allowed by our current ReachableORAddresses config option; and + * - 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. + * + * If need_descriptor is true, only return the node if we currently have + * a descriptor (routerinfo or microdesc) for it. + */ +static INLINE const node_t * +entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, + int assume_reachable, int need_descriptor, const char **msg) +{ + const node_t *node; + const or_options_t *options = get_options(); + tor_assert(msg); + + if (e->path_bias_disabled) { + *msg = "path-biased"; + return NULL; + } + 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))) { + *msg = "unreachable"; + return NULL; + } + node = node_get_by_id(e->identity); + if (!node) { + *msg = "no node info"; + return NULL; + } + if (need_descriptor && !node_has_descriptor(node)) { + *msg = "no descriptor"; + return NULL; + } + if (get_options()->UseBridges) { + if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) { + *msg = "not a bridge"; + return NULL; + } + if (!node_is_a_configured_bridge(node)) { + *msg = "not a configured bridge"; + return NULL; + } + } else { /* !get_options()->UseBridges */ + if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) { + *msg = "not general-purpose"; + return NULL; + } + } + if (routerset_contains_node(options->EntryNodes, node)) { + /* they asked for it, they get it */ + need_uptime = need_capacity = 0; + } + if (node_is_unreliable(node, need_uptime, need_capacity, 0)) { + *msg = "not fast/stable"; + return NULL; + } + if (!fascist_firewall_allows_node(node)) { + *msg = "unreachable by config"; + return NULL; + } + return node; +} + +/** Return the number of entry guards that we think are usable. */ +int +num_live_entry_guards(int for_directory) +{ + int n = 0; + const char *msg; + if (! entry_guards) + return 0; + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { + if (for_directory && !entry->is_dir_cache) + continue; + if (entry_is_live(entry, 0, 1, 0, !for_directory, &msg)) + ++n; + } SMARTLIST_FOREACH_END(entry); + return n; +} + +/** If <b>digest</b> matches the identity of any node in the + * entry_guards list, return that node. Else return NULL. */ +entry_guard_t * +entry_guard_get_by_id_digest(const char *digest) +{ + SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, + if (tor_memeq(digest, entry->identity, DIGEST_LEN)) + return entry; + ); + return NULL; +} + +/** Dump a description of our list of entry guards to the log at level + * <b>severity</b>. */ +static void +log_entry_guards(int severity) +{ + smartlist_t *elements = smartlist_new(); + char *s; + + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) + { + const char *msg = NULL; + if (entry_is_live(e, 0, 1, 0, 0, &msg)) + smartlist_add_asprintf(elements, "%s [%s] (up %s)", + e->nickname, + hex_str(e->identity, DIGEST_LEN), + e->made_contact ? "made-contact" : "never-contacted"); + else + smartlist_add_asprintf(elements, "%s [%s] (%s, %s)", + e->nickname, + hex_str(e->identity, DIGEST_LEN), + msg, + e->made_contact ? "made-contact" : "never-contacted"); + } + SMARTLIST_FOREACH_END(e); + + s = smartlist_join_strings(elements, ",", 0, NULL); + SMARTLIST_FOREACH(elements, char*, cp, tor_free(cp)); + smartlist_free(elements); + log_fn(severity,LD_CIRC,"%s",s); + tor_free(s); +} + +/** Called when one or more guards that we would previously have used for some + * purpose are no longer in use because a higher-priority guard has become + * usable again. */ +static void +control_event_guard_deferred(void) +{ + /* XXXX We don't actually have a good way to figure out _how many_ entries + * are live for some purpose. We need an entry_is_even_slightly_live() + * function for this to work right. NumEntryGuards isn't reliable: if we + * need guards with weird properties, we can have more than that number + * live. + **/ +#if 0 + int n = 0; + const char *msg; + const 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, &msg)) { + if (n++ == options->NumEntryGuards) { + control_event_guard(entry->nickname, entry->identity, "DEFERRED"); + return; + } + } + }); +#endif +} + +/** Largest amount that we'll backdate chosen_on_date */ +#define CHOSEN_ON_DATE_SLOP (30*86400) + +/** Add a new (preferably stable and fast) router to our + * entry_guards list. Return a pointer to the router if we succeed, + * or NULL if we can't find any more suitable entries. + * + * If <b>chosen</b> is defined, use that one, and if it's not + * already in our entry_guards list, put it at the *beginning*. + * Else, put the one we pick at the end of the list. */ +static const node_t * +add_an_entry_guard(const node_t *chosen, int reset_status, int prepend, + int for_discovery, int for_directory) +{ + const node_t *node; + entry_guard_t *entry; + + if (chosen) { + node = chosen; + entry = entry_guard_get_by_id_digest(node->identity); + if (entry) { + if (reset_status) { + entry->bad_since = 0; + entry->can_retry = 1; + } + entry->is_dir_cache = node->rs && + node->rs->version_supports_microdesc_cache; + if (get_options()->UseBridges && node_is_a_configured_bridge(node)) + entry->is_dir_cache = 1; + return NULL; + } + } else if (!for_directory) { + node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL); + if (!node) + return NULL; + } else { + const routerstatus_t *rs; + rs = router_pick_directory_server(MICRODESC_DIRINFO|V3_DIRINFO, + PDS_PREFER_TUNNELED_DIR_CONNS_|PDS_FOR_GUARD); + if (!rs) + return NULL; + node = node_get_by_id(rs->identity_digest); + if (!node) + return NULL; + } + if (node->using_as_guard) + return NULL; + if (entry_guard_get_by_id_digest(node->identity) != NULL) { + log_info(LD_CIRC, "I was about to add a duplicate entry guard."); + /* This can happen if we choose a guard, then the node goes away, then + * comes back. */ + ((node_t*) node)->using_as_guard = 1; + return NULL; + } + entry = tor_malloc_zero(sizeof(entry_guard_t)); + log_info(LD_CIRC, "Chose %s as new entry guard.", + node_describe(node)); + strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname)); + memcpy(entry->identity, node->identity, DIGEST_LEN); + entry->is_dir_cache = node_is_dir(node) && + node->rs && node->rs->version_supports_microdesc_cache; + if (get_options()->UseBridges && node_is_a_configured_bridge(node)) + entry->is_dir_cache = 1; + + /* Choose expiry time smudged over the past month. The goal here + * is to a) spread out when Tor clients rotate their guards, so they + * don't all select them on the same day, and b) avoid leaving a + * precise timestamp in the state file about when we first picked + * this guard. For details, see the Jan 2010 or-dev thread. */ + entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); + entry->chosen_by_version = tor_strdup(VERSION); + + /* Are we picking this guard because all of our current guards are + * down so we need another one (for_discovery is 1), or because we + * decided we need more variety in our guard list (for_discovery is 0)? + * + * Currently we hack this behavior into place by setting "made_contact" + * for guards of the latter variety, so we'll be willing to use any of + * them right off the bat. + */ + if (!for_discovery) + entry->made_contact = 1; + + ((node_t*)node)->using_as_guard = 1; + if (prepend) + smartlist_insert(entry_guards, 0, entry); + else + smartlist_add(entry_guards, entry); + control_event_guard(entry->nickname, entry->identity, "NEW"); + control_event_guard_deferred(); + log_entry_guards(LOG_INFO); + return node; +} + +/** Choose how many entry guards or directory guards we'll use. If + * <b>for_directory</b> is true, we return how many directory guards to + * use; else we return how many entry guards to use. */ +static int +decide_num_guards(const or_options_t *options, int for_directory) +{ + if (for_directory && options->NumDirectoryGuards != 0) + return options->NumDirectoryGuards; + return options->NumEntryGuards; +} + +/** If the use of entry guards is configured, choose more entry guards + * until we have enough in the list. */ +static void +pick_entry_guards(const or_options_t *options, int for_directory) +{ + int changed = 0; + const int num_needed = decide_num_guards(options, for_directory); + + tor_assert(entry_guards); + + while (num_live_entry_guards(for_directory) < num_needed) { + if (!add_an_entry_guard(NULL, 0, 0, 0, for_directory)) + break; + changed = 1; + } + if (changed) + entry_guards_changed(); +} + +/** How long (in seconds) do we allow an entry guard to be nonfunctional, + * unlisted, excluded, or otherwise nonusable before we give up on it? */ +#define ENTRY_GUARD_REMOVE_AFTER (30*24*60*60) + +/** Release all storage held by <b>e</b>. */ +static void +entry_guard_free(entry_guard_t *e) +{ + if (!e) + return; + tor_free(e->chosen_by_version); + tor_free(e); +} + +/** + * Return the minimum lifetime of working entry guard, in seconds, + * as given in the consensus networkstatus. (Plus CHOSEN_ON_DATE_SLOP, + * so that we can do the chosen_on_date randomization while achieving the + * desired minimum lifetime.) + */ +static int32_t +guards_get_lifetime(void) +{ + const or_options_t *options = get_options(); +#define DFLT_GUARD_LIFETIME (86400 * 60) /* Two months. */ +#define MIN_GUARD_LIFETIME (86400 * 30) /* One months. */ +#define MAX_GUARD_LIFETIME (86400 * 1826) /* Five years. */ + + if (options->GuardLifetime >= 1) { + return CLAMP(MIN_GUARD_LIFETIME, + options->GuardLifetime, + MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP; + } + + return networkstatus_get_param(NULL, "GuardLifetime", + DFLT_GUARD_LIFETIME, + MIN_GUARD_LIFETIME, + MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP; +} + +/** Remove any entry guard which was selected by an unknown version of Tor, + * or which was selected by a version of Tor that's known to select + * entry guards badly, or which was selected more 2 months ago. */ +/* XXXX The "obsolete guards" and "chosen long ago guards" things should + * probably be different functions. */ +static int +remove_obsolete_entry_guards(time_t now) +{ + int changed = 0, i; + int32_t guard_lifetime = guards_get_lifetime(); + + for (i = 0; i < smartlist_len(entry_guards); ++i) { + entry_guard_t *entry = smartlist_get(entry_guards, i); + const char *ver = entry->chosen_by_version; + const char *msg = NULL; + tor_version_t v; + int version_is_bad = 0, date_is_bad = 0; + if (!ver) { + msg = "does not say what version of Tor it was selected by"; + version_is_bad = 1; + } else if (tor_version_parse(ver, &v)) { + msg = "does not seem to be from any recognized version of Tor"; + version_is_bad = 1; + } else { + char *tor_ver = NULL; + tor_asprintf(&tor_ver, "Tor %s", ver); + if ((tor_version_as_new_as(tor_ver, "0.1.0.10-alpha") && + !tor_version_as_new_as(tor_ver, "0.1.2.16-dev")) || + (tor_version_as_new_as(tor_ver, "0.2.0.0-alpha") && + !tor_version_as_new_as(tor_ver, "0.2.0.6-alpha")) || + /* above are bug 440; below are bug 1217 */ + (tor_version_as_new_as(tor_ver, "0.2.1.3-alpha") && + !tor_version_as_new_as(tor_ver, "0.2.1.23")) || + (tor_version_as_new_as(tor_ver, "0.2.2.0-alpha") && + !tor_version_as_new_as(tor_ver, "0.2.2.7-alpha"))) { + msg = "was selected without regard for guard bandwidth"; + version_is_bad = 1; + } + tor_free(tor_ver); + } + if (!version_is_bad && entry->chosen_on_date + guard_lifetime < now) { + /* It's been too long since the date listed in our state file. */ + msg = "was selected several months ago"; + date_is_bad = 1; + } + + if (version_is_bad || date_is_bad) { /* we need to drop it */ + char dbuf[HEX_DIGEST_LEN+1]; + tor_assert(msg); + base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN); + log_fn(version_is_bad ? LOG_NOTICE : LOG_INFO, LD_CIRC, + "Entry guard '%s' (%s) %s. (Version=%s.) Replacing it.", + entry->nickname, dbuf, msg, ver?escaped(ver):"none"); + control_event_guard(entry->nickname, entry->identity, "DROPPED"); + entry_guard_free(entry); + smartlist_del_keeporder(entry_guards, i--); + log_entry_guards(LOG_INFO); + changed = 1; + } + } + + return changed ? 1 : 0; +} + +/** Remove all entry guards that have been down or unlisted for so + * 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(time_t now) +{ + char dbuf[HEX_DIGEST_LEN+1]; + char tbuf[ISO_TIME_LEN+1]; + int i; + int changed = 0; + + for (i = 0; i < smartlist_len(entry_guards); ) { + entry_guard_t *entry = smartlist_get(entry_guards, i); + if (entry->bad_since && + ! entry->path_bias_disabled && + entry->bad_since + ENTRY_GUARD_REMOVE_AFTER < now) { + + base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN); + format_local_iso_time(tbuf, entry->bad_since); + log_info(LD_CIRC, "Entry guard '%s' (%s) has been down or unlisted " + "since %s local time; removing.", + entry->nickname, dbuf, tbuf); + control_event_guard(entry->nickname, entry->identity, "DROPPED"); + entry_guard_free(entry); + smartlist_del_keeporder(entry_guards, i); + log_entry_guards(LOG_INFO); + changed = 1; + } else + ++i; + } + return changed ? 1 : 0; +} + +/** A new directory or router-status has arrived; update the down/listed + * status of the entry guards. + * + * An entry is 'down' if the directory lists it as nonrunning. + * An entry is 'unlisted' if the directory doesn't include it. + * + * Don't call this on startup; only on a fresh download. Otherwise we'll + * think that things are unlisted. + */ +void +entry_guards_compute_status(const or_options_t *options, time_t now) +{ + int changed = 0; + digestmap_t *reasons; + + if (! entry_guards) + return; + + 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) + { + const node_t *r = node_get_by_id(entry->identity); + const char *reason = NULL; + if (entry_guard_set_status(entry, r, now, options, &reason)) + changed = 1; + + if (entry->bad_since) + tor_assert(reason); + if (reason) + digestmap_set(reasons, entry->identity, (char*)reason); + } + SMARTLIST_FOREACH_END(entry); + + if (remove_dead_entry_guards(now)) + changed = 1; + if (remove_obsolete_entry_guards(now)) + changed = 1; + + if (changed) { + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { + const char *reason = digestmap_get(reasons, entry->identity); + const char *live_msg = ""; + const node_t *r = entry_is_live(entry, 0, 1, 0, 0, &live_msg); + log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", + entry->nickname, + hex_str(entry->identity, DIGEST_LEN), + entry->unreachable_since ? "unreachable" : "reachable", + entry->bad_since ? "unusable" : "usable", + reason ? ", ": "", + reason ? reason : "", + 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(0), smartlist_len(entry_guards)); + log_entry_guards(LOG_INFO); + entry_guards_changed(); + } + + digestmap_free(reasons, NULL); +} + +/** Called when a connection to an OR with the identity digest <b>digest</b> + * is established (<b>succeeded</b>==1) or has failed (<b>succeeded</b>==0). + * If the OR is an entry, change that entry's up/down status. + * Return 0 normally, or -1 if we want to tear down the new connection. + * + * If <b>mark_relay_status</b>, also call router_set_status() on this + * relay. + * + * XXX024 change succeeded and mark_relay_status into 'int flags'. + */ +int +entry_guard_register_connect_status(const char *digest, int succeeded, + int mark_relay_status, time_t now) +{ + int changed = 0; + int refuse_conn = 0; + int first_contact = 0; + entry_guard_t *entry = NULL; + int idx = -1; + char buf[HEX_DIGEST_LEN+1]; + + if (! entry_guards) + return 0; + + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + tor_assert(e); + if (tor_memeq(e->identity, digest, DIGEST_LEN)) { + entry = e; + idx = e_sl_idx; + break; + } + } SMARTLIST_FOREACH_END(e); + + if (!entry) + return 0; + + base16_encode(buf, sizeof(buf), entry->identity, DIGEST_LEN); + + if (succeeded) { + if (entry->unreachable_since) { + log_info(LD_CIRC, "Entry guard '%s' (%s) is now reachable again. Good.", + entry->nickname, buf); + entry->can_retry = 0; + entry->unreachable_since = 0; + entry->last_attempted = now; + control_event_guard(entry->nickname, entry->identity, "UP"); + changed = 1; + } + if (!entry->made_contact) { + entry->made_contact = 1; + first_contact = changed = 1; + } + } else { /* ! succeeded */ + if (!entry->made_contact) { + /* We've never connected to this one. */ + log_info(LD_CIRC, + "Connection to never-contacted entry guard '%s' (%s) failed. " + "Removing from the list. %d/%d entry guards usable/new.", + entry->nickname, buf, + num_live_entry_guards(0)-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); + changed = 1; + } else if (!entry->unreachable_since) { + log_info(LD_CIRC, "Unable to connect to entry guard '%s' (%s). " + "Marking as unreachable.", entry->nickname, buf); + entry->unreachable_since = entry->last_attempted = now; + control_event_guard(entry->nickname, entry->identity, "DOWN"); + changed = 1; + entry->can_retry = 0; /* We gave it an early chance; no good. */ + } else { + char tbuf[ISO_TIME_LEN+1]; + format_iso_time(tbuf, entry->unreachable_since); + log_debug(LD_CIRC, "Failed to connect to unreachable entry guard " + "'%s' (%s). It has been unreachable since %s.", + entry->nickname, buf, tbuf); + entry->last_attempted = now; + entry->can_retry = 0; /* We gave it an early chance; no good. */ + } + } + + /* if the caller asked us to, also update the is_running flags for this + * relay */ + if (mark_relay_status) + router_set_status(digest, succeeded); + + if (first_contact) { + /* We've just added a new long-term entry guard. Perhaps the network just + * came back? We should give our earlier entries another try too, + * and close this connection so we don't use it before we've given + * the others a shot. */ + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + if (e == entry) + break; + if (e->made_contact) { + const char *msg; + const node_t *r = entry_is_live(e, 0, 1, 1, 0, &msg); + if (r && e->unreachable_since) { + refuse_conn = 1; + e->can_retry = 1; + } + } + } SMARTLIST_FOREACH_END(e); + if (refuse_conn) { + log_info(LD_CIRC, + "Connected to new entry guard '%s' (%s). Marking earlier " + "entry guards up. %d/%d entry guards usable/new.", + entry->nickname, buf, + num_live_entry_guards(0), smartlist_len(entry_guards)); + log_entry_guards(LOG_INFO); + changed = 1; + } + } + + if (changed) + entry_guards_changed(); + return refuse_conn ? -1 : 0; +} + +/** When we try to choose an entry guard, should we parse and add + * config's EntryNodes first? */ +static int should_add_entry_nodes = 0; + +/** Called when the value of EntryNodes changes in our configuration. */ +void +entry_nodes_should_be_added(void) +{ + log_info(LD_CIRC, "EntryNodes config option set. Putting configured " + "relays at the front of the entry guard list."); + should_add_entry_nodes = 1; +} + +/** Update the using_as_guard fields of all the nodes. We do this after we + * remove entry guards from the list: This is the only function that clears + * the using_as_guard field. */ +static void +update_node_guard_status(void) +{ + smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, node_t *, node, node->using_as_guard = 0); + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { + node_t *node = node_get_mutable_by_id(entry->identity); + if (node) + node->using_as_guard = 1; + } SMARTLIST_FOREACH_END(entry); +} + +/** Adjust the entry guards list so that it only contains entries from + * EntryNodes, adding new entries from EntryNodes to the list as needed. */ +static void +entry_guards_set_from_config(const or_options_t *options) +{ + smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps; + smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list; + tor_assert(entry_guards); + + should_add_entry_nodes = 0; + + if (!options->EntryNodes) { + /* It's possible that a controller set EntryNodes, thus making + * should_add_entry_nodes set, then cleared it again, all before the + * call to choose_random_entry() that triggered us. If so, just return. + */ + return; + } + + { + char *string = routerset_to_string(options->EntryNodes); + log_info(LD_CIRC,"Adding configured EntryNodes '%s'.", string); + tor_free(string); + } + + entry_nodes = smartlist_new(); + worse_entry_nodes = smartlist_new(); + entry_fps = smartlist_new(); + old_entry_guards_on_list = smartlist_new(); + old_entry_guards_not_on_list = smartlist_new(); + + /* Split entry guards into those on the list and those not. */ + + routerset_get_all_nodes(entry_nodes, options->EntryNodes, + options->ExcludeNodes, 0); + SMARTLIST_FOREACH(entry_nodes, const node_t *,node, + smartlist_add(entry_fps, (void*)node->identity)); + + SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, { + if (smartlist_contains_digest(entry_fps, e->identity)) + smartlist_add(old_entry_guards_on_list, e); + else + smartlist_add(old_entry_guards_not_on_list, e); + }); + + /* Remove all currently configured guard nodes, excluded nodes, unreachable + * nodes, or non-Guard nodes from entry_nodes. */ + SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { + if (entry_guard_get_by_id_digest(node->identity)) { + SMARTLIST_DEL_CURRENT(entry_nodes, node); + continue; + } else if (routerset_contains_node(options->ExcludeNodes, node)) { + SMARTLIST_DEL_CURRENT(entry_nodes, node); + continue; + } else if (!fascist_firewall_allows_node(node)) { + SMARTLIST_DEL_CURRENT(entry_nodes, node); + continue; + } else if (! node->is_possible_guard) { + smartlist_add(worse_entry_nodes, (node_t*)node); + SMARTLIST_DEL_CURRENT(entry_nodes, node); + } + } SMARTLIST_FOREACH_END(node); + + /* Now build the new entry_guards list. */ + smartlist_clear(entry_guards); + /* First, the previously configured guards that are in EntryNodes. */ + smartlist_add_all(entry_guards, old_entry_guards_on_list); + /* Next, scramble the rest of EntryNodes, putting the guards first. */ + smartlist_shuffle(entry_nodes); + smartlist_shuffle(worse_entry_nodes); + smartlist_add_all(entry_nodes, worse_entry_nodes); + + /* Next, the rest of EntryNodes */ + SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { + add_an_entry_guard(node, 0, 0, 1, 0); + if (smartlist_len(entry_guards) > options->NumEntryGuards * 10) + break; + } SMARTLIST_FOREACH_END(node); + log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(entry_guards)); + /* Finally, free the remaining previously configured guards that are not in + * EntryNodes. */ + SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e, + entry_guard_free(e)); + + update_node_guard_status(); + + smartlist_free(entry_nodes); + smartlist_free(worse_entry_nodes); + smartlist_free(entry_fps); + smartlist_free(old_entry_guards_on_list); + smartlist_free(old_entry_guards_not_on_list); + entry_guards_changed(); +} + +/** 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 must stick to it. + */ +int +entry_list_is_constrained(const or_options_t *options) +{ + if (options->EntryNodes) + return 1; + if (options->UseBridges) + return 1; + return 0; +} + +/** Return true iff this node can answer directory questions about + * microdescriptors. */ +static int +node_understands_microdescriptors(const node_t *node) +{ + tor_assert(node); + if (node->rs && node->rs->version_supports_microdesc_cache) + return 1; + if (node->ri && tor_version_supports_microdescriptors(node->ri->platform)) + return 1; + return 0; +} + +/** Return true iff <b>node</b> is able to answer directory questions + * of type <b>dirinfo</b>. */ +static int +node_can_handle_dirinfo(const node_t *node, dirinfo_type_t dirinfo) +{ + /* Checking dirinfo for any type other than microdescriptors isn't required + yet, since we only choose directory guards that can support microdescs, + routerinfos, and networkstatuses, AND we don't use directory guards if + we're configured to do direct downloads of anything else. The only case + where we might have a guard that doesn't know about a type of directory + information is when we're retrieving directory information from a + bridge. */ + + if ((dirinfo & MICRODESC_DIRINFO) && + !node_understands_microdescriptors(node)) + return 0; + return 1; +} + +/** Pick a live (up and listed) entry guard from entry_guards. If + * <b>state</b> is non-NULL, this is for a specific circuit -- + * make sure not to pick this circuit's exit or any node in the + * exit's family. If <b>state</b> is NULL, we're looking for a random + * guard (likely a bridge). If <b>dirinfo</b> is not NO_DIRINFO, then + * only select from nodes that know how to answer directory questions + * of that type. */ +const node_t * +choose_random_entry(cpath_build_state_t *state) +{ + return choose_random_entry_impl(state, 0, 0); +} + +/** Pick a live (up and listed) directory guard from entry_guards for + * downloading information of type <b>type</b>. */ +const node_t * +choose_random_dirguard(dirinfo_type_t type) +{ + return choose_random_entry_impl(NULL, 1, type); +} + +/** Helper for choose_random{entry,dirguard}. */ +static const node_t * +choose_random_entry_impl(cpath_build_state_t *state, int for_directory, + dirinfo_type_t dirinfo_type) +{ + const or_options_t *options = get_options(); + smartlist_t *live_entry_guards = smartlist_new(); + smartlist_t *exit_family = smartlist_new(); + const node_t *chosen_exit = + state?build_state_get_exit_node(state) : NULL; + const node_t *node = NULL; + int need_uptime = state ? state->need_uptime : 0; + int need_capacity = state ? state->need_capacity : 0; + int preferred_min, consider_exit_family = 0; + int need_descriptor = !for_directory; + const int num_needed = decide_num_guards(options, for_directory); + + if (chosen_exit) { + nodelist_add_node_and_family(exit_family, chosen_exit); + consider_exit_family = 1; + } + + if (!entry_guards) + entry_guards = smartlist_new(); + + if (should_add_entry_nodes) + entry_guards_set_from_config(options); + + if (!entry_list_is_constrained(options) && + smartlist_len(entry_guards) < num_needed) + pick_entry_guards(options, for_directory); + + retry: + smartlist_clear(live_entry_guards); + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { + const char *msg; + node = entry_is_live(entry, need_uptime, need_capacity, 0, + need_descriptor, &msg); + if (!node) + continue; /* down, no point */ + if (for_directory) { + if (!entry->is_dir_cache) + continue; /* We need a directory and didn't get one. */ + } + if (node == chosen_exit) + continue; /* don't pick the same node for entry and exit */ + if (consider_exit_family && smartlist_contains(exit_family, node)) + continue; /* avoid relays that are family members of our exit */ + if (dirinfo_type != NO_DIRINFO && + !node_can_handle_dirinfo(node, dirinfo_type)) + continue; /* this node won't be able to answer our dir questions */ +#if 0 /* since EntryNodes is always strict now, this clause is moot */ + if (options->EntryNodes && + !routerset_contains_node(options->EntryNodes, node)) { + /* We've come to the end of our preferred entry nodes. */ + if (smartlist_len(live_entry_guards)) + goto choose_and_finish; /* only choose from the ones we like */ + if (options->StrictNodes) { + /* in theory this case should never happen, since + * entry_guards_set_from_config() drops unwanted relays */ + tor_fragile_assert(); + } else { + log_info(LD_CIRC, + "No relays from EntryNodes available. Using others."); + } + } +#endif + smartlist_add(live_entry_guards, (void*)node); + if (!entry->made_contact) { + /* Always start with the first not-yet-contacted entry + * guard. Otherwise we might add several new ones, pick + * 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) >= num_needed) + goto choose_and_finish; /* we have enough */ + } SMARTLIST_FOREACH_END(entry); + + if (entry_list_is_constrained(options)) { + /* If we prefer the entry nodes we've got, and we have at least + * 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_constrained(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 + * be a long time til we get it. -RD */ + node = add_an_entry_guard(NULL, 0, 0, 1, for_directory); + if (node) { + entry_guards_changed(); + /* XXX we start over here in case the new node we added shares + * a family with our exit node. There's a chance that we'll just + * load up on entry guards here, if the network we're using is + * one big family. Perhaps we should teach add_an_entry_guard() + * to understand nodes-to-avoid-if-possible? -RD */ + goto retry; + } + } + if (!node && need_uptime) { + need_uptime = 0; /* try without that requirement */ + goto retry; + } + if (!node && need_capacity) { + /* still no? last attempt, try without requiring capacity */ + need_capacity = 0; + goto retry; + } +#if 0 + /* Removing this retry logic: if we only allow one exit, and it is in the + same family as all our entries, then we are just plain not going to win + here. */ + if (!node && entry_list_is_constrained(options) && consider_exit_family) { + /* still no? if we're using bridges or have strictentrynodes + * set, and our chosen exit is in the same family as all our + * bridges/entry guards, then be flexible about families. */ + consider_exit_family = 0; + goto retry; + } +#endif + /* live_entry_guards may be empty below. Oh well, we tried. */ + } + + choose_and_finish: + 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. */ + node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD); + } else { + /* We choose uniformly at random here, because choose_good_entry_server() + * already weights its choices by bandwidth, so we don't want to + * *double*-weight our guard selection. */ + node = smartlist_choose(live_entry_guards); + } + smartlist_free(live_entry_guards); + smartlist_free(exit_family); + return node; +} + +/** Parse <b>state</b> and learn about the entry guards it describes. + * If <b>set</b> is true, and there are no errors, replace the global + * entry_list with what we find. + * On success, return 0. On failure, alloc into *<b>msg</b> a string + * describing the error, and return -1. + */ +int +entry_guards_parse_state(or_state_t *state, int set, char **msg) +{ + entry_guard_t *node = NULL; + smartlist_t *new_entry_guards = smartlist_new(); + config_line_t *line; + time_t now = time(NULL); + const char *state_version = state->TorVersion; + digestmap_t *added_by = digestmap_new(); + + *msg = NULL; + for (line = state->EntryGuards; line; line = line->next) { + if (!strcasecmp(line->key, "EntryGuard")) { + smartlist_t *args = smartlist_new(); + node = tor_malloc_zero(sizeof(entry_guard_t)); + /* all entry guards on disk have been contacted */ + node->made_contact = 1; + smartlist_add(new_entry_guards, node); + smartlist_split_string(args, line->value, " ", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + if (smartlist_len(args)<2) { + *msg = tor_strdup("Unable to parse entry nodes: " + "Too few arguments to EntryGuard"); + } else if (!is_legal_nickname(smartlist_get(args,0))) { + *msg = tor_strdup("Unable to parse entry nodes: " + "Bad nickname for EntryGuard"); + } else { + strlcpy(node->nickname, smartlist_get(args,0), MAX_NICKNAME_LEN+1); + if (base16_decode(node->identity, DIGEST_LEN, smartlist_get(args,1), + strlen(smartlist_get(args,1)))<0) { + *msg = tor_strdup("Unable to parse entry nodes: " + "Bad hex digest for EntryGuard"); + } + } + if (smartlist_len(args) >= 3) { + const char *is_cache = smartlist_get(args, 2); + if (!strcasecmp(is_cache, "DirCache")) { + node->is_dir_cache = 1; + } else if (!strcasecmp(is_cache, "NoDirCache")) { + node->is_dir_cache = 0; + } else { + log_warn(LD_CONFIG, "Bogus third argument to EntryGuard line: %s", + escaped(is_cache)); + } + } + SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); + smartlist_free(args); + if (*msg) + break; + } else if (!strcasecmp(line->key, "EntryGuardDownSince") || + !strcasecmp(line->key, "EntryGuardUnlistedSince")) { + time_t when; + time_t last_try = 0; + if (!node) { + *msg = tor_strdup("Unable to parse entry nodes: " + "EntryGuardDownSince/UnlistedSince without EntryGuard"); + break; + } + if (parse_iso_time(line->value, &when)<0) { + *msg = tor_strdup("Unable to parse entry nodes: " + "Bad time in EntryGuardDownSince/UnlistedSince"); + break; + } + if (when > now) { + /* It's a bad idea to believe info in the future: you can wind + * up with timeouts that aren't allowed to happen for years. */ + continue; + } + if (strlen(line->value) >= ISO_TIME_LEN+ISO_TIME_LEN+1) { + /* ignore failure */ + (void) parse_iso_time(line->value+ISO_TIME_LEN+1, &last_try); + } + if (!strcasecmp(line->key, "EntryGuardDownSince")) { + node->unreachable_since = when; + node->last_attempted = last_try; + } else { + node->bad_since = when; + } + } else if (!strcasecmp(line->key, "EntryGuardAddedBy")) { + char d[DIGEST_LEN]; + /* format is digest version date */ + if (strlen(line->value) < HEX_DIGEST_LEN+1+1+1+ISO_TIME_LEN) { + log_warn(LD_BUG, "EntryGuardAddedBy line is not long enough."); + continue; + } + if (base16_decode(d, sizeof(d), line->value, HEX_DIGEST_LEN)<0 || + line->value[HEX_DIGEST_LEN] != ' ') { + log_warn(LD_BUG, "EntryGuardAddedBy line %s does not begin with " + "hex digest", escaped(line->value)); + continue; + } + digestmap_set(added_by, d, tor_strdup(line->value+HEX_DIGEST_LEN+1)); + } else if (!strcasecmp(line->key, "EntryGuardPathUseBias")) { + const or_options_t *options = get_options(); + double use_cnt, success_cnt; + + if (!node) { + *msg = tor_strdup("Unable to parse entry nodes: " + "EntryGuardPathUseBias without EntryGuard"); + break; + } + + if (tor_sscanf(line->value, "%lf %lf", + &use_cnt, &success_cnt) != 2) { + log_info(LD_GENERAL, "Malformed path use bias line for node %s", + node->nickname); + continue; + } + + if (use_cnt < success_cnt) { + int severity = LOG_INFO; + /* If this state file was written by a Tor that would have + * already fixed it, then the overcounting bug is still there.. */ + if (tor_version_as_new_as(state_version, "0.2.4.13-alpha")) { + severity = LOG_NOTICE; + } + log_fn(severity, LD_BUG, + "State file contains unexpectedly high usage success " + "counts %lf/%lf for Guard %s ($%s)", + success_cnt, use_cnt, + node->nickname, hex_str(node->identity, DIGEST_LEN)); + success_cnt = use_cnt; + } + + node->use_attempts = use_cnt; + node->use_successes = success_cnt; + + log_info(LD_GENERAL, "Read %f/%f path use bias for node %s", + node->use_successes, node->use_attempts, node->nickname); + + /* Note: We rely on the < comparison here to allow us to set a 0 + * rate and disable the feature entirely. If refactoring, don't + * change to <= */ + if (pathbias_get_use_success_count(node)/node->use_attempts + < pathbias_get_extreme_use_rate(options) && + pathbias_get_dropguards(options)) { + node->path_bias_disabled = 1; + log_info(LD_GENERAL, + "Path use bias is too high (%f/%f); disabling node %s", + node->circ_successes, node->circ_attempts, node->nickname); + } + } else if (!strcasecmp(line->key, "EntryGuardPathBias")) { + const or_options_t *options = get_options(); + double hop_cnt, success_cnt, timeouts, collapsed, successful_closed, + unusable; + + if (!node) { + *msg = tor_strdup("Unable to parse entry nodes: " + "EntryGuardPathBias without EntryGuard"); + break; + } + + /* First try 3 params, then 2. */ + /* In the long run: circuit_success ~= successful_circuit_close + + * collapsed_circuits + + * unusable_circuits */ + if (tor_sscanf(line->value, "%lf %lf %lf %lf %lf %lf", + &hop_cnt, &success_cnt, &successful_closed, + &collapsed, &unusable, &timeouts) != 6) { + int old_success, old_hops; + if (tor_sscanf(line->value, "%u %u", &old_success, &old_hops) != 2) { + continue; + } + log_info(LD_GENERAL, "Reading old-style EntryGuardPathBias %s", + escaped(line->value)); + + success_cnt = old_success; + successful_closed = old_success; + hop_cnt = old_hops; + timeouts = 0; + collapsed = 0; + unusable = 0; + } + + if (hop_cnt < success_cnt) { + int severity = LOG_INFO; + /* If this state file was written by a Tor that would have + * already fixed it, then the overcounting bug is still there.. */ + if (tor_version_as_new_as(state_version, "0.2.4.13-alpha")) { + severity = LOG_NOTICE; + } + log_fn(severity, LD_BUG, + "State file contains unexpectedly high success counts " + "%lf/%lf for Guard %s ($%s)", + success_cnt, hop_cnt, + node->nickname, hex_str(node->identity, DIGEST_LEN)); + success_cnt = hop_cnt; + } + + node->circ_attempts = hop_cnt; + node->circ_successes = success_cnt; + + node->successful_circuits_closed = successful_closed; + node->timeouts = timeouts; + node->collapsed_circuits = collapsed; + node->unusable_circuits = unusable; + + log_info(LD_GENERAL, "Read %f/%f path bias for node %s", + node->circ_successes, node->circ_attempts, node->nickname); + /* Note: We rely on the < comparison here to allow us to set a 0 + * rate and disable the feature entirely. If refactoring, don't + * change to <= */ + if (pathbias_get_close_success_count(node)/node->circ_attempts + < pathbias_get_extreme_rate(options) && + pathbias_get_dropguards(options)) { + node->path_bias_disabled = 1; + log_info(LD_GENERAL, + "Path bias is too high (%f/%f); disabling node %s", + node->circ_successes, node->circ_attempts, node->nickname); + } + + } else { + log_warn(LD_BUG, "Unexpected key %s", line->key); + } + } + + SMARTLIST_FOREACH_BEGIN(new_entry_guards, entry_guard_t *, e) { + char *sp; + char *val = digestmap_get(added_by, e->identity); + if (val && (sp = strchr(val, ' '))) { + time_t when; + *sp++ = '\0'; + if (parse_iso_time(sp, &when)<0) { + log_warn(LD_BUG, "Can't read time %s in EntryGuardAddedBy", sp); + } else { + e->chosen_by_version = tor_strdup(val); + e->chosen_on_date = when; + } + } else { + if (state_version) { + e->chosen_by_version = tor_strdup(state_version); + e->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); + } + } + if (e->path_bias_disabled && !e->bad_since) + e->bad_since = time(NULL); + } + SMARTLIST_FOREACH_END(e); + + if (*msg || !set) { + SMARTLIST_FOREACH(new_entry_guards, entry_guard_t *, e, + entry_guard_free(e)); + smartlist_free(new_entry_guards); + } else { /* !err && set */ + if (entry_guards) { + SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, + entry_guard_free(e)); + smartlist_free(entry_guards); + } + entry_guards = new_entry_guards; + entry_guards_dirty = 0; + /* XXX024 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(now)) + entry_guards_dirty = 1; + + update_node_guard_status(); + } + digestmap_free(added_by, tor_free_); + return *msg ? -1 : 0; +} + +/** Our list of entry guards has changed, or some element of one + * of our entry guards has changed. Write the changes to disk within + * the next few minutes. + */ +void +entry_guards_changed(void) +{ + time_t when; + entry_guards_dirty = 1; + + /* or_state_save() will call entry_guards_update_state(). */ + when = get_options()->AvoidDiskWrites ? time(NULL) + 3600 : time(NULL)+600; + or_state_mark_dirty(get_or_state(), when); +} + +/** If the entry guard info has not changed, do nothing and return. + * Otherwise, free the EntryGuards piece of <b>state</b> and create + * a new one out of the global entry_guards list, and then mark + * <b>state</b> dirty so it will get saved to disk. + */ +void +entry_guards_update_state(or_state_t *state) +{ + config_line_t **next, *line; + if (! entry_guards_dirty) + return; + + config_free_lines(state->EntryGuards); + next = &state->EntryGuards; + *next = NULL; + if (!entry_guards) + entry_guards = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + char dbuf[HEX_DIGEST_LEN+1]; + if (!e->made_contact) + continue; /* don't write this one to disk */ + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("EntryGuard"); + base16_encode(dbuf, sizeof(dbuf), e->identity, DIGEST_LEN); + tor_asprintf(&line->value, "%s %s %sDirCache", e->nickname, dbuf, + e->is_dir_cache ? "" : "No"); + next = &(line->next); + if (e->unreachable_since) { + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("EntryGuardDownSince"); + line->value = tor_malloc(ISO_TIME_LEN+1+ISO_TIME_LEN+1); + format_iso_time(line->value, e->unreachable_since); + if (e->last_attempted) { + line->value[ISO_TIME_LEN] = ' '; + format_iso_time(line->value+ISO_TIME_LEN+1, e->last_attempted); + } + next = &(line->next); + } + if (e->bad_since) { + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("EntryGuardUnlistedSince"); + line->value = tor_malloc(ISO_TIME_LEN+1); + format_iso_time(line->value, e->bad_since); + next = &(line->next); + } + if (e->chosen_on_date && e->chosen_by_version && + !strchr(e->chosen_by_version, ' ')) { + char d[HEX_DIGEST_LEN+1]; + char t[ISO_TIME_LEN+1]; + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("EntryGuardAddedBy"); + base16_encode(d, sizeof(d), e->identity, DIGEST_LEN); + format_iso_time(t, e->chosen_on_date); + tor_asprintf(&line->value, "%s %s %s", + d, e->chosen_by_version, t); + next = &(line->next); + } + if (e->circ_attempts > 0) { + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("EntryGuardPathBias"); + /* In the long run: circuit_success ~= successful_circuit_close + + * collapsed_circuits + + * unusable_circuits */ + tor_asprintf(&line->value, "%f %f %f %f %f %f", + e->circ_attempts, e->circ_successes, + pathbias_get_close_success_count(e), + e->collapsed_circuits, + e->unusable_circuits, e->timeouts); + next = &(line->next); + } + if (e->use_attempts > 0) { + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("EntryGuardPathUseBias"); + + tor_asprintf(&line->value, "%f %f", + e->use_attempts, + pathbias_get_use_success_count(e)); + next = &(line->next); + } + + } SMARTLIST_FOREACH_END(e); + if (!get_options()->AvoidDiskWrites) + or_state_mark_dirty(get_or_state(), 0); + entry_guards_dirty = 0; +} + +/** If <b>question</b> is the string "entry-guards", then dump + * to *<b>answer</b> a newly allocated string describing all of + * the nodes in the global entry_guards list. See control-spec.txt + * for details. + * For backward compatibility, we also handle the string "helper-nodes". + * */ +int +getinfo_helper_entry_guards(control_connection_t *conn, + const char *question, char **answer, + const char **errmsg) +{ + (void) conn; + (void) errmsg; + + if (!strcmp(question,"entry-guards") || + !strcmp(question,"helper-nodes")) { + smartlist_t *sl = smartlist_new(); + char tbuf[ISO_TIME_LEN+1]; + char nbuf[MAX_VERBOSE_NICKNAME_LEN+1]; + if (!entry_guards) + entry_guards = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + const char *status = NULL; + time_t when = 0; + const node_t *node; + + if (!e->made_contact) { + status = "never-connected"; + } else if (e->bad_since) { + when = e->bad_since; + status = "unusable"; + } else { + status = "up"; + } + + node = node_get_by_id(e->identity); + if (node) { + node_get_verbose_nickname(node, nbuf); + } else { + nbuf[0] = '$'; + base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN); + /* 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); + smartlist_add_asprintf(sl, "%s %s %s\n", nbuf, status, tbuf); + } else { + smartlist_add_asprintf(sl, "%s %s\n", nbuf, status); + } + } SMARTLIST_FOREACH_END(e); + *answer = smartlist_join_strings(sl, "", 0, NULL); + SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); + smartlist_free(sl); + } + return 0; +} + +/** A list of configured bridges. Whenever we actually get a descriptor + * for one, we add it as an entry guard. Note that the order of bridges + * in this list does not necessarily correspond to the order of bridges + * in the torrc. */ +static smartlist_t *bridge_list = NULL; + +/** Mark every entry of the bridge list to be removed on our next call to + * sweep_bridge_list unless it has first been un-marked. */ +void +mark_bridge_list(void) +{ + if (!bridge_list) + bridge_list = smartlist_new(); + SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, + b->marked_for_removal = 1); +} + +/** Remove every entry of the bridge list that was marked with + * mark_bridge_list if it has not subsequently been un-marked. */ +void +sweep_bridge_list(void) +{ + if (!bridge_list) + bridge_list = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) { + if (b->marked_for_removal) { + SMARTLIST_DEL_CURRENT(bridge_list, b); + bridge_free(b); + } + } SMARTLIST_FOREACH_END(b); +} + +/** Initialize the bridge list to empty, creating it if needed. */ +static void +clear_bridge_list(void) +{ + if (!bridge_list) + bridge_list = smartlist_new(); + SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b)); + smartlist_clear(bridge_list); +} + +/** Free the bridge <b>bridge</b>. */ +static void +bridge_free(bridge_info_t *bridge) +{ + if (!bridge) + return; + + tor_free(bridge->transport_name); + tor_free(bridge); +} + +/** If we have a bridge configured whose digest matches <b>digest</b>, or a + * bridge with no known digest whose address matches any of the + * tor_addr_port_t's in <b>orports</b>, return that bridge. Else return + * NULL. */ +static bridge_info_t * +get_configured_bridge_by_orports_digest(const char *digest, + const smartlist_t *orports) +{ + if (!bridge_list) + return NULL; + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) + { + if (tor_digest_is_zero(bridge->identity)) { + SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, ap) + { + if (tor_addr_compare(&bridge->addr, &ap->addr, CMP_EXACT) == 0 && + bridge->port == ap->port) + return bridge; + } + SMARTLIST_FOREACH_END(ap); + } + if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN)) + return bridge; + } + SMARTLIST_FOREACH_END(bridge); + return NULL; +} + +/** If we have a bridge configured whose digest matches <b>digest</b>, or a + * bridge with no known digest whose address matches <b>addr</b>:<b>/port</b>, + * return that bridge. Else return NULL. */ +static bridge_info_t * +get_configured_bridge_by_addr_port_digest(const 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_compare(&bridge->addr, addr, CMP_EXACT) && + bridge->port == port) + return bridge; + if (digest && tor_memeq(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(const routerinfo_t *ri) +{ + bridge_info_t *bi = NULL; + smartlist_t *orports = router_get_all_orports(ri); + bi = get_configured_bridge_by_orports_digest(ri->cache_info.identity_digest, + orports); + SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p)); + smartlist_free(orports); + return bi; +} + +/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */ +int +routerinfo_is_a_configured_bridge(const routerinfo_t *ri) +{ + return get_configured_bridge_by_routerinfo(ri) ? 1 : 0; +} + +/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */ +int +node_is_a_configured_bridge(const node_t *node) +{ + int retval = 0; + smartlist_t *orports = node_get_all_orports(node); + retval = get_configured_bridge_by_orports_digest(node->identity, + orports) != NULL; + SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p)); + smartlist_free(orports); + return retval; +} + +/** 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(const 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)) { + char *transport_info = NULL; + const char *transport_name = + find_transport_name_by_bridge_addrport(addr, port); + if (transport_name) + tor_asprintf(&transport_info, " (with transport '%s')", transport_name); + + memcpy(bridge->identity, digest, DIGEST_LEN); + log_notice(LD_DIR, "Learned fingerprint %s for bridge %s%s.", + hex_str(digest, DIGEST_LEN), fmt_addrport(addr, port), + transport_info ? transport_info : ""); + tor_free(transport_info); + } +} + +/** Return true if <b>bridge</b> has the same identity digest as + * <b>digest</b>. If <b>digest</b> is NULL, it matches + * bridges with unspecified identity digests. */ +static int +bridge_has_digest(const bridge_info_t *bridge, const char *digest) +{ + if (digest) + return tor_memeq(digest, bridge->identity, DIGEST_LEN); + else + return tor_digest_is_zero(bridge->identity); +} + +/** We are about to add a new bridge at <b>addr</b>:<b>port</b>, with optional + * <b>digest</b> and <b>transport_name</b>. Mark for removal any previously + * existing bridge with the same address and port, and warn the user as + * appropriate. + */ +static void +bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port, + const char *digest, const char *transport_name) +{ + /* Iterate the already-registered bridge list: + + If you find a bridge with the same adress and port, mark it for + removal. It doesn't make sense to have two active bridges with + the same IP:PORT. If the bridge in question has a different + digest or transport than <b>digest</b>/<b>transport_name</b>, + it's probably a misconfiguration and we should warn the user. + */ + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) { + if (bridge->marked_for_removal) + continue; + + if (tor_addr_eq(&bridge->addr, addr) && (bridge->port == port)) { + + bridge->marked_for_removal = 1; + + if (!bridge_has_digest(bridge, digest) || + strcmp_opt(bridge->transport_name, transport_name)) { + /* warn the user */ + char *bridge_description_new, *bridge_description_old; + tor_asprintf(&bridge_description_new, "%s:%s:%s", + fmt_addrport(addr, port), + digest ? hex_str(digest, DIGEST_LEN) : "", + transport_name ? transport_name : ""); + tor_asprintf(&bridge_description_old, "%s:%s:%s", + fmt_addrport(&bridge->addr, bridge->port), + tor_digest_is_zero(bridge->identity) ? + "" : hex_str(bridge->identity,DIGEST_LEN), + bridge->transport_name ? bridge->transport_name : ""); + + log_warn(LD_GENERAL,"Tried to add bridge '%s', but we found a conflict" + " with the already registered bridge '%s'. We will discard" + " the old bridge and keep '%s'. If this is not what you" + " wanted, please change your configuration file accordingly.", + bridge_description_new, bridge_description_old, + bridge_description_new); + + tor_free(bridge_description_new); + tor_free(bridge_description_old); + } + } + } SMARTLIST_FOREACH_END(bridge); +} + +/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b> + * is set, it tells us the identity key too. If we already had the + * bridge in our list, unmark it, and don't actually add anything new. + * If <b>transport_name</b> is non-NULL - the bridge is associated with a + * pluggable transport - we assign the transport to the bridge. */ +void +bridge_add_from_config(const tor_addr_t *addr, uint16_t port, + const char *digest, const char *transport_name) +{ + bridge_info_t *b; + + bridge_resolve_conflicts(addr, port, digest, transport_name); + + b = tor_malloc_zero(sizeof(bridge_info_t)); + tor_addr_copy(&b->addr, addr); + b->port = port; + if (digest) + memcpy(b->identity, digest, DIGEST_LEN); + if (transport_name) + b->transport_name = tor_strdup(transport_name); + b->fetch_status.schedule = DL_SCHED_BRIDGE; + if (!bridge_list) + bridge_list = smartlist_new(); + + smartlist_add(bridge_list, b); +} + +/** Return true iff <b>routerset</b> contains the bridge <b>bridge</b>. */ +static int +routerset_contains_bridge(const routerset_t *routerset, + const bridge_info_t *bridge) +{ + int result; + extend_info_t *extinfo; + tor_assert(bridge); + if (!routerset) + return 0; + + extinfo = extend_info_new( + NULL, bridge->identity, NULL, NULL, &bridge->addr, bridge->port); + result = routerset_contains_extendinfo(routerset, extinfo); + extend_info_free(extinfo); + return result; +} + +/** If <b>digest</b> is one of our known bridges, return it. */ +static bridge_info_t * +find_bridge_by_digest(const char *digest) +{ + SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, + { + if (tor_memeq(bridge->identity, digest, DIGEST_LEN)) + return bridge; + }); + return NULL; +} + +/** Given the <b>addr</b> and <b>port</b> of a bridge, if that bridge + * supports a pluggable transport, return its name. Otherwise, return + * NULL. */ +const char * +find_transport_name_by_bridge_addrport(const tor_addr_t *addr, uint16_t port) +{ + if (!bridge_list) + return NULL; + + SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) { + if (tor_addr_eq(&bridge->addr, addr) && + (bridge->port == port)) + return bridge->transport_name; + } SMARTLIST_FOREACH_END(bridge); + + return NULL; +} + +/** If <b>addr</b> and <b>port</b> match the address and port of a + * bridge of ours that uses pluggable transports, place its transport + * in <b>transport</b>. + * + * Return 0 on success (found a transport, or found a bridge with no + * transport, or found no bridge); return -1 if we should be using a + * transport, but the transport could not be found. + */ +int +find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, + const transport_t **transport) +{ + *transport = NULL; + if (!bridge_list) + return 0; + + SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) { + if (tor_addr_eq(&bridge->addr, addr) && + (bridge->port == port)) { /* bridge matched */ + if (bridge->transport_name) { /* it also uses pluggable transports */ + *transport = transport_get_by_name(bridge->transport_name); + if (*transport == NULL) { /* it uses pluggable transports, but + the transport could not be found! */ + return -1; + } + return 0; + } else { /* bridge matched, but it doesn't use transports. */ + break; + } + } + } SMARTLIST_FOREACH_END(bridge); + + *transport = NULL; + return 0; +} + +/** We need to ask <b>bridge</b> for its server descriptor. */ +static void +launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) +{ + char *address; + const or_options_t *options = get_options(); + + if (connection_get_by_type_addr_port_purpose( + CONN_TYPE_DIR, &bridge->addr, bridge->port, + DIR_PURPOSE_FETCH_SERVERDESC)) + return; /* it's already on the way */ + + if (routerset_contains_bridge(options->ExcludeNodes, bridge)) { + download_status_mark_impossible(&bridge->fetch_status); + log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.", + safe_str_client(fmt_and_decorate_addr(&bridge->addr))); + return; + } + + address = tor_dup_addr(&bridge->addr); + + directory_initiate_command(address, &bridge->addr, + bridge->port, 0/*no dirport*/, + bridge->identity, + DIR_PURPOSE_FETCH_SERVERDESC, + ROUTER_PURPOSE_BRIDGE, + DIRIND_ONEHOP, "authority.z", NULL, 0, 0); + tor_free(address); +} + +/** Fetching the bridge descriptor from the bridge authority returned a + * "not found". Fall back to trying a direct fetch. */ +void +retry_bridge_descriptor_fetch_directly(const char *digest) +{ + bridge_info_t *bridge = find_bridge_by_digest(digest); + if (!bridge) + return; /* not found? oh well. */ + + launch_direct_bridge_descriptor_fetch(bridge); +} + +/** For each bridge in our list for which we don't currently have a + * descriptor, fetch a new copy of its descriptor -- either directly + * from the bridge or via a bridge authority. */ +void +fetch_bridge_descriptors(const or_options_t *options, time_t now) +{ + int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO); + int ask_bridge_directly; + int can_use_bridge_authority; + + if (!bridge_list) + return; + + /* If we still have unconfigured managed proxies, don't go and + connect to a bridge. */ + if (pt_proxies_configuration_pending()) + return; + + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) + { + if (!download_status_is_ready(&bridge->fetch_status, now, + IMPOSSIBLE_TO_DOWNLOAD)) + continue; /* don't bother, no need to retry yet */ + if (routerset_contains_bridge(options->ExcludeNodes, bridge)) { + download_status_mark_impossible(&bridge->fetch_status); + log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.", + safe_str_client(fmt_and_decorate_addr(&bridge->addr))); + continue; + } + + /* schedule another fetch as if this one will fail, in case it does */ + download_status_failed(&bridge->fetch_status, 0); + + can_use_bridge_authority = !tor_digest_is_zero(bridge->identity) && + num_bridge_auths; + ask_bridge_directly = !can_use_bridge_authority || + !options->UpdateBridgesFromAuthority; + log_debug(LD_DIR, "ask_bridge_directly=%d (%d, %d, %d)", + ask_bridge_directly, tor_digest_is_zero(bridge->identity), + !options->UpdateBridgesFromAuthority, !num_bridge_auths); + + if (ask_bridge_directly && + !fascist_firewall_allows_address_or(&bridge->addr, bridge->port)) { + log_notice(LD_DIR, "Bridge at '%s' isn't reachable by our " + "firewall policy. %s.", + fmt_addrport(&bridge->addr, bridge->port), + can_use_bridge_authority ? + "Asking bridge authority instead" : "Skipping"); + if (can_use_bridge_authority) + ask_bridge_directly = 0; + else + continue; + } + + if (ask_bridge_directly) { + /* we need to ask the bridge itself for its descriptor. */ + launch_direct_bridge_descriptor_fetch(bridge); + } else { + /* We have a digest and we want to ask an authority. We could + * combine all the requests into one, but that may give more + * hints to the bridge authority than we want to give. */ + char resource[10 + HEX_DIGEST_LEN]; + memcpy(resource, "fp/", 3); + base16_encode(resource+3, HEX_DIGEST_LEN+1, + bridge->identity, DIGEST_LEN); + memcpy(resource+3+HEX_DIGEST_LEN, ".z", 3); + log_info(LD_DIR, "Fetching bridge info '%s' from bridge authority.", + resource); + directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC, + ROUTER_PURPOSE_BRIDGE, resource, 0); + } + } + SMARTLIST_FOREACH_END(bridge); +} + +/** If our <b>bridge</b> is configured to be a different address than + * the bridge gives in <b>node</b>, rewrite the routerinfo + * we received to use the address we meant to use. Now we handle + * multihomed bridges better. + */ +static void +rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node) +{ + /* XXXX move this function. */ + /* XXXX overridden addresses should really live in the node_t, so that the + * routerinfo_t and the microdesc_t can be immutable. But we can only + * do that safely if we know that no function that connects to an OR + * does so through an address from any source other than node_get_addr(). + */ + tor_addr_t addr; + + if (node->ri) { + routerinfo_t *ri = node->ri; + tor_addr_from_ipv4h(&addr, ri->addr); + + if ((!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) && + bridge->port == ri->or_port) || + (!tor_addr_compare(&bridge->addr, &ri->ipv6_addr, CMP_EXACT) && + bridge->port == ri->ipv6_orport)) { + /* they match, so no need to do anything */ + } else { + if (tor_addr_family(&bridge->addr) == AF_INET) { + ri->addr = tor_addr_to_ipv4h(&bridge->addr); + tor_free(ri->address); + ri->address = tor_dup_ip(ri->addr); + ri->or_port = bridge->port; + log_info(LD_DIR, + "Adjusted bridge routerinfo for '%s' to match configured " + "address %s:%d.", + ri->nickname, ri->address, ri->or_port); + } else if (tor_addr_family(&bridge->addr) == AF_INET6) { + tor_addr_copy(&ri->ipv6_addr, &bridge->addr); + ri->ipv6_orport = bridge->port; + log_info(LD_DIR, + "Adjusted bridge routerinfo for '%s' to match configured " + "address %s.", + ri->nickname, fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport)); + } else { + log_err(LD_BUG, "Address family not supported: %d.", + tor_addr_family(&bridge->addr)); + return; + } + } + + /* Mark which address to use based on which bridge_t we got. */ + node->ipv6_preferred = (tor_addr_family(&bridge->addr) == AF_INET6 && + !tor_addr_is_null(&node->ri->ipv6_addr)); + + /* XXXipv6 we lack support for falling back to another address for + the same relay, warn the user */ + if (!tor_addr_is_null(&ri->ipv6_addr)) { + tor_addr_port_t ap; + node_get_pref_orport(node, &ap); + log_notice(LD_CONFIG, + "Bridge '%s' has both an IPv4 and an IPv6 address. " + "Will prefer using its %s address (%s).", + ri->nickname, + tor_addr_family(&ap.addr) == AF_INET6 ? "IPv6" : "IPv4", + fmt_addrport(&ap.addr, ap.port)); + } + } + if (node->rs) { + routerstatus_t *rs = node->rs; + tor_addr_from_ipv4h(&addr, rs->addr); + + if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) && + bridge->port == rs->or_port) { + /* they match, so no need to do anything */ + } else { + rs->addr = tor_addr_to_ipv4h(&bridge->addr); + rs->or_port = bridge->port; + log_info(LD_DIR, + "Adjusted bridge routerstatus for '%s' to match " + "configured address %s.", + rs->nickname, fmt_addrport(&bridge->addr, rs->or_port)); + } + } +} + +/** We just learned a descriptor for a bridge. See if that + * digest is in our entry guard list, and add it if not. */ +void +learned_bridge_descriptor(routerinfo_t *ri, int from_cache) +{ + tor_assert(ri); + tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE); + if (get_options()->UseBridges) { + int first = !any_bridge_descriptors_known(); + bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri); + time_t now = time(NULL); + router_set_status(ri->cache_info.identity_digest, 1); + + if (bridge) { /* if we actually want to use this one */ + node_t *node; + /* it's here; schedule its re-fetch for a long time from now. */ + if (!from_cache) + download_status_reset(&bridge->fetch_status); + + node = node_get_mutable_by_id(ri->cache_info.identity_digest); + tor_assert(node); + rewrite_node_address_for_bridge(bridge, node); + add_an_entry_guard(node, 1, 1, 0, 0); + + log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname, + from_cache ? "cached" : "fresh", router_describe(ri)); + /* set entry->made_contact so if it goes down we don't drop it from + * our entry node list */ + entry_guard_register_connect_status(ri->cache_info.identity_digest, + 1, 0, now); + if (first) { + /* XXXX apparently, this is never called. See bug #9229. */ + routerlist_retry_directory_downloads(now); + } + + update_networkstatus_downloads(now); + } + } +} + +/** Return 1 if any of our entry guards have descriptors that + * are marked with purpose 'bridge' and are running. Else return 0. + * + * We use this function to decide if we're ready to start building + * circuits through our bridges, or if we need to wait until the + * directory "server/authority" requests finish. */ +int +any_bridge_descriptors_known(void) +{ + tor_assert(get_options()->UseBridges); + return choose_random_entry(NULL) != NULL; +} + +/** Return 1 if there are any directory conns fetching bridge descriptors + * that aren't marked for close. We use this to guess if we should tell + * the controller that we have a problem. */ +int +any_pending_bridge_descriptor_fetches(void) +{ + smartlist_t *conns = get_connection_array(); + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { + if (conn->type == CONN_TYPE_DIR && + conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC && + TO_DIR_CONN(conn)->router_purpose == ROUTER_PURPOSE_BRIDGE && + !conn->marked_for_close && + conn->linked && + conn->linked_conn && !conn->linked_conn->marked_for_close) { + log_debug(LD_DIR, "found one: %s", conn->address); + return 1; + } + } SMARTLIST_FOREACH_END(conn); + return 0; +} + +/** 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 +entries_retry_helper(const or_options_t *options, int act) +{ + const node_t *node; + int any_known = 0; + int any_running = 0; + int need_bridges = options->UseBridges != 0; + if (!entry_guards) + entry_guards = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + node = node_get_by_id(e->identity); + if (node && node_has_descriptor(node) && + node_is_bridge(node) == need_bridges) { + any_known = 1; + if (node->is_running) + any_running = 1; /* some entry is both known and running */ + else if (act) { + /* Mark all current connections to this OR as unhealthy, since + * 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(node->identity, 1); + + /* mark this entry node for retry */ + router_set_status(node->identity, 1); + e->can_retry = 1; + e->bad_since = 0; + } + } + } SMARTLIST_FOREACH_END(e); + log_debug(LD_DIR, "%d: any_known %d, any_running %d", + act, any_known, any_running); + return any_known && !any_running; +} + +/** Do we know any descriptors for our bridges / entrynodes, and are + * all the ones we have descriptors for down? */ +int +entries_known_but_down(const or_options_t *options) +{ + tor_assert(entry_list_is_constrained(options)); + return entries_retry_helper(options, 0); +} + +/** Mark all down known bridges / entrynodes up. */ +void +entries_retry_all(const or_options_t *options) +{ + tor_assert(entry_list_is_constrained(options)); + entries_retry_helper(options, 1); +} + +/** Return true if at least one of our bridges runs a Tor version that can + * provide microdescriptors to us. If not, we'll fall back to asking for + * full descriptors. */ +int +any_bridge_supports_microdescriptors(void) +{ + const node_t *node; + if (!get_options()->UseBridges || !entry_guards) + return 0; + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + node = node_get_by_id(e->identity); + if (node && node->is_running && + node_is_bridge(node) && node_is_a_configured_bridge(node) && + node_understands_microdescriptors(node)) { + /* This is one of our current bridges, and we know enough about + * it to know that it will be able to answer our microdescriptor + * questions. */ + return 1; + } + } SMARTLIST_FOREACH_END(e); + return 0; +} + +/** Release all storage held by the list of entry guards and related + * memory structs. */ +void +entry_guards_free_all(void) +{ + if (entry_guards) { + SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, + entry_guard_free(e)); + smartlist_free(entry_guards); + entry_guards = NULL; + } + clear_bridge_list(); + smartlist_free(bridge_list); + bridge_list = NULL; + circuit_build_times_free_timeouts(&circ_times); +} + diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h new file mode 100644 index 0000000000..52b8dc00e4 --- /dev/null +++ b/src/or/entrynodes.h @@ -0,0 +1,127 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file guardnodes.h + * \brief Header file for circuitbuild.c. + **/ + +#ifndef TOR_ENTRYNODES_H +#define TOR_ENTRYNODES_H + +#if 1 +/* XXXX NM I would prefer that all of this stuff be private to + * entrynodes.c. */ + +/** An entry_guard_t represents our information about a chosen long-term + * first hop, known as a "helper" node in the literature. We can't just + * use a node_t, since we want to remember these even when we + * don't have any directory info. */ +typedef struct entry_guard_t { + char nickname[MAX_NICKNAME_LEN+1]; + char identity[DIGEST_LEN]; + time_t chosen_on_date; /**< Approximately when was this guard added? + * "0" if we don't know. */ + char *chosen_by_version; /**< What tor version added this guard? NULL + * if we don't know. */ + unsigned int made_contact : 1; /**< 0 if we have never connected to this + * router, 1 if we have. */ + unsigned int can_retry : 1; /**< Should we retry connecting to this entry, + * in spite of having it marked as unreachable?*/ + unsigned int path_bias_noticed : 1; /**< Did we alert the user about path + * bias for this node already? */ + unsigned int path_bias_warned : 1; /**< Did we alert the user about path bias + * for this node already? */ + unsigned int path_bias_extreme : 1; /**< Did we alert the user about path + * bias for this node already? */ + unsigned int path_bias_disabled : 1; /**< Have we disabled this node because + * of path bias issues? */ + unsigned int path_bias_use_noticed : 1; /**< Did we alert the user about path + * use bias for this node already? */ + unsigned int path_bias_use_extreme : 1; /**< Did we alert the user about path + * use bias for this node already? */ + unsigned int is_dir_cache : 1; /**< Is this node a directory cache? */ + time_t bad_since; /**< 0 if this guard is currently usable, or the time at + * which it was observed to become (according to the + * directory or the user configuration) unusable. */ + time_t unreachable_since; /**< 0 if we can connect to this guard, or the + * time at which we first noticed we couldn't + * connect to it. */ + time_t last_attempted; /**< 0 if we can connect to this guard, or the time + * at which we last failed to connect to it. */ + + double circ_attempts; /**< Number of circuits this guard has "attempted" */ + double circ_successes; /**< Number of successfully built circuits using + * this guard as first hop. */ + double successful_circuits_closed; /**< Number of circuits that carried + * streams successfully. */ + double collapsed_circuits; /**< Number of fully built circuits that were + * remotely closed before any streams were + * attempted. */ + double unusable_circuits; /**< Number of circuits for which streams were + * attempted, but none succeeded. */ + double timeouts; /**< Number of 'right-censored' circuit timeouts for this + * guard. */ + double use_attempts; /**< Number of circuits we tried to use with streams */ + double use_successes; /**< Number of successfully used circuits using + * this guard as first hop. */ +} entry_guard_t; + +entry_guard_t *entry_guard_get_by_id_digest(const char *digest); +void entry_guards_changed(void); +const smartlist_t *get_entry_guards(void); +int num_live_entry_guards(int for_directory); + +#endif + +void entry_guards_compute_status(const or_options_t *options, time_t now); +int entry_guard_register_connect_status(const char *digest, int succeeded, + int mark_relay_status, time_t now); +void entry_nodes_should_be_added(void); +int entry_list_is_constrained(const or_options_t *options); +const node_t *choose_random_entry(cpath_build_state_t *state); +const node_t *choose_random_dirguard(dirinfo_type_t t); +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 mark_bridge_list(void); +void sweep_bridge_list(void); + +int routerinfo_is_a_configured_bridge(const routerinfo_t *ri); +int node_is_a_configured_bridge(const node_t *node); +void learned_router_identity(const tor_addr_t *addr, uint16_t port, + const char *digest); +void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, + const char *digest, + const char *transport_name); +void retry_bridge_descriptor_fetch_directly(const char *digest); +void fetch_bridge_descriptors(const or_options_t *options, time_t now); +void learned_bridge_descriptor(routerinfo_t *ri, int from_cache); +int any_bridge_descriptors_known(void); +int any_pending_bridge_descriptor_fetches(void); +int entries_known_but_down(const or_options_t *options); +void entries_retry_all(const or_options_t *options); + +int any_bridge_supports_microdescriptors(void); + +void entry_guards_free_all(void); + +const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr, + uint16_t port); +struct transport_t; +int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, + const struct transport_t **transport); + +int validate_pluggable_transports_config(void); + +double pathbias_get_close_success_count(entry_guard_t *guard); +double pathbias_get_use_success_count(entry_guard_t *guard); + +#endif + diff --git a/src/or/eventdns_tor.h b/src/or/eventdns_tor.h index 4c40b3524b..69662281bc 100644 --- a/src/or/eventdns_tor.h +++ b/src/or/eventdns_tor.h @@ -1,6 +1,9 @@ -/* Copyright (c) 2007-2012, The Tor Project, Inc. */ +/* Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#ifndef TOR_EVENTDNS_TOR_H +#define TOR_EVENTDNS_TOR_H + #include "orconfig.h" #define DNS_USE_OPENSSL_FOR_ID #ifndef HAVE_UINT @@ -18,3 +21,5 @@ typedef unsigned char u_char; #include "util.h" #include "compat.h" +#endif + diff --git a/src/or/fp_pair.c b/src/or/fp_pair.c new file mode 100644 index 0000000000..4d8a835c83 --- /dev/null +++ b/src/or/fp_pair.c @@ -0,0 +1,308 @@ +/* Copyright (c) 2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "fp_pair.h" + +/* Define fp_pair_map_t structures */ + +struct fp_pair_map_entry_s { + HT_ENTRY(fp_pair_map_entry_s) node; + void *val; + fp_pair_t key; +}; + +struct fp_pair_map_s { + HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_s) head; +}; + +/* + * Hash function and equality checker for fp_pair_map_t + */ + +/** Compare fp_pair_entry_t objects by key value. */ +static INLINE int +fp_pair_map_entries_eq(const fp_pair_map_entry_t *a, + const fp_pair_map_entry_t *b) +{ + return tor_memeq(&(a->key), &(b->key), sizeof(fp_pair_t)); +} + +/** Return a hash value for an fp_pair_entry_t. */ +static INLINE unsigned int +fp_pair_map_entry_hash(const fp_pair_map_entry_t *a) +{ + const uint32_t *p; + unsigned int hash; + + p = (const uint32_t *)(a->key.first); + /* Hashes are 20 bytes long, so 5 times uint32_t */ + hash = p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4]; + /* Now XOR in the second fingerprint */ + p = (const uint32_t *)(a->key.second); + hash ^= p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4]; + + return hash; +} + +/* + * Hash table functions for fp_pair_map_t + */ + +HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_s, node, + fp_pair_map_entry_hash, fp_pair_map_entries_eq) +HT_GENERATE(fp_pair_map_impl, fp_pair_map_entry_s, node, + fp_pair_map_entry_hash, fp_pair_map_entries_eq, + 0.6, tor_malloc, tor_realloc, tor_free) + +/** Constructor to create a new empty map from fp_pair_t to void * + */ + +fp_pair_map_t * +fp_pair_map_new(void) +{ + fp_pair_map_t *result; + + result = tor_malloc(sizeof(fp_pair_map_t)); + HT_INIT(fp_pair_map_impl, &result->head); + return result; +} + +/** Set the current value for key to val; returns the previous + * value for key if one was set, or NULL if one was not. + */ + +void * +fp_pair_map_set(fp_pair_map_t *map, const fp_pair_t *key, void *val) +{ + fp_pair_map_entry_t *resolve; + fp_pair_map_entry_t search; + void *oldval; + + tor_assert(map); + tor_assert(key); + tor_assert(val); + + memcpy(&(search.key), key, sizeof(*key)); + resolve = HT_FIND(fp_pair_map_impl, &(map->head), &search); + if (resolve) { + oldval = resolve->val; + resolve->val = val; + } else { + resolve = tor_malloc_zero(sizeof(fp_pair_map_entry_t)); + memcpy(&(resolve->key), key, sizeof(*key)); + resolve->val = val; + HT_INSERT(fp_pair_map_impl, &(map->head), resolve); + oldval = NULL; + } + + return oldval; +} + +/** Set the current value for the key (first, second) to val; returns + * the previous value for key if one was set, or NULL if one was not. + */ + +void * +fp_pair_map_set_by_digests(fp_pair_map_t *map, + const char *first, const char *second, + void *val) +{ + fp_pair_t k; + + tor_assert(first); + tor_assert(second); + + memcpy(k.first, first, DIGEST_LEN); + memcpy(k.second, second, DIGEST_LEN); + + return fp_pair_map_set(map, &k, val); +} + +/** Return the current value associated with key, or NULL if no value is set. + */ + +void * +fp_pair_map_get(const fp_pair_map_t *map, const fp_pair_t *key) +{ + fp_pair_map_entry_t *resolve; + fp_pair_map_entry_t search; + void *val = NULL; + + tor_assert(map); + tor_assert(key); + + memcpy(&(search.key), key, sizeof(*key)); + resolve = HT_FIND(fp_pair_map_impl, &(map->head), &search); + if (resolve) val = resolve->val; + + return val; +} + +/** Return the current value associated the key (first, second), or + * NULL if no value is set. + */ + +void * +fp_pair_map_get_by_digests(const fp_pair_map_t *map, + const char *first, const char *second) +{ + fp_pair_t k; + + tor_assert(first); + tor_assert(second); + + memcpy(k.first, first, DIGEST_LEN); + memcpy(k.second, second, DIGEST_LEN); + + return fp_pair_map_get(map, &k); +} + +/** Remove the value currently associated with key from the map. + * Return the value if one was set, or NULL if there was no entry for + * key. The caller must free any storage associated with the + * returned value. + */ + +void * +fp_pair_map_remove(fp_pair_map_t *map, const fp_pair_t *key) +{ + fp_pair_map_entry_t *resolve; + fp_pair_map_entry_t search; + void *val = NULL; + + tor_assert(map); + tor_assert(key); + + memcpy(&(search.key), key, sizeof(*key)); + resolve = HT_REMOVE(fp_pair_map_impl, &(map->head), &search); + if (resolve) { + val = resolve->val; + tor_free(resolve); + } + + return val; +} + +/** Remove all entries from map, and deallocate storage for those entries. + * If free_val is provided, it is invoked on every value in map. + */ + +void +fp_pair_map_free(fp_pair_map_t *map, void (*free_val)(void*)) +{ + fp_pair_map_entry_t **ent, **next, *this; + + if (map) { + for (ent = HT_START(fp_pair_map_impl, &(map->head)); + ent != NULL; ent = next) { + this = *ent; + next = HT_NEXT_RMV(fp_pair_map_impl, &(map->head), ent); + if (free_val) free_val(this->val); + tor_free(this); + } + tor_assert(HT_EMPTY(&(map->head))); + HT_CLEAR(fp_pair_map_impl, &(map->head)); + tor_free(map); + } +} + +/** Return true iff map has no entries. + */ + +int +fp_pair_map_isempty(const fp_pair_map_t *map) +{ + tor_assert(map); + + return HT_EMPTY(&(map->head)); +} + +/** Return the number of items in map. + */ + +int +fp_pair_map_size(const fp_pair_map_t *map) +{ + tor_assert(map); + + return HT_SIZE(&(map->head)); +} + +/** return an iterator pointing to the start of map. + */ + +fp_pair_map_iter_t * +fp_pair_map_iter_init(fp_pair_map_t *map) +{ + tor_assert(map); + + return HT_START(fp_pair_map_impl, &(map->head)); +} + +/** Advance iter a single step to the next entry of map, and return + * its new value. + */ + +fp_pair_map_iter_t * +fp_pair_map_iter_next(fp_pair_map_t *map, fp_pair_map_iter_t *iter) +{ + tor_assert(map); + tor_assert(iter); + + return HT_NEXT(fp_pair_map_impl, &(map->head), iter); +} + +/** Advance iter a single step to the next entry of map, removing the current + * entry, and return its new value. + */ + +fp_pair_map_iter_t * +fp_pair_map_iter_next_rmv(fp_pair_map_t *map, fp_pair_map_iter_t *iter) +{ + fp_pair_map_entry_t *rmv; + + tor_assert(map); + tor_assert(iter); + tor_assert(*iter); + + rmv = *iter; + iter = HT_NEXT_RMV(fp_pair_map_impl, &(map->head), iter); + tor_free(rmv); + + return iter; +} + +/** Set *key_out and *val_out to the current entry pointed to by iter. + */ + +void +fp_pair_map_iter_get(fp_pair_map_iter_t *iter, + fp_pair_t *key_out, void **val_out) +{ + tor_assert(iter); + tor_assert(*iter); + + if (key_out) memcpy(key_out, &((*iter)->key), sizeof(fp_pair_t)); + if (val_out) *val_out = (*iter)->val; +} + +/** Return true iff iter has advanced past the last entry of its map. + */ + +int +fp_pair_map_iter_done(fp_pair_map_iter_t *iter) +{ + return (iter == NULL); +} + +/** Assert if anything has gone wrong with the internal + * representation of map. + */ + +void +fp_pair_map_assert_ok(const fp_pair_map_t *map) +{ + tor_assert(!fp_pair_map_impl_HT_REP_IS_BAD_(&(map->head))); +} + diff --git a/src/or/fp_pair.h b/src/or/fp_pair.h new file mode 100644 index 0000000000..89f664a813 --- /dev/null +++ b/src/or/fp_pair.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file fp_pair.h + * \brief Header file for fp_pair.c. + **/ + +#ifndef _TOR_FP_PAIR_H +#define _TOR_FP_PAIR_H + +/* + * Declare fp_pair_map_t functions and structs + */ + +typedef struct fp_pair_map_entry_s fp_pair_map_entry_t; +typedef struct fp_pair_map_s fp_pair_map_t; +typedef fp_pair_map_entry_t *fp_pair_map_iter_t; + +fp_pair_map_t * fp_pair_map_new(void); +void * fp_pair_map_set(fp_pair_map_t *map, const fp_pair_t *key, void *val); +void * fp_pair_map_set_by_digests(fp_pair_map_t *map, + const char *first, const char *second, + void *val); +void * fp_pair_map_get(const fp_pair_map_t *map, const fp_pair_t *key); +void * fp_pair_map_get_by_digests(const fp_pair_map_t *map, + const char *first, const char *second); +void * fp_pair_map_remove(fp_pair_map_t *map, const fp_pair_t *key); +void fp_pair_map_free(fp_pair_map_t *map, void (*free_val)(void*)); +int fp_pair_map_isempty(const fp_pair_map_t *map); +int fp_pair_map_size(const fp_pair_map_t *map); +fp_pair_map_iter_t * fp_pair_map_iter_init(fp_pair_map_t *map); +fp_pair_map_iter_t * fp_pair_map_iter_next(fp_pair_map_t *map, + fp_pair_map_iter_t *iter); +fp_pair_map_iter_t * fp_pair_map_iter_next_rmv(fp_pair_map_t *map, + fp_pair_map_iter_t *iter); +void fp_pair_map_iter_get(fp_pair_map_iter_t *iter, + fp_pair_t *key_out, void **val_out); +int fp_pair_map_iter_done(fp_pair_map_iter_t *iter); +void fp_pair_map_assert_ok(const fp_pair_map_t *map); + +#undef DECLARE_MAP_FNS + +#endif + diff --git a/src/or/geoip.c b/src/or/geoip.c index 6b7cc82b82..e2e98e8ec4 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2012, The Tor Project, Inc. */ +/* Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -21,17 +21,23 @@ 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 { +/** An entry from the GeoIP IPv4 file: maps an IPv4 range to a country. */ +typedef struct geoip_ipv4_entry_t { uint32_t ip_low; /**< The lowest IP in the range, in host order */ uint32_t ip_high; /**< The highest IP in the range, in host order */ intptr_t country; /**< An index into geoip_countries */ -} geoip_entry_t; +} geoip_ipv4_entry_t; + +/** An entry from the GeoIP IPv6 file: maps an IPv6 range to a country. */ +typedef struct geoip_ipv6_entry_t { + struct in6_addr ip_low; /**< The lowest IP in the range, in host order */ + struct in6_addr ip_high; /**< The highest IP in the range, in host order */ + intptr_t country; /**< An index into geoip_countries */ +} geoip_ipv6_entry_t; /** A per-country record for GeoIP request history. */ typedef struct geoip_country_t { char countrycode[3]; - uint32_t n_v2_ns_requests; uint32_t n_v3_ns_requests; } geoip_country_t; @@ -41,45 +47,48 @@ static smartlist_t *geoip_countries = NULL; * The index is encoded in the pointer, and 1 is added so that NULL can mean * not found. */ static strmap_t *country_idxplus1_by_lc_code = NULL; -/** A list of all known geoip_entry_t, sorted by ip_low. */ -static smartlist_t *geoip_entries = NULL; +/** Lists of all known geoip_ipv4_entry_t and geoip_ipv6_entry_t, sorted + * by their respective ip_low. */ +static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL; -/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */ +/** SHA1 digest of the GeoIP files to include in extra-info descriptors. */ static char geoip_digest[DIGEST_LEN]; +static char geoip6_digest[DIGEST_LEN]; -/** Return the index of the <b>country</b>'s entry in the GeoIP DB - * if it is a valid 2-letter country code, otherwise return -1. - */ +/** Return the index of the <b>country</b>'s entry in the GeoIP + * country list if it is a valid 2-letter country code, otherwise + * return -1. */ country_t geoip_get_country(const char *country) { - void *_idxplus1; + void *idxplus1_; intptr_t idx; - _idxplus1 = strmap_get_lc(country_idxplus1_by_lc_code, country); - if (!_idxplus1) + idxplus1_ = strmap_get_lc(country_idxplus1_by_lc_code, country); + if (!idxplus1_) return -1; - idx = ((uintptr_t)_idxplus1)-1; + idx = ((uintptr_t)idxplus1_)-1; return (country_t)idx; } -/** Add an entry to the GeoIP table, mapping all IPs between <b>low</b> and - * <b>high</b>, inclusive, to the 2-letter country code <b>country</b>. - */ +/** Add an entry to a GeoIP table, mapping all IP addresses between <b>low</b> + * and <b>high</b>, inclusive, to the 2-letter country code <b>country</b>. */ static void -geoip_add_entry(uint32_t low, uint32_t high, const char *country) +geoip_add_entry(const tor_addr_t *low, const tor_addr_t *high, + const char *country) { intptr_t idx; - geoip_entry_t *ent; - void *_idxplus1; + void *idxplus1_; - if (high < low) + if (tor_addr_family(low) != tor_addr_family(high)) + return; + if (tor_addr_compare(high, low, CMP_EXACT) < 0) return; - _idxplus1 = strmap_get_lc(country_idxplus1_by_lc_code, country); + idxplus1_ = strmap_get_lc(country_idxplus1_by_lc_code, country); - if (!_idxplus1) { + if (!idxplus1_) { geoip_country_t *c = tor_malloc_zero(sizeof(geoip_country_t)); strlcpy(c->countrycode, country, sizeof(c->countrycode)); tor_strlower(c->countrycode); @@ -87,54 +96,103 @@ geoip_add_entry(uint32_t low, uint32_t high, const char *country) idx = smartlist_len(geoip_countries) - 1; strmap_set_lc(country_idxplus1_by_lc_code, country, (void*)(idx+1)); } else { - idx = ((uintptr_t)_idxplus1)-1; + idx = ((uintptr_t)idxplus1_)-1; } { geoip_country_t *c = smartlist_get(geoip_countries, idx); tor_assert(!strcasecmp(c->countrycode, country)); } - ent = tor_malloc_zero(sizeof(geoip_entry_t)); - ent->ip_low = low; - ent->ip_high = high; - ent->country = idx; - smartlist_add(geoip_entries, ent); + + if (tor_addr_family(low) == AF_INET) { + geoip_ipv4_entry_t *ent = tor_malloc_zero(sizeof(geoip_ipv4_entry_t)); + ent->ip_low = tor_addr_to_ipv4h(low); + ent->ip_high = tor_addr_to_ipv4h(high); + ent->country = idx; + smartlist_add(geoip_ipv4_entries, ent); + } else if (tor_addr_family(low) == AF_INET6) { + geoip_ipv6_entry_t *ent = tor_malloc_zero(sizeof(geoip_ipv6_entry_t)); + ent->ip_low = *tor_addr_to_in6(low); + ent->ip_high = *tor_addr_to_in6(high); + ent->country = idx; + smartlist_add(geoip_ipv6_entries, ent); + } } -/** Add an entry to the GeoIP table, parsing it from <b>line</b>. The - * format is as for geoip_load_file(). */ +/** Add an entry to the GeoIP table indicated by <b>family</b>, + * parsing it from <b>line</b>. The format is as for geoip_load_file(). */ /*private*/ int -geoip_parse_entry(const char *line) +geoip_parse_entry(const char *line, sa_family_t family) { - unsigned int low, high; - char b[3]; + tor_addr_t low_addr, high_addr; + char c[3]; + char *country = NULL; + if (!geoip_countries) init_geoip_countries(); - if (!geoip_entries) - geoip_entries = smartlist_new(); + if (family == AF_INET) { + if (!geoip_ipv4_entries) + geoip_ipv4_entries = smartlist_new(); + } else if (family == AF_INET6) { + if (!geoip_ipv6_entries) + geoip_ipv6_entries = smartlist_new(); + } else { + log_warn(LD_GENERAL, "Unsupported family: %d", family); + return -1; + } while (TOR_ISSPACE(*line)) ++line; if (*line == '#') return 0; - if (tor_sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) { - geoip_add_entry(low, high, b); - return 0; - } else if (tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) { - geoip_add_entry(low, high, b); - return 0; - } else { - log_warn(LD_GENERAL, "Unable to parse line from GEOIP file: %s", - escaped(line)); - return -1; + + if (family == AF_INET) { + unsigned int low, high; + if (tor_sscanf(line,"%u,%u,%2s", &low, &high, c) == 3 || + tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, c) == 3) { + tor_addr_from_ipv4h(&low_addr, low); + tor_addr_from_ipv4h(&high_addr, high); + } else + goto fail; + country = c; + } else { /* AF_INET6 */ + char buf[512]; + char *low_str, *high_str; + struct in6_addr low, high; + char *strtok_state; + strlcpy(buf, line, sizeof(buf)); + low_str = tor_strtok_r(buf, ",", &strtok_state); + if (!low_str) + goto fail; + high_str = tor_strtok_r(NULL, ",", &strtok_state); + if (!high_str) + goto fail; + country = tor_strtok_r(NULL, "\n", &strtok_state); + if (!country) + goto fail; + if (strlen(country) != 2) + goto fail; + if (tor_inet_pton(AF_INET6, low_str, &low) <= 0) + goto fail; + tor_addr_from_in6(&low_addr, &low); + if (tor_inet_pton(AF_INET6, high_str, &high) <= 0) + goto fail; + tor_addr_from_in6(&high_addr, &high); } + geoip_add_entry(&low_addr, &high_addr, country); + return 0; + + fail: + log_warn(LD_GENERAL, "Unable to parse line from GEOIP %s file: %s", + family == AF_INET ? "IPv4" : "IPv6", escaped(line)); + return -1; } /** Sorting helper: return -1, 1, or 0 based on comparison of two - * geoip_entry_t */ + * geoip_ipv4_entry_t */ static int -_geoip_compare_entries(const void **_a, const void **_b) +geoip_ipv4_compare_entries_(const void **_a, const void **_b) { - const geoip_entry_t *a = *_a, *b = *_b; + const geoip_ipv4_entry_t *a = *_a, *b = *_b; if (a->ip_low < b->ip_low) return -1; else if (a->ip_low > b->ip_low) @@ -144,13 +202,13 @@ _geoip_compare_entries(const void **_a, const void **_b) } /** bsearch helper: return -1, 1, or 0 based on comparison of an IP (a pointer - * to a uint32_t in host order) to a geoip_entry_t */ + * to a uint32_t in host order) to a geoip_ipv4_entry_t */ static int -_geoip_compare_key_to_entry(const void *_key, const void **_member) +geoip_ipv4_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; + const geoip_ipv4_entry_t *entry = *_member; if (addr < entry->ip_low) return -1; else if (addr > entry->ip_high) @@ -159,6 +217,34 @@ _geoip_compare_key_to_entry(const void *_key, const void **_member) return 0; } +/** Sorting helper: return -1, 1, or 0 based on comparison of two + * geoip_ipv6_entry_t */ +static int +geoip_ipv6_compare_entries_(const void **_a, const void **_b) +{ + const geoip_ipv6_entry_t *a = *_a, *b = *_b; + return fast_memcmp(a->ip_low.s6_addr, b->ip_low.s6_addr, + sizeof(struct in6_addr)); +} + +/** bsearch helper: return -1, 1, or 0 based on comparison of an IPv6 + * (a pointer to a in6_addr) to a geoip_ipv6_entry_t */ +static int +geoip_ipv6_compare_key_to_entry_(const void *_key, const void **_member) +{ + const struct in6_addr *addr = (struct in6_addr *)_key; + const geoip_ipv6_entry_t *entry = *_member; + + if (fast_memcmp(addr->s6_addr, entry->ip_low.s6_addr, + sizeof(struct in6_addr)) < 0) + return -1; + else if (fast_memcmp(addr->s6_addr, entry->ip_high.s6_addr, + sizeof(struct in6_addr)) > 0) + return 1; + else + return 0; +} + /** Return 1 if we should collect geoip stats on bridge users, and * include them in our extrainfo descriptor. Else return 0. */ int @@ -185,27 +271,35 @@ init_geoip_countries(void) 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. +/** Clear appropriate GeoIP database, based on <b>family</b>, and + * reload it from the file <b>filename</b>. Return 0 on success, -1 on + * failure. * - * Recognized line formats are: + * Recognized line formats for IPv4 are: * INTIPLOW,INTIPHIGH,CC * and * "INTIPLOW","INTIPHIGH","CC","CC3","COUNTRY NAME" * where INTIPLOW and INTIPHIGH are IPv4 addresses encoded as 4-byte unsigned * integers, and CC is a country code. * + * Recognized line format for IPv6 is: + * IPV6LOW,IPV6HIGH,CC + * where IPV6LOW and IPV6HIGH are IPv6 addresses and CC is a country code. + * * It also recognizes, and skips over, blank lines and lines that start * with '#' (comments). */ int -geoip_load_file(const char *filename, const or_options_t *options) +geoip_load_file(sa_family_t family, const char *filename) { FILE *f; const char *msg = ""; + const or_options_t *options = get_options(); int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO; crypto_digest_t *geoip_digest_env = NULL; - clear_geoip_db(); + + tor_assert(family == AF_INET || family == AF_INET6); + if (!(f = tor_fopen_cloexec(filename, "r"))) { log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s. %s", filename, msg); @@ -213,33 +307,51 @@ geoip_load_file(const char *filename, const or_options_t *options) } if (!geoip_countries) init_geoip_countries(); - if (geoip_entries) { - SMARTLIST_FOREACH(geoip_entries, geoip_entry_t *, e, tor_free(e)); - smartlist_free(geoip_entries); + + if (family == AF_INET) { + if (geoip_ipv4_entries) { + SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, e, + tor_free(e)); + smartlist_free(geoip_ipv4_entries); + } + geoip_ipv4_entries = smartlist_new(); + } else { /* AF_INET6 */ + if (geoip_ipv6_entries) { + SMARTLIST_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, e, + tor_free(e)); + smartlist_free(geoip_ipv6_entries); + } + geoip_ipv6_entries = smartlist_new(); } - geoip_entries = smartlist_new(); geoip_digest_env = crypto_digest_new(); - log_notice(LD_GENERAL, "Parsing GEOIP file %s.", filename); + + log_notice(LD_GENERAL, "Parsing GEOIP %s file %s.", + (family == AF_INET) ? "IPv4" : "IPv6", filename); while (!feof(f)) { char buf[512]; if (fgets(buf, (int)sizeof(buf), f) == NULL) break; crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf)); /* FFFF track full country name. */ - geoip_parse_entry(buf); + geoip_parse_entry(buf, family); } /*XXXX abort and return -1 if no entries/illformed?*/ fclose(f); - smartlist_sort(geoip_entries, _geoip_compare_entries); - - /* Okay, now we need to maybe change our mind about what is in which - * country. */ - refresh_all_country_info(); - - /* Remember file digest so that we can include it in our extra-info - * descriptors. */ - crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN); + /* Sort list and remember file digests so that we can include it in + * our extra-info descriptors. */ + if (family == AF_INET) { + smartlist_sort(geoip_ipv4_entries, geoip_ipv4_compare_entries_); + /* Okay, now we need to maybe change our mind about what is in + * which country. We do this for IPv4 only since that's what we + * store in node->country. */ + refresh_all_country_info(); + crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN); + } else { + /* AF_INET6 */ + smartlist_sort(geoip_ipv6_entries, geoip_ipv6_compare_entries_); + crypto_digest_get_digest(geoip_digest_env, geoip6_digest, DIGEST_LEN); + } crypto_digest_free(geoip_digest_env); return 0; @@ -252,12 +364,30 @@ geoip_load_file(const char *filename, const or_options_t *options) * geoip_get_country_name(). */ int -geoip_get_country_by_ip(uint32_t ipaddr) +geoip_get_country_by_ipv4(uint32_t ipaddr) { - geoip_entry_t *ent; - if (!geoip_entries) + geoip_ipv4_entry_t *ent; + if (!geoip_ipv4_entries) return -1; - ent = smartlist_bsearch(geoip_entries, &ipaddr, _geoip_compare_key_to_entry); + ent = smartlist_bsearch(geoip_ipv4_entries, &ipaddr, + geoip_ipv4_compare_key_to_entry_); + return ent ? (int)ent->country : 0; +} + +/** Given an IPv6 address, return a number representing the 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_ipv6(const struct in6_addr *addr) +{ + geoip_ipv6_entry_t *ent; + + if (!geoip_ipv6_entries) + return -1; + ent = smartlist_bsearch(geoip_ipv6_entries, addr, + geoip_ipv6_compare_key_to_entry_); return ent ? (int)ent->country : 0; } @@ -269,14 +399,16 @@ geoip_get_country_by_ip(uint32_t ipaddr) int geoip_get_country_by_addr(const tor_addr_t *addr) { - if (tor_addr_family(addr) != AF_INET) { - /*XXXX IP6 support ipv6 geoip.*/ + if (tor_addr_family(addr) == AF_INET) { + return geoip_get_country_by_ipv4(tor_addr_to_ipv4h(addr)); + } else if (tor_addr_family(addr) == AF_INET6) { + return geoip_get_country_by_ipv6(tor_addr_to_in6(addr)); + } else { return -1; } - return geoip_get_country_by_ip(tor_addr_to_ipv4h(addr)); } -/** Return the number of countries recognized by the GeoIP database. */ +/** Return the number of countries recognized by the GeoIP country list. */ int geoip_get_n_countries(void) { @@ -299,18 +431,28 @@ geoip_get_country_name(country_t num) /** Return true iff we have loaded a GeoIP database.*/ int -geoip_is_loaded(void) +geoip_is_loaded(sa_family_t family) { - return geoip_countries != NULL && geoip_entries != NULL; + tor_assert(family == AF_INET || family == AF_INET6); + if (geoip_countries == NULL) + return 0; + if (family == AF_INET) + return geoip_ipv4_entries != NULL; + else /* AF_INET6 */ + return geoip_ipv6_entries != NULL; } /** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The * result does not need to be deallocated, but will be overwritten by the * next call of hex_str(). */ const char * -geoip_db_digest(void) +geoip_db_digest(sa_family_t family) { - return hex_str(geoip_digest, DIGEST_LEN); + tor_assert(family == AF_INET || family == AF_INET6); + if (family == AF_INET) + return hex_str(geoip_digest, DIGEST_LEN); + else /* AF_INET6 */ + return hex_str(geoip6_digest, DIGEST_LEN); } /** Entry in a map from IP address to the last time we've seen an incoming @@ -372,67 +514,6 @@ client_history_clear(void) } } -/** 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> * at time <b>now</b>. Ignored by all but bridges and directories if * configured accordingly. */ @@ -467,29 +548,21 @@ geoip_note_client_seen(geoip_client_action_t action, else ent->last_seen_in_minutes = 0; - if (action == GEOIP_CLIENT_NETWORKSTATUS || - action == GEOIP_CLIENT_NETWORKSTATUS_V2) { + if (action == GEOIP_CLIENT_NETWORKSTATUS) { int country_idx = geoip_get_country_by_addr(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; - else - ++country->n_v2_ns_requests; + ++country->n_v3_ns_requests; } - - /* Periodically determine share of requests that we should see */ - if (last_time_determined_shares + REQUEST_SHARE_INTERVAL < now) - geoip_determine_shares(now); } } /** HT_FOREACH helper: remove a clientmap_entry_t from the hashtable if it's * older than a certain time. */ static int -_remove_old_client_helper(struct clientmap_entry_t *ent, void *_cutoff) +remove_old_client_helper_(struct clientmap_entry_t *ent, void *_cutoff) { time_t cutoff = *(time_t*)_cutoff / 60; if (ent->last_seen_in_minutes < cutoff) { @@ -505,40 +578,28 @@ void geoip_remove_old_clients(time_t cutoff) { clientmap_HT_FOREACH_FN(&client_history, - _remove_old_client_helper, + remove_old_client_helper_, &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>. */ +/** Note that we've rejected a client's request for a v3 network status + * 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) +geoip_note_ns_response(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]++; + ns_v3_responses[response]++; } /** Do not mention any country from which fewer than this number of IPs have @@ -559,10 +620,10 @@ typedef struct c_hist_t { } c_hist_t; /** Sorting helper: return -1, 1, or 0 based on comparison of two - * geoip_entry_t. Sort in descending order of total, and then by country + * geoip_ipv4_entry_t. Sort in descending order of total, and then by country * code. */ static int -_c_hist_compare(const void **_a, const void **_b) +c_hist_compare_(const void **_a, const void **_b) { const c_hist_t *a = *_a, *b = *_b; if (a->total > b->total) @@ -578,7 +639,7 @@ _c_hist_compare(const void **_a, const void **_b) * failed, the others as still running. */ #define DIRREQ_TIMEOUT (10*60) -/** Entry in a map from either conn->global_identifier for direct requests +/** Entry in a map from either chan->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 @@ -586,14 +647,13 @@ _c_hist_compare(const void **_a, const void **_b) 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 + * chan->global_identifier of the dir channel (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? */ @@ -631,7 +691,7 @@ HT_GENERATE(dirreqmap, dirreq_map_entry_t, node, dirreq_map_ent_hash, * <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, +dirreq_map_put_(dirreq_map_entry_t *entry, dirreq_type_t type, uint64_t dirreq_id) { dirreq_map_entry_t *old_ent; @@ -653,7 +713,7 @@ _dirreq_map_put(dirreq_map_entry_t *entry, dirreq_type_t type, * 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_get_(dirreq_type_t type, uint64_t dirreq_id) { dirreq_map_entry_t lookup; lookup.type = type; @@ -662,12 +722,11 @@ _dirreq_map_get(dirreq_type_t type, uint64_t dirreq_id) } /** 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. */ + * request for a v3 network status with unique ID <b>dirreq_id</b> of size + * <b>response_size</b> has started. */ void geoip_start_dirreq(uint64_t dirreq_id, size_t response_size, - geoip_client_action_t action, dirreq_type_t type) + dirreq_type_t type) { dirreq_map_entry_t *ent; if (!get_options()->DirReqStatistics) @@ -676,9 +735,8 @@ geoip_start_dirreq(uint64_t dirreq_id, size_t response_size, 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); + dirreq_map_put_(ent, type, dirreq_id); } /** Change the state of the either direct or tunneled (see <b>type</b>) @@ -694,7 +752,7 @@ geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, dirreq_map_entry_t *ent; if (!get_options()->DirReqStatistics) return; - ent = _dirreq_map_get(type, dirreq_id); + ent = dirreq_map_get_(type, dirreq_id); if (!ent) return; if (new_state == DIRREQ_IS_FOR_NETWORK_STATUS) @@ -705,7 +763,7 @@ geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, if ((type == DIRREQ_DIRECT && new_state == DIRREQ_FLUSHING_DIR_CONN_FINISHED) || (type == DIRREQ_TUNNELED && - new_state == DIRREQ_OR_CONN_BUFFER_FLUSHED)) { + new_state == DIRREQ_CHANNEL_BUFFER_FLUSHED)) { tor_gettimeofday(&ent->completion_time); ent->completed = 1; } @@ -717,8 +775,7 @@ geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, * 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) +geoip_get_dirreq_history(dirreq_type_t type) { char *result = NULL; smartlist_t *dirreq_completed = NULL; @@ -728,13 +785,10 @@ geoip_get_dirreq_history(geoip_client_action_t action, struct timeval now; tor_gettimeofday(&now); - if (action != GEOIP_CLIENT_NETWORKSTATUS && - action != GEOIP_CLIENT_NETWORKSTATUS_V2) - return NULL; dirreq_completed = smartlist_new(); for (ptr = HT_START(dirreqmap, &dirreq_map); ptr; ptr = next) { ent = *ptr; - if (ent->action != action || ent->type != type) { + if (ent->type != type) { next = HT_NEXT(dirreqmap, &dirreq_map, ptr); continue; } else { @@ -813,27 +867,35 @@ geoip_get_dirreq_history(geoip_client_action_t action, 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) +/** Store a newly allocated comma-separated string in + * *<a>country_str</a> 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. *<a>country_str</a> is set to NULL if + * we're not ready to export per country data yet. + * + * Store a newly allocated comma-separated string in <a>ipver_str</a> + * containing entries for clients connecting over IPv4 and IPv6. The + * format is family=num where num is the nubmer of IPs we've seen + * connecting over that protocol family, and family is 'v4' or 'v6'. + * + * Return 0 on success and -1 if we're missing geoip data. */ +int +geoip_get_client_history(geoip_client_action_t action, + char **country_str, char **ipver_str) { - 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; + unsigned ipv4_count = 0, ipv6_count = 0; - if (!geoip_is_loaded()) - return NULL; + if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6)) + return -1; counts = tor_malloc_zero(sizeof(unsigned)*n_countries); HT_FOREACH(ent, clientmap, &client_history) { @@ -846,10 +908,34 @@ geoip_get_client_history(geoip_client_action_t action) tor_assert(0 <= country && country < n_countries); ++counts[country]; ++total; + switch (tor_addr_family(&(*ent)->addr)) { + case AF_INET: + ipv4_count++; + break; + case AF_INET6: + ipv6_count++; + break; + } } - /* Don't record anything if we haven't seen enough IPs. */ - if (total < MIN_IPS_TO_NOTE_ANYTHING) - goto done; + if (ipver_str) { + smartlist_t *chunks = smartlist_new(); + smartlist_add_asprintf(chunks, "v4=%u", + round_to_next_multiple_of(ipv4_count, granularity)); + smartlist_add_asprintf(chunks, "v6=%u", + round_to_next_multiple_of(ipv6_count, granularity)); + *ipver_str = smartlist_join_strings(chunks, ",", 0, NULL); + SMARTLIST_FOREACH(chunks, char *, c, tor_free(c)); + smartlist_free(chunks); + } + + /* Don't record per country data if we haven't seen enough IPs. */ + if (total < MIN_IPS_TO_NOTE_ANYTHING) { + tor_free(counts); + if (country_str) + *country_str = NULL; + return 0; + } + /* Make a list of c_hist_t */ entries = smartlist_new(); for (i = 0; i < n_countries; ++i) { @@ -868,40 +954,35 @@ geoip_get_client_history(geoip_client_action_t action) } /* 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_new(); - SMARTLIST_FOREACH(entries, c_hist_t *, ch, { - smartlist_add_asprintf(chunks, "%s=%u", ch->country, ch->total); - }); - result = smartlist_join_strings(chunks, ",", 0, NULL); - done: - tor_free(counts); - if (chunks) { + smartlist_sort(entries, c_hist_compare_); + + if (country_str) { + smartlist_t *chunks = smartlist_new(); + SMARTLIST_FOREACH(entries, c_hist_t *, ch, { + smartlist_add_asprintf(chunks, "%s=%u", ch->country, ch->total); + }); + *country_str = smartlist_join_strings(chunks, ",", 0, NULL); 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; + + SMARTLIST_FOREACH(entries, c_hist_t *, c, tor_free(c)); + smartlist_free(entries); + tor_free(counts); + + return 0; } /** Return a newly allocated string holding the per-country request history - * for <b>action</b> in a format suitable for an extra-info document, or NULL - * on failure. */ + * for v3 network statuses in a format suitable for an extra-info document, + * or NULL on failure. */ char * -geoip_get_request_history(geoip_client_action_t action) +geoip_get_request_history(void) { smartlist_t *entries, *strings; char *result; unsigned granularity = IP_GRANULARITY; - if (action != GEOIP_CLIENT_NETWORKSTATUS && - action != GEOIP_CLIENT_NETWORKSTATUS_V2) - return NULL; if (!geoip_countries) return NULL; @@ -909,8 +990,7 @@ geoip_get_request_history(geoip_client_action_t action) SMARTLIST_FOREACH_BEGIN(geoip_countries, geoip_country_t *, c) { uint32_t tot = 0; c_hist_t *ent; - tot = (action == GEOIP_CLIENT_NETWORKSTATUS) ? - c->n_v3_ns_requests : c->n_v2_ns_requests; + tot = c->n_v3_ns_requests; if (!tot) continue; ent = tor_malloc_zero(sizeof(c_hist_t)); @@ -918,7 +998,7 @@ geoip_get_request_history(geoip_client_action_t action) ent->total = round_to_next_multiple_of(tot, granularity); smartlist_add(entries, ent); } SMARTLIST_FOREACH_END(c); - smartlist_sort(entries, _c_hist_compare); + smartlist_sort(entries, c_hist_compare_); strings = smartlist_new(); SMARTLIST_FOREACH(entries, c_hist_t *, ent, { @@ -948,14 +1028,13 @@ void geoip_reset_dirreq_stats(time_t now) { SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { - c->n_v2_ns_requests = c->n_v3_ns_requests = 0; + 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) { + if ((*ent)->action == GEOIP_CLIENT_NETWORKSTATUS) { this = *ent; next = HT_NEXT_RMV(clientmap, &client_history, ent); tor_free(this); @@ -964,10 +1043,6 @@ geoip_reset_dirreq_stats(time_t now) } } } - 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; @@ -995,12 +1070,9 @@ char * geoip_format_dirreq_stats(time_t now) { char t[ISO_TIME_LEN+1]; - double v2_share = 0.0, v3_share = 0.0; int i; - char *v3_ips_string, *v2_ips_string, *v3_reqs_string, *v2_reqs_string, - *v2_share_string = NULL, *v3_share_string = NULL, - *v3_direct_dl_string, *v2_direct_dl_string, - *v3_tunneled_dl_string, *v2_tunneled_dl_string; + char *v3_ips_string, *v3_reqs_string, *v3_direct_dl_string, + *v3_tunneled_dl_string; char *result; if (!start_of_dirreq_stats_interval) @@ -1009,89 +1081,45 @@ geoip_format_dirreq_stats(time_t now) tor_assert(now >= start_of_dirreq_stats_interval); format_iso_time(t, now); - v2_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2); - v3_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS); - v2_reqs_string = geoip_get_request_history( - GEOIP_CLIENT_NETWORKSTATUS_V2); - v3_reqs_string = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS); + geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS, &v3_ips_string, NULL); + v3_reqs_string = geoip_get_request_history(); #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 (!geoip_get_mean_shares(now, &v2_share, &v3_share)) { - tor_asprintf(&v2_share_string, "dirreq-v2-share %0.2f%%\n", - v2_share*100); - tor_asprintf(&v3_share_string, "dirreq-v3-share %0.2f%%\n", - v3_share*100); - } - - v2_direct_dl_string = geoip_get_dirreq_history( - GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_DIRECT); - v3_direct_dl_string = geoip_get_dirreq_history( - GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_DIRECT); - - v2_tunneled_dl_string = geoip_get_dirreq_history( - GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_TUNNELED); - v3_tunneled_dl_string = geoip_get_dirreq_history( - GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_TUNNELED); + v3_direct_dl_string = geoip_get_dirreq_history(DIRREQ_DIRECT); + v3_tunneled_dl_string = geoip_get_dirreq_history(DIRREQ_TUNNELED); /* Put everything together into a single string. */ tor_asprintf(&result, "dirreq-stats-end %s (%d s)\n" "dirreq-v3-ips %s\n" - "dirreq-v2-ips %s\n" "dirreq-v3-reqs %s\n" - "dirreq-v2-reqs %s\n" "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u," "not-found=%u,not-modified=%u,busy=%u\n" - "dirreq-v2-resp ok=%u,unavailable=%u," - "not-found=%u,not-modified=%u,busy=%u\n" - "%s" - "%s" "dirreq-v3-direct-dl %s\n" - "dirreq-v2-direct-dl %s\n" - "dirreq-v3-tunneled-dl %s\n" - "dirreq-v2-tunneled-dl %s\n", + "dirreq-v3-tunneled-dl %s\n", t, (unsigned) (now - start_of_dirreq_stats_interval), v3_ips_string ? v3_ips_string : "", - v2_ips_string ? v2_ips_string : "", v3_reqs_string ? v3_reqs_string : "", - v2_reqs_string ? v2_reqs_string : "", ns_v3_responses[GEOIP_SUCCESS], ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS], ns_v3_responses[GEOIP_REJECT_UNAVAILABLE], ns_v3_responses[GEOIP_REJECT_NOT_FOUND], ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED], ns_v3_responses[GEOIP_REJECT_BUSY], - ns_v2_responses[GEOIP_SUCCESS], - ns_v2_responses[GEOIP_REJECT_UNAVAILABLE], - ns_v2_responses[GEOIP_REJECT_NOT_FOUND], - ns_v2_responses[GEOIP_REJECT_NOT_MODIFIED], - ns_v2_responses[GEOIP_REJECT_BUSY], - v2_share_string ? v2_share_string : "", - v3_share_string ? v3_share_string : "", v3_direct_dl_string ? v3_direct_dl_string : "", - v2_direct_dl_string ? v2_direct_dl_string : "", - v3_tunneled_dl_string ? v3_tunneled_dl_string : "", - v2_tunneled_dl_string ? v2_tunneled_dl_string : ""); + v3_tunneled_dl_string ? v3_tunneled_dl_string : ""); /* Free partial strings. */ tor_free(v3_ips_string); - tor_free(v2_ips_string); tor_free(v3_reqs_string); - tor_free(v2_reqs_string); - tor_free(v2_share_string); - tor_free(v3_share_string); tor_free(v3_direct_dl_string); - tor_free(v2_direct_dl_string); tor_free(v3_tunneled_dl_string); - tor_free(v2_tunneled_dl_string); return result; } @@ -1216,7 +1244,7 @@ static char *bridge_stats_extrainfo = NULL; char * geoip_format_bridge_stats(time_t now) { - char *out = NULL, *data = NULL; + char *out = NULL, *country_data = NULL, *ipver_data = NULL; long duration = now - start_of_bridge_stats_interval; char written[ISO_TIME_LEN+1]; @@ -1226,14 +1254,17 @@ geoip_format_bridge_stats(time_t now) return NULL; /* Not initialized. */ format_iso_time(written, now); - data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + geoip_get_client_history(GEOIP_CLIENT_CONNECT, &country_data, &ipver_data); tor_asprintf(&out, "bridge-stats-end %s (%ld s)\n" - "bridge-ips %s\n", + "bridge-ips %s\n" + "bridge-ip-versions %s\n", written, duration, - data ? data : ""); - tor_free(data); + country_data ? country_data : "", + ipver_data ? ipver_data : ""); + tor_free(country_data); + tor_free(ipver_data); return out; } @@ -1244,17 +1275,20 @@ geoip_format_bridge_stats(time_t now) static char * format_bridge_stats_controller(time_t now) { - char *out = NULL, *data = NULL; + char *out = NULL, *country_data = NULL, *ipver_data = NULL; char started[ISO_TIME_LEN+1]; (void) now; format_iso_time(started, start_of_bridge_stats_interval); - data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + geoip_get_client_history(GEOIP_CLIENT_CONNECT, &country_data, &ipver_data); tor_asprintf(&out, - "TimeStarted=\"%s\" CountrySummary=%s", - started, data ? data : ""); - tor_free(data); + "TimeStarted=\"%s\" CountrySummary=%s IPVersions=%s", + started, + country_data ? country_data : "", + ipver_data ? ipver_data : ""); + tor_free(country_data); + tor_free(ipver_data); return out; } @@ -1316,8 +1350,11 @@ load_bridge_stats(time_t now) fname = get_datadir_fname2("stats", "bridge-stats"); contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); - if (contents && validate_bridge_stats(contents, now)) + if (contents && validate_bridge_stats(contents, now)) { bridge_stats_extrainfo = contents; + } else { + tor_free(contents); + } tor_free(fname); } @@ -1381,11 +1418,13 @@ geoip_format_entry_stats(time_t now) tor_assert(now >= start_of_entry_stats_interval); - data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + geoip_get_client_history(GEOIP_CLIENT_CONNECT, &data, NULL); format_iso_time(t, now); - tor_asprintf(&result, "entry-stats-end %s (%u s)\nentry-ips %s\n", - t, (unsigned) (now - start_of_entry_stats_interval), - data ? data : ""); + tor_asprintf(&result, + "entry-stats-end %s (%u s)\n" + "entry-ips %s\n", + t, (unsigned) (now - start_of_entry_stats_interval), + data ? data : ""); tor_free(data); return result; } @@ -1437,25 +1476,30 @@ getinfo_helper_geoip(control_connection_t *control_conn, const char **errmsg) { (void)control_conn; - 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; + sa_family_t family; + tor_addr_t addr; question += strlen("ip-to-country/"); - if (tor_inet_aton(question, &in) != 0) { - ip = ntohl(in.s_addr); - c = geoip_get_country_by_ip(ip); - *answer = tor_strdup(geoip_get_country_name(c)); + family = tor_addr_parse(&addr, question); + if (family != AF_INET && family != AF_INET6) { + *errmsg = "Invalid address family"; + return -1; + } + if (!geoip_is_loaded(family)) { + *errmsg = "GeoIP data not loaded"; + return -1; } + if (family == AF_INET) + c = geoip_get_country_by_ipv4(tor_addr_to_ipv4h(&addr)); + else /* AF_INET6 */ + c = geoip_get_country_by_ipv6(tor_addr_to_in6(&addr)); + *answer = tor_strdup(geoip_get_country_name(c)); } return 0; } -/** Release all storage held by the GeoIP database. */ +/** Release all storage held by the GeoIP databases and country list. */ static void clear_geoip_db(void) { @@ -1465,13 +1509,20 @@ clear_geoip_db(void) } 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); + if (geoip_ipv4_entries) { + SMARTLIST_FOREACH(geoip_ipv4_entries, geoip_ipv4_entry_t *, ent, + tor_free(ent)); + smartlist_free(geoip_ipv4_entries); + } + if (geoip_ipv6_entries) { + SMARTLIST_FOREACH(geoip_ipv6_entries, geoip_ipv6_entry_t *, ent, + tor_free(ent)); + smartlist_free(geoip_ipv6_entries); } geoip_countries = NULL; country_idxplus1_by_lc_code = NULL; - geoip_entries = NULL; + geoip_ipv4_entries = NULL; + geoip_ipv6_entries = NULL; } /** Release all storage held in this file. */ diff --git a/src/or/geoip.h b/src/or/geoip.h index 4aed4e07bb..ebefee5f4e 100644 --- a/src/or/geoip.h +++ b/src/or/geoip.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,37 +9,38 @@ * \brief Header file for geoip.c. **/ -#ifndef _TOR_GEOIP_H -#define _TOR_GEOIP_H +#ifndef TOR_GEOIP_H +#define TOR_GEOIP_H #ifdef GEOIP_PRIVATE -int geoip_parse_entry(const char *line); +int geoip_parse_entry(const char *line, sa_family_t family); +int geoip_get_country_by_ipv4(uint32_t ipaddr); +int geoip_get_country_by_ipv6(const struct in6_addr *addr); #endif int should_record_bridge_info(const or_options_t *options); -int geoip_load_file(const char *filename, const or_options_t *options); -int geoip_get_country_by_ip(uint32_t ipaddr); +int geoip_load_file(sa_family_t family, const char *filename); int geoip_get_country_by_addr(const tor_addr_t *addr); int geoip_get_n_countries(void); const char *geoip_get_country_name(country_t num); -int geoip_is_loaded(void); -const char *geoip_db_digest(void); +int geoip_is_loaded(sa_family_t family); +const char *geoip_db_digest(sa_family_t family); country_t geoip_get_country(const char *countrycode); void geoip_note_client_seen(geoip_client_action_t action, const tor_addr_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); +void geoip_note_ns_response(geoip_ns_response_t response); +int geoip_get_client_history(geoip_client_action_t action, + char **country_str, char **ipver_str); +char *geoip_get_request_history(void); 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); + dirreq_type_t type); void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, dirreq_state_t new_state); diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 3a9c1e4224..a412571331 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -23,12 +23,15 @@ hibernating, phase 2: #define HIBERNATE_PRIVATE #include "or.h" +#include "channel.h" +#include "channeltls.h" #include "config.h" #include "connection.h" #include "connection_edge.h" #include "hibernate.h" #include "main.h" #include "router.h" +#include "statefile.h" extern long stats_n_seconds_working; /* published uptime */ @@ -503,10 +506,6 @@ accounting_run_housekeeping(time_t now) } } -/** When we have no idea how fast we are, how long do we assume it will take - * us to exhaust our bandwidth? */ -#define GUESS_TIME_TO_USE_BANDWIDTH (24*60*60) - /** Based on our interval and our estimated bandwidth, choose a * deterministic (but random-ish) time to wake up. */ static void @@ -845,7 +844,13 @@ hibernate_go_dormant(time_t now) if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */ connection_mark_unattached_ap(TO_ENTRY_CONN(conn), END_STREAM_REASON_HIBERNATING); - else + else if (conn->type == CONN_TYPE_OR) { + if (TO_OR_CONN(conn)->chan) { + channel_mark_for_close(TLS_CHAN_TO_BASE(TO_OR_CONN(conn)->chan)); + } else { + connection_mark_for_close(conn); + } + } else connection_mark_for_close(conn); } @@ -881,12 +886,12 @@ hibernate_end_time_elapsed(time_t now) /* We weren't sleeping before; we should sleep now. */ log_notice(LD_ACCT, "Accounting period ended. Commencing hibernation until " - "%s GMT", buf); + "%s UTC", buf); hibernate_go_dormant(now); } else { log_notice(LD_ACCT, "Accounting period ended. This period, we will hibernate" - " until %s GMT",buf); + " until %s UTC",buf); } } } diff --git a/src/or/hibernate.h b/src/or/hibernate.h index 9aa026b7b0..d2d6989e10 100644 --- a/src/or/hibernate.h +++ b/src/or/hibernate.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for hibernate.c. **/ -#ifndef _TOR_HIBERNATE_H -#define _TOR_HIBERNATE_H +#ifndef TOR_HIBERNATE_H +#define TOR_HIBERNATE_H int accounting_parse_options(const or_options_t *options, int validate_only); int accounting_is_enabled(const or_options_t *options); diff --git a/src/or/include.am b/src/or/include.am new file mode 100644 index 0000000000..65dbeff53e --- /dev/null +++ b/src/or/include.am @@ -0,0 +1,195 @@ +bin_PROGRAMS+= src/or/tor +noinst_LIBRARIES+= src/or/libtor.a + +if BUILD_NT_SERVICES +tor_platform_source=src/or/ntmain.c +else +tor_platform_source= +endif + +EXTRA_DIST+= src/or/ntmain.c src/or/or_sha1.i src/or/Makefile.nmake + +if USE_EXTERNAL_EVDNS +evdns_source= +else +evdns_source=src/ext/eventdns.c +endif + +if CURVE25519_ENABLED +onion_ntor_source=src/or/onion_ntor.c +else +onion_ntor_source= +endif + +src_or_libtor_a_SOURCES = \ + src/or/addressmap.c \ + src/or/buffers.c \ + src/or/channel.c \ + src/or/channeltls.c \ + src/or/circuitbuild.c \ + src/or/circuitlist.c \ + src/or/circuitmux.c \ + src/or/circuitmux_ewma.c \ + src/or/circuitstats.c \ + src/or/circuituse.c \ + src/or/command.c \ + src/or/config.c \ + src/or/confparse.c \ + src/or/connection.c \ + src/or/connection_edge.c \ + src/or/connection_or.c \ + src/or/control.c \ + src/or/cpuworker.c \ + src/or/directory.c \ + src/or/dirserv.c \ + src/or/dirvote.c \ + src/or/dns.c \ + src/or/dnsserv.c \ + src/or/fp_pair.c \ + src/or/geoip.c \ + src/or/entrynodes.c \ + src/or/hibernate.c \ + src/or/main.c \ + src/or/microdesc.c \ + src/or/networkstatus.c \ + src/or/nodelist.c \ + src/or/onion.c \ + src/or/onion_fast.c \ + src/or/onion_tap.c \ + src/or/transports.c \ + src/or/policies.c \ + src/or/reasons.c \ + src/or/relay.c \ + src/or/rendclient.c \ + src/or/rendcommon.c \ + src/or/rendmid.c \ + src/or/rendservice.c \ + src/or/rephist.c \ + src/or/replaycache.c \ + src/or/router.c \ + src/or/routerlist.c \ + src/or/routerparse.c \ + src/or/routerset.c \ + src/or/statefile.c \ + src/or/status.c \ + $(evdns_source) \ + $(tor_platform_source) \ + $(onion_ntor_source) \ + src/or/config_codedigest.c + +#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \ +# ../common/libor-event.a + + +src_or_tor_SOURCES = src/or/tor_main.c +AM_CPPFLAGS += -I$(srcdir)/src/or -Isrc/or + +src/or/tor_main.o: micro-revision.i + +AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \ + -DLOCALSTATEDIR="\"$(localstatedir)\"" \ + -DBINDIR="\"$(bindir)\"" + +# -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. + + +src_or_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ +src_or_tor_LDADD = src/or/libtor.a src/common/libor.a \ + src/common/libor-crypto.a $(LIBDONNA) \ + src/common/libor-event.a \ + @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + +ORHEADERS = \ + src/or/addressmap.h \ + src/or/buffers.h \ + src/or/channel.h \ + src/or/channeltls.h \ + src/or/circuitbuild.h \ + src/or/circuitlist.h \ + src/or/circuitmux.h \ + src/or/circuitmux_ewma.h \ + src/or/circuitstats.h \ + src/or/circuituse.h \ + src/or/command.h \ + src/or/config.h \ + src/or/confparse.h \ + src/or/connection.h \ + src/or/connection_edge.h \ + src/or/connection_or.h \ + src/or/control.h \ + src/or/cpuworker.h \ + src/or/directory.h \ + src/or/dirserv.h \ + src/or/dirvote.h \ + src/or/dns.h \ + src/or/dnsserv.h \ + src/or/eventdns_tor.h \ + src/or/fp_pair.h \ + src/or/geoip.h \ + src/or/entrynodes.h \ + src/or/hibernate.h \ + src/or/main.h \ + src/or/microdesc.h \ + src/or/networkstatus.h \ + src/or/nodelist.h \ + src/or/ntmain.h \ + src/or/onion.h \ + src/or/onion_fast.h \ + src/or/onion_ntor.h \ + src/or/onion_tap.h \ + src/or/or.h \ + src/or/transports.h \ + src/or/policies.h \ + src/or/reasons.h \ + src/or/relay.h \ + src/or/rendclient.h \ + src/or/rendcommon.h \ + src/or/rendmid.h \ + src/or/rendservice.h \ + src/or/rephist.h \ + src/or/replaycache.h \ + src/or/router.h \ + src/or/routerlist.h \ + src/or/routerset.h \ + src/or/routerparse.h \ + src/or/statefile.h \ + src/or/status.h + +noinst_HEADERS+= $(ORHEADERS) micro-revision.i + +src/or/config_codedigest.o: src/or/or_sha1.i + +micro-revision.i: FORCE + @rm -f micro-revision.tmp; \ + if test -d "$(top_srcdir)/.git" && \ + test -x "`which git 2>&1;true`"; then \ + HASH="`cd "$(top_srcdir)" && git rev-parse --short=16 HEAD`"; \ + echo \"$$HASH\" > micro-revision.tmp; \ + fi; \ + if test ! -f micro-revision.tmp ; then \ + 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; \ + fi; true + +src/or/or_sha1.i: $(src_or_tor_SOURCES) $(src_or_libtor_a_SOURCES) $(ORHEADERS) + $(AM_V_GEN)if test "@SHA1SUM@" != none; then \ + (cd "$(srcdir)" && "@SHA1SUM@" $(src_or_tor_SOURCES) $(src_or_libtor_a_SOURCES) $(ORHEADERS) ) | \ + "@SED@" -n 's/^\(.*\)$$/"\1\\n"/p' > src/or/or_sha1.i; \ + elif test "@OPENSSL@" != none; then \ + (cd "$(srcdir)" && "@OPENSSL@" sha1 $(src_or_tor_SOURCES) $(src_or_libtor_a_SOURCES) $(ORHEADERS)) | \ + "@SED@" -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > src/or/or_sha1.i; \ + else \ + rm src/or/or_sha1.i; \ + touch src/or/or_sha1.i; \ + fi + +CLEANFILES+= micro-revision.i src/or/micro-revision.i + +FORCE: diff --git a/src/or/main.c b/src/or/main.c index 34bf3e50f5..bd23141b97 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,7 +12,10 @@ #define MAIN_PRIVATE #include "or.h" +#include "addressmap.h" #include "buffers.h" +#include "channel.h" +#include "channeltls.h" #include "circuitbuild.h" #include "circuitlist.h" #include "circuituse.h" @@ -28,6 +31,7 @@ #include "dirvote.h" #include "dns.h" #include "dnsserv.h" +#include "entrynodes.h" #include "geoip.h" #include "hibernate.h" #include "main.h" @@ -46,6 +50,7 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "statefile.h" #include "status.h" #ifdef USE_DMALLOC #include <dmalloc.h> @@ -153,10 +158,6 @@ int can_complete_circuit=0; /** How long do we let a directory connection stall before expiring it? */ #define DIR_CONN_MAX_STALL (5*60) -/** How long do we let OR connections handshake before we decide that - * they are obsolete? */ -#define TLS_HANDSHAKE_TIMEOUT (60) - /** Decides our behavior when no logs are configured/before any * logs have been configured. For 0, we log notice to stdout as normal. * For 1, we log warnings only. For 2, we log nothing. @@ -397,6 +398,18 @@ connection_unlink(connection_t *conn) if (conn->type == CONN_TYPE_OR) { if (!tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest)) connection_or_remove_from_identity_map(TO_OR_CONN(conn)); + /* connection_unlink() can only get called if the connection + * was already on the closeable list, and it got there by + * connection_mark_for_close(), which was called from + * connection_or_close_normally() or + * connection_or_close_for_error(), so the channel should + * already be in CHANNEL_STATE_CLOSING, and then the + * connection_about_to_close_connection() goes to + * connection_or_about_to_close(), which calls channel_closed() + * to notify the channel_t layer, and closed the channel, so + * nothing more to do here to deal with the channel associated + * with an orconn. + */ } connection_free(conn); } @@ -405,7 +418,7 @@ connection_unlink(connection_t *conn) void add_connection_to_closeable_list(connection_t *conn) { - tor_assert(!smartlist_isin(closeable_connection_lst, conn)); + tor_assert(!smartlist_contains(closeable_connection_lst, conn)); tor_assert(conn->marked_for_close); assert_connection_ok(conn, time(NULL)); smartlist_add(closeable_connection_lst, conn); @@ -415,14 +428,14 @@ add_connection_to_closeable_list(connection_t *conn) int connection_is_on_closeable_list(connection_t *conn) { - return smartlist_isin(closeable_connection_lst, conn); + return smartlist_contains(closeable_connection_lst, conn); } /** Return true iff conn is in the current poll array. */ int connection_in_array(connection_t *conn) { - return smartlist_isin(connection_array, conn); + return smartlist_contains(connection_array, conn); } /** Set <b>*array</b> to an array of all connections, and <b>*n</b> @@ -649,7 +662,7 @@ connection_start_reading_from_linked_conn(connection_t *conn) tor_event_base_loopexit(tor_libevent_get_base(), &tv); } } else { - tor_assert(smartlist_isin(active_linked_connection_lst, conn)); + tor_assert(smartlist_contains(active_linked_connection_lst, conn)); } } @@ -669,7 +682,7 @@ connection_stop_reading_from_linked_conn(connection_t *conn) * so let's leave it alone for now. */ smartlist_remove(active_linked_connection_lst, conn); } else { - tor_assert(!smartlist_isin(active_linked_connection_lst, conn)); + tor_assert(!smartlist_contains(active_linked_connection_lst, conn)); } } @@ -796,7 +809,8 @@ conn_close_if_marked(int i) } #endif - log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s); + log_debug(LD_NET,"Cleaning up connection (fd "TOR_SOCKET_T_FORMAT").", + conn->s); /* If the connection we are about to close was trying to connect to a proxy server and failed, the client won't be able to use that @@ -953,8 +967,9 @@ directory_info_has_arrived(time_t now, int from_cache) const or_options_t *options = get_options(); if (!router_have_minimum_dir_info()) { - int quiet = directory_too_idle_to_fetch_descriptors(options, now); - log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR, + int quiet = from_cache || + directory_too_idle_to_fetch_descriptors(options, now); + tor_log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR, "I learned some more directory information, but not enough to " "build a circuit: %s", get_dir_info_status_string()); update_all_descriptor_downloads(now); @@ -1044,7 +1059,8 @@ run_connection_housekeeping(int i, time_t now) tor_assert(conn->outbuf); #endif - if (or_conn->is_bad_for_new_circs && !or_conn->n_circuits) { + if (channel_is_bad_for_new_circs(TLS_CHAN_TO_BASE(or_conn->chan)) && + !connection_or_get_num_circuits(or_conn)) { /* It's bad for new circuits, and has no unmarked circuits on it: * mark it now. */ log_info(LD_OR, @@ -1054,28 +1070,29 @@ run_connection_housekeeping(int i, time_t now) connection_or_connect_failed(TO_OR_CONN(conn), END_OR_CONN_REASON_TIMEOUT, "Tor gave up on the connection"); - connection_mark_and_flush(conn); + connection_or_close_normally(TO_OR_CONN(conn), 1); } else if (!connection_state_is_open(conn)) { if (past_keepalive) { /* We never managed to actually get this connection open and happy. */ log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).", (int)conn->s,conn->address, conn->port); - connection_mark_for_close(conn); + connection_or_close_normally(TO_OR_CONN(conn), 0); } - } else if (we_are_hibernating() && !or_conn->n_circuits && + } else if (we_are_hibernating() && + !connection_or_get_num_circuits(or_conn) && !connection_get_outbuf_len(conn)) { /* We're hibernating, there's no circuits, and nothing to flush.*/ log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " "[Hibernating or exiting].", (int)conn->s,conn->address, conn->port); - connection_mark_and_flush(conn); - } else if (!or_conn->n_circuits && + connection_or_close_normally(TO_OR_CONN(conn), 1); + } else if (!connection_or_get_num_circuits(or_conn) && now >= or_conn->timestamp_last_added_nonpadding + IDLE_OR_CONN_TIMEOUT) { log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " "[idle %d].", (int)conn->s,conn->address, conn->port, (int)(now - or_conn->timestamp_last_added_nonpadding)); - connection_mark_for_close(conn); + connection_or_close_normally(TO_OR_CONN(conn), 0); } else if ( now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 && now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) { @@ -1085,7 +1102,7 @@ run_connection_housekeeping(int i, time_t now) (int)conn->s, conn->address, conn->port, (int)connection_get_outbuf_len(conn), (int)(now-conn->timestamp_lastwritten)); - connection_mark_for_close(conn); + connection_or_close_normally(TO_OR_CONN(conn), 0); } else if (past_keepalive && !connection_get_outbuf_len(conn)) { /* send a padding cell */ log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)", @@ -1108,7 +1125,7 @@ signewnym_impl(time_t now) return; } - circuit_expire_all_dirty_circs(); + circuit_mark_all_dirty_circs_as_unusable(); addressmap_clear_transient(); rend_client_purge_state(); time_of_last_signewnym = now; @@ -1136,7 +1153,6 @@ run_scheduled_events(time_t now) static time_t time_to_check_v3_certificate = 0; static time_t time_to_check_listeners = 0; static time_t time_to_check_descriptor = 0; - static time_t time_to_check_ipaddress = 0; static time_t time_to_shrink_memory = 0; static time_t time_to_try_getting_descriptors = 0; static time_t time_to_reset_descriptor_failures = 0; @@ -1180,7 +1196,7 @@ run_scheduled_events(time_t now) * eventually. */ if (signewnym_is_pending && time_of_last_signewnym + MAX_SIGNEWNYM_RATE <= now) { - log(LOG_INFO, LD_CONTROL, "Honoring delayed NEWNYM request"); + log_info(LD_CONTROL, "Honoring delayed NEWNYM request"); signewnym_impl(now); } @@ -1382,11 +1398,10 @@ run_scheduled_events(time_t now) /** 2. Periodically, we consider force-uploading our descriptor * (if we've passed our internal checks). */ -/** How often do we check whether part of our router info has changed in a way - * that would require an upload? */ +/** How often do we check whether part of our router info has changed in a + * way that would require an upload? That includes checking whether our IP + * address has changed. */ #define CHECK_DESCRIPTOR_INTERVAL (60) -/** How often do we (as a router) check whether our IP address has changed? */ -#define CHECK_IPADDRESS_INTERVAL (15*60) /* 2b. Once per minute, regenerate and upload the descriptor if the old * one is inaccurate. */ @@ -1394,10 +1409,7 @@ run_scheduled_events(time_t now) static int dirport_reachability_count = 0; time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL; check_descriptor_bandwidth_changed(now); - if (time_to_check_ipaddress < now) { - time_to_check_ipaddress = now + CHECK_IPADDRESS_INTERVAL; - check_descriptor_ipaddress_changed(now); - } + check_descriptor_ipaddress_changed(now); mark_my_descriptor_dirty_if_too_old(now); consider_publishable_server(0); /* also, check religiously for reachability, if it's within the first @@ -1519,6 +1531,10 @@ run_scheduled_events(time_t now) * flush it. */ or_state_save(now); + /** 8c. Do channel cleanup just like for connections */ + channel_run_cleanup(); + channel_listener_run_cleanup(); + /** 9. and if we're a server, check whether our DNS is telling stories to * us. */ if (!net_is_disabled() && @@ -1546,11 +1562,15 @@ run_scheduled_events(time_t now) options->PortForwarding && is_server) { #define PORT_FORWARDING_CHECK_INTERVAL 5 - /* XXXXX this should take a list of ports, not just two! */ - tor_check_port_forwarding(options->PortForwardingHelper, - get_primary_dir_port(), - get_primary_or_port(), - now); + smartlist_t *ports_to_forward = get_list_of_ports_to_forward(); + if (ports_to_forward) { + tor_check_port_forwarding(options->PortForwardingHelper, + ports_to_forward, + now); + + SMARTLIST_FOREACH(ports_to_forward, char *, cp, tor_free(cp)); + smartlist_free(ports_to_forward); + } time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL; } @@ -1561,7 +1581,8 @@ run_scheduled_events(time_t now) /** 12. write the heartbeat message */ if (options->HeartbeatPeriod && time_to_next_heartbeat <= now) { - log_heartbeat(now); + if (time_to_next_heartbeat) /* don't log the first heartbeat */ + log_heartbeat(now); time_to_next_heartbeat = now+options->HeartbeatPeriod; } } @@ -1823,7 +1844,7 @@ do_hup(void) /* Rotate away from the old dirty circuits. This has to be done * after we've read the new options, but before we start using * circuits for directory fetches. */ - circuit_expire_all_dirty_circs(); + circuit_mark_all_dirty_circs_as_unusable(); /* retry appropriate downloads */ router_reset_status_download_failures(); @@ -1861,6 +1882,13 @@ do_main_loop(void) } } +#ifdef USE_BUFFEREVENTS + log_warn(LD_GENERAL, "Tor was compiled with the --enable-bufferevents " + "option. This is still experimental, and might cause strange " + "bugs. If you want a more stable Tor, be sure to build without " + "--enable-bufferevents."); +#endif + handle_signals(1); /* load the private keys, if we're supposed to have them, and set up the @@ -2053,7 +2081,7 @@ process_signal(uintptr_t sig) time_t now = time(NULL); if (time_of_last_signewnym + MAX_SIGNEWNYM_RATE > now) { signewnym_is_pending = 1; - log(LOG_NOTICE, LD_CONTROL, + log_notice(LD_CONTROL, "Rate limiting NEWNYM request: delaying by %d second(s)", (int)(MAX_SIGNEWNYM_RATE+time_of_last_signewnym-now)); } else { @@ -2085,7 +2113,7 @@ static void dumpmemusage(int severity) { connection_dump_buffer_mem_stats(severity); - log(severity, LD_GENERAL, "In rephist: "U64_FORMAT" used by %d Tors.", + tor_log(severity, LD_GENERAL, "In rephist: "U64_FORMAT" used by %d Tors.", U64_PRINTF_ARG(rephist_total_alloc), rephist_total_num); dump_routerlist_mem_usage(severity); dump_cell_pool_usage(severity); @@ -2103,27 +2131,27 @@ dumpstats(int severity) time_t elapsed; size_t rbuf_cap, wbuf_cap, rbuf_len, wbuf_len; - log(severity, LD_GENERAL, "Dumping stats:"); + tor_log(severity, LD_GENERAL, "Dumping stats:"); SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { int i = conn_sl_idx; - log(severity, LD_GENERAL, + tor_log(severity, LD_GENERAL, "Conn %d (socket %d) type %d (%s), state %d (%s), created %d secs ago", i, (int)conn->s, conn->type, conn_type_to_string(conn->type), conn->state, conn_state_to_string(conn->type, conn->state), (int)(now - conn->timestamp_created)); if (!connection_is_listener(conn)) { - log(severity,LD_GENERAL, + tor_log(severity,LD_GENERAL, "Conn %d is to %s:%d.", i, safe_str_client(conn->address), conn->port); - log(severity,LD_GENERAL, + tor_log(severity,LD_GENERAL, "Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)", i, (int)connection_get_inbuf_len(conn), (int)buf_allocation(conn->inbuf), (int)(now - conn->timestamp_lastread)); - log(severity,LD_GENERAL, + tor_log(severity,LD_GENERAL, "Conn %d: %d bytes waiting on outbuf " "(len %d, last written %d secs ago)",i, (int)connection_get_outbuf_len(conn), @@ -2134,7 +2162,7 @@ dumpstats(int severity) if (or_conn->tls) { tor_tls_get_buffer_sizes(or_conn->tls, &rbuf_cap, &rbuf_len, &wbuf_cap, &wbuf_len); - log(severity, LD_GENERAL, + tor_log(severity, LD_GENERAL, "Conn %d: %d/%d bytes used on OpenSSL read buffer; " "%d/%d bytes used on write buffer.", i, (int)rbuf_len, (int)rbuf_cap, (int)wbuf_len, (int)wbuf_cap); @@ -2144,7 +2172,11 @@ dumpstats(int severity) circuit_dump_by_conn(conn, severity); /* dump info about all the circuits * using this conn */ } SMARTLIST_FOREACH_END(conn); - log(severity, LD_NET, + + channel_dumpstats(severity); + channel_listener_dumpstats(severity); + + tor_log(severity, LD_NET, "Cells processed: "U64_FORMAT" padding\n" " "U64_FORMAT" create\n" " "U64_FORMAT" created\n" @@ -2160,33 +2192,36 @@ dumpstats(int severity) U64_PRINTF_ARG(stats_n_relay_cells_delivered), U64_PRINTF_ARG(stats_n_destroy_cells_processed)); if (stats_n_data_cells_packaged) - log(severity,LD_NET,"Average packaged cell fullness: %2.3f%%", + tor_log(severity,LD_NET,"Average packaged cell fullness: %2.3f%%", 100*(U64_TO_DBL(stats_n_data_bytes_packaged) / U64_TO_DBL(stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) ); if (stats_n_data_cells_received) - log(severity,LD_NET,"Average delivered cell fullness: %2.3f%%", + tor_log(severity,LD_NET,"Average delivered cell fullness: %2.3f%%", 100*(U64_TO_DBL(stats_n_data_bytes_received) / U64_TO_DBL(stats_n_data_cells_received*RELAY_PAYLOAD_SIZE)) ); + cpuworker_log_onionskin_overhead(severity, ONION_HANDSHAKE_TYPE_TAP, "TAP"); + cpuworker_log_onionskin_overhead(severity, ONION_HANDSHAKE_TYPE_NTOR,"ntor"); + if (now - time_of_process_start >= 0) elapsed = now - time_of_process_start; else elapsed = 0; if (elapsed) { - log(severity, LD_NET, + tor_log(severity, LD_NET, "Average bandwidth: "U64_FORMAT"/%d = %d bytes/sec reading", U64_PRINTF_ARG(stats_n_bytes_read), (int)elapsed, (int) (stats_n_bytes_read/elapsed)); - log(severity, LD_NET, + tor_log(severity, LD_NET, "Average bandwidth: "U64_FORMAT"/%d = %d bytes/sec writing", U64_PRINTF_ARG(stats_n_bytes_written), (int)elapsed, (int) (stats_n_bytes_written/elapsed)); } - log(severity, LD_NET, "--------------- Dumping memory information:"); + tor_log(severity, LD_NET, "--------------- Dumping memory information:"); dumpmemusage(severity); rep_hist_dump_stats(now,severity); @@ -2286,6 +2321,9 @@ tor_init(int argc, char *argv[]) quiet = 1; if (!strcmp(argv[i], "--quiet")) quiet = 2; + /* --version implies --quiet */ + if (!strcmp(argv[i], "--version")) + quiet = 2; } /* give it somewhere to log to initially */ switch (quiet) { @@ -2302,12 +2340,17 @@ tor_init(int argc, char *argv[]) { const char *version = get_version(); + const char *bev_str = #ifdef USE_BUFFEREVENTS - log_notice(LD_GENERAL, "Tor v%s (with bufferevents) running on %s.", - version, get_uname()); + "(with bufferevents) "; #else - log_notice(LD_GENERAL, "Tor v%s running on %s.", version, get_uname()); + ""; #endif + log_notice(LD_GENERAL, "Tor v%s %srunning on %s with Libevent %s " + "and OpenSSL %s.", version, bev_str, + get_uname(), + tor_libevent_get_version_str(), + crypto_openssl_get_version_str()); log_notice(LD_GENERAL, "Tor can't help you if you use it wrong! " "Learn how to be safe at " @@ -2319,7 +2362,7 @@ tor_init(int argc, char *argv[]) } #ifdef NON_ANONYMOUS_MODE_ENABLED - log(LOG_WARN, LD_GENERAL, "This copy of Tor was compiled to run in a " + log_warn(LD_GENERAL, "This copy of Tor was compiled to run in a " "non-anonymous mode. It will provide NO ANONYMITY."); #endif @@ -2346,6 +2389,7 @@ tor_init(int argc, char *argv[]) log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } + stream_choice_seed_weak_rng(); return 0; } @@ -2441,6 +2485,8 @@ tor_free_all(int postfork) circuit_free_all(); entry_guards_free_all(); pt_free_all(); + channel_tls_free_all(); + channel_free_all(); connection_free_all(); buf_shrink_freelists(1); memarea_clear_freelist(); @@ -2448,6 +2494,7 @@ tor_free_all(int postfork) microdesc_free_all(); if (!postfork) { config_free_all(); + or_state_free_all(); router_free_all(); policies_free_all(); } @@ -2461,6 +2508,10 @@ tor_free_all(int postfork) smartlist_free(closeable_connection_lst); smartlist_free(active_linked_connection_lst); periodic_timer_free(second_timer); +#ifndef USE_BUFFEREVENTS + periodic_timer_free(refill_timer); +#endif + if (!postfork) { release_lockfile(); } @@ -2631,7 +2682,7 @@ tor_main(int argc, char *argv[]) { /* Instruct OpenSSL to use our internal wrappers for malloc, realloc and free. */ - int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc, _tor_free); + int r = CRYPTO_set_mem_ex_functions(tor_malloc_, tor_realloc_, tor_free_); tor_assert(r); } #endif diff --git a/src/or/main.h b/src/or/main.h index f843b6f9fc..338449b6a6 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for main.c. **/ -#ifndef _TOR_MAIN_H -#define _TOR_MAIN_H +#ifndef TOR_MAIN_H +#define TOR_MAIN_H extern int can_complete_circuit; diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 4acec6ae3d..0e72c0b89b 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2012, The Tor Project, Inc. */ +/* Copyright (c) 2009-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "or.h" @@ -6,6 +6,7 @@ #include "config.h" #include "directory.h" #include "dirserv.h" +#include "entrynodes.h" #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" @@ -42,7 +43,7 @@ struct microdesc_cache_t { /** Helper: computes a hash of <b>md</b> to place it in a hash table. */ static INLINE unsigned int -_microdesc_hash(microdesc_t *md) +microdesc_hash_(microdesc_t *md) { unsigned *d = (unsigned*)md->digest; #if SIZEOF_INT == 4 @@ -54,15 +55,15 @@ _microdesc_hash(microdesc_t *md) /** Helper: compares <b>a</b> and </b> for equality for hash-table purposes. */ static INLINE int -_microdesc_eq(microdesc_t *a, microdesc_t *b) +microdesc_eq_(microdesc_t *a, microdesc_t *b) { return tor_memeq(a->digest, b->digest, DIGEST256_LEN); } HT_PROTOTYPE(microdesc_map, microdesc_t, node, - _microdesc_hash, _microdesc_eq); + microdesc_hash_, microdesc_eq_); HT_GENERATE(microdesc_map, microdesc_t, node, - _microdesc_hash, _microdesc_eq, 0.6, + microdesc_hash_, microdesc_eq_, 0.6, malloc, realloc, free); /** Write the body of <b>md</b> into <b>f</b>, with appropriate annotations. @@ -70,20 +71,24 @@ HT_GENERATE(microdesc_map, microdesc_t, node, * *<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) +dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out) { ssize_t r = 0; - size_t written; - /* XXXX drops unkown annotations. */ + ssize_t written; + if (md->body == NULL) { + *annotation_len_out = 0; + return 0; + } + /* XXXX drops unknown 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); - if (fputs(annotation, f) < 0) { + if (write_all(fd, annotation, strlen(annotation), 0) < 0) { log_warn(LD_DIR, "Couldn't write microdescriptor annotation: %s", - strerror(ferror(f))); + strerror(errno)); return -1; } r += strlen(annotation); @@ -92,13 +97,13 @@ dump_microdescriptor(FILE *f, microdesc_t *md, size_t *annotation_len_out) *annotation_len_out = 0; } - md->off = (off_t) ftell(f); - written = fwrite(md->body, 1, md->bodylen, f); - if (written != md->bodylen) { + md->off = tor_fd_getpos(fd); + written = write_all(fd, md->body, md->bodylen, 0); + if (written != (ssize_t)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))); + "Couldn't dump microdescriptor (wrote %ld out of %lu): %s", + (long)written, (unsigned long)md->bodylen, + strerror(errno)); return -1; } r += md->bodylen; @@ -131,7 +136,7 @@ get_microdesc_cache(void) */ /** 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>, + * 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. If listed_at is positive, @@ -149,17 +154,16 @@ microdescs_add_to_cache(microdesc_cache_t *cache, { 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); + where); if (listed_at > 0) { SMARTLIST_FOREACH(descriptors, microdesc_t *, md, md->last_listed = listed_at); } if (requested_digests256) { - digestmap_t *requested; /* XXXX actuqlly we should just use a + digestmap_t *requested; /* XXXX actually we should just use a digest256map */ requested = digestmap_new(); SMARTLIST_FOREACH(requested_digests256, const char *, cp, @@ -168,7 +172,7 @@ microdescs_add_to_cache(microdesc_cache_t *cache, if (digestmap_get(requested, md->digest)) { digestmap_set(requested, md->digest, (void*)2); } else { - log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microcdesc"); + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microdesc"); microdesc_free(md); SMARTLIST_DEL_CURRENT(descriptors, md); } @@ -187,7 +191,7 @@ microdescs_add_to_cache(microdesc_cache_t *cache, return added; } -/** As microdescs_add_to_cache, but takes a list of micrdescriptors instead of +/** As microdescs_add_to_cache, but takes a list of microdescriptors instead of * a string to decode. Frees any members of <b>descriptors</b> that it does * not add. */ smartlist_t * @@ -197,18 +201,17 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, { smartlist_t *added; open_file_t *open_file = NULL; - FILE *f = NULL; + int fd = -1; // 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) { + fd = start_writing_to_file(cache->journal_fname, + OPEN_FLAGS_APPEND|O_BINARY, + 0600, &open_file); + if (fd < 0) { log_warn(LD_DIR, "Couldn't append to journal in %s: %s", cache->journal_fname, strerror(errno)); - return NULL; } } @@ -227,17 +230,17 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, } /* Okay, it's a new one. */ - if (f) { + if (fd >= 0) { size_t annotation_len; - size = dump_microdescriptor(f, md, &annotation_len); + size = dump_microdescriptor(fd, md, &annotation_len); if (size < 0) { - /* we already warned in dump_microdescriptor; */ + /* we already warned in dump_microdescriptor */ abort_writing_to_file(open_file); - smartlist_clear(added); - return added; + fd = -1; + } else { + md->saved_location = SAVED_IN_JOURNAL; + cache->journal_len += size; } - md->saved_location = SAVED_IN_JOURNAL; - cache->journal_len += size; } else { md->saved_location = where; } @@ -251,8 +254,14 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, cache->total_len_seen += md->bodylen; } SMARTLIST_FOREACH_END(md); - if (f) - finish_writing_to_file(open_file); /*XXX Check me.*/ + if (fd >= 0) { + if (finish_writing_to_file(open_file) < 0) { + log_warn(LD_DIR, "Error appending to microdescriptor file: %s", + strerror(errno)); + smartlist_clear(added); + return added; + } + } { networkstatus_t *ns = networkstatus_get_latest_consensus(); @@ -323,8 +332,8 @@ microdesc_cache_reload(microdesc_cache_t *cache) } tor_free(journal_content); } - log_notice(LD_DIR, "Reloaded microdescriptor cache. Found %d descriptors.", - total); + log_info(LD_DIR, "Reloaded microdescriptor cache. Found %d descriptors.", + total); microdesc_cache_rebuild(cache, 0 /* don't force */); @@ -397,6 +406,26 @@ should_rebuild_md_cache(microdesc_cache_t *cache) return 0; } +/** + * Mark <b>md</b> as having no body, and release any storage previously held + * by its body. + */ +static void +microdesc_wipe_body(microdesc_t *md) +{ + if (!md) + return; + + if (md->saved_location != SAVED_IN_CACHE) + tor_free(md->body); + + md->off = 0; + md->saved_location = SAVED_NOWHERE; + md->body = NULL; + md->bodylen = 0; + md->no_save = 1; +} + /** 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. If <b>force</b> is true, do this unconditionally. If @@ -405,11 +434,11 @@ int microdesc_cache_rebuild(microdesc_cache_t *cache, int force) { open_file_t *open_file; - FILE *f; + int fd = -1; microdesc_t **mdp; smartlist_t *wrote; ssize_t size; - off_t off = 0; + off_t off = 0, off_real; int orig_size, new_size; if (cache == NULL) { @@ -429,10 +458,10 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) 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) + fd = start_writing_to_file(cache->cache_fname, + OPEN_FLAGS_REPLACE|O_BINARY, + 0600, &open_file); + if (fd < 0) return -1; wrote = smartlist_new(); @@ -440,18 +469,28 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) HT_FOREACH(mdp, microdesc_map, &cache->map) { microdesc_t *md = *mdp; size_t annotation_len; - if (md->no_save) + if (md->no_save || !md->body) continue; - size = dump_microdescriptor(f, md, &annotation_len); + size = dump_microdescriptor(fd, md, &annotation_len); if (size < 0) { - /* XXX handle errors from dump_microdescriptor() */ - /* log? return -1? die? coredump the universe? */ + microdesc_wipe_body(md); + + /* rewind, in case it was a partial write. */ + tor_fd_setpos(fd, off); continue; } tor_assert(((size_t)size) == annotation_len + md->bodylen); md->off = off + annotation_len; off += size; + off_real = tor_fd_getpos(fd); + if (off_real != off) { + log_warn(LD_BUG, "Discontinuity in position in microdescriptor cache." + "By my count, I'm at "I64_FORMAT + ", but I should be at "I64_FORMAT, + I64_PRINTF_ARG(off), I64_PRINTF_ARG(off_real)); + off = off_real; + } if (md->saved_location != SAVED_IN_CACHE) { tor_free(md->body); md->saved_location = SAVED_IN_CACHE; @@ -459,10 +498,24 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) smartlist_add(wrote, md); } + /* We must do this unmap _before_ we call finish_writing_to_file(), or + * windows will not actually replace the file. */ if (cache->cache_content) tor_munmap_file(cache->cache_content); - finish_writing_to_file(open_file); /*XXX Check me.*/ + if (finish_writing_to_file(open_file) < 0) { + log_warn(LD_DIR, "Error rebuilding microdescriptor cache: %s", + strerror(errno)); + /* Okay. Let's prevent from making things worse elsewhere. */ + cache->cache_content = NULL; + HT_FOREACH(mdp, microdesc_map, &cache->map) { + microdesc_t *md = *mdp; + if (md->saved_location == SAVED_IN_CACHE) { + microdesc_wipe_body(md); + } + } + return -1; + } cache->cache_content = tor_mmap_file(cache->cache_fname); @@ -478,7 +531,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) if (PREDICT_UNLIKELY( md->bodylen < 9 || fast_memneq(md->body, "onion-key", 9) != 0)) { /* XXXX once bug 2022 is solved, we can kill this block and turn it - * into just the tor_assert(!memcmp) */ + * into just the tor_assert(fast_memeq) */ off_t avail = cache->cache_content->size - md->off; char *bad_str; tor_assert(avail >= 0); @@ -531,7 +584,7 @@ microdesc_check_counts(void) /** 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) +microdesc_free_(microdesc_t *md, const char *fname, int lineno) { if (!md) return; @@ -542,12 +595,12 @@ microdesc_free(microdesc_t *md) microdesc_cache_t *cache = get_microdesc_cache(); microdesc_t *md2 = HT_FIND(microdesc_map, &cache->map, md); if (md2 == md) { - log_warn(LD_BUG, "microdesc_free() called, but md was still in " - "microdesc_map"); + log_warn(LD_BUG, "microdesc_free() called from %s:%d, but md was still " + "in microdesc_map", fname, lineno); HT_REMOVE(microdesc_map, &cache->map, md); } else { - log_warn(LD_BUG, "microdesc_free() called with held_in_map set, but " - "microdesc was not in the map."); + log_warn(LD_BUG, "microdesc_free() called from %s:%d with held_in_map " + "set, but microdesc was not in the map.", fname, lineno); } tor_fragile_assert(); } @@ -561,11 +614,13 @@ microdesc_free(microdesc_t *md) } }); if (found) { - log_info(LD_BUG, "microdesc_free() called, but md was still referenced " - "%d node(s); held_by_nodes == %u", found, md->held_by_nodes); + log_info(LD_BUG, "microdesc_free() called from %s:%d, but md was still " + "referenced %d node(s); held_by_nodes == %u", + fname, lineno, found, md->held_by_nodes); } else { - log_warn(LD_BUG, "microdesc_free() called with held_by_nodes set to %u, " - "but md was not referenced by any nodes", md->held_by_nodes); + log_warn(LD_BUG, "microdesc_free() called from %s:%d with held_by_nodes " + "set to %u, but md was not referenced by any nodes", + fname, lineno, md->held_by_nodes); } tor_fragile_assert(); } @@ -574,6 +629,7 @@ microdesc_free(microdesc_t *md) if (md->onion_pkey) crypto_pk_free(md->onion_pkey); + tor_free(md->onion_curve25519_pkey); if (md->body && md->saved_location != SAVED_IN_CACHE) tor_free(md->body); @@ -582,6 +638,7 @@ microdesc_free(microdesc_t *md) smartlist_free(md->family); } short_policy_free(md->exit_policy); + short_policy_free(md->ipv6_exit_policy); tor_free(md); } @@ -727,9 +784,9 @@ we_use_microdescriptors_for_circuits(const or_options_t *options) int ret = options->UseMicrodescriptors; if (ret == -1) { /* UseMicrodescriptors is "auto"; we need to decide: */ - /* If we are configured to use bridges and one of our bridges doesn't + /* If we are configured to use bridges and none of our bridges * know what a microdescriptor is, the answer is no. */ - if (options->UseBridges && any_bridges_dont_support_microdescriptors()) + if (options->UseBridges && !any_bridge_supports_microdescriptors()) return 0; /* Otherwise, we decide that we'll use microdescriptors iff we are * not a server, and we're not autofetching everything. */ diff --git a/src/or/microdesc.h b/src/or/microdesc.h index 5646fc7a85..7adb8c68af 100644 --- a/src/or/microdesc.h +++ b/src/or/microdesc.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for microdesc.c. **/ -#ifndef _TOR_MICRODESC_H -#define _TOR_MICRODESC_H +#ifndef TOR_MICRODESC_H +#define TOR_MICRODESC_H microdesc_cache_t *get_microdesc_cache(void); @@ -39,7 +39,9 @@ smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns, int downloadable_only, digestmap_t *skip); -void microdesc_free(microdesc_t *md); +void microdesc_free_(microdesc_t *md, const char *fname, int line); +#define microdesc_free(md) \ + microdesc_free_((md), __FILE__, __LINE__) void microdesc_free_all(void); void update_microdesc_downloads(time_t now); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 10cc56231f..23b7304b39 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,7 +11,10 @@ */ #include "or.h" -#include "circuitbuild.h" +#include "channel.h" +#include "circuitmux.h" +#include "circuitmux_ewma.h" +#include "circuitstats.h" #include "config.h" #include "connection.h" #include "connection_or.h" @@ -19,6 +22,7 @@ #include "directory.h" #include "dirserv.h" #include "dirvote.h" +#include "entrynodes.h" #include "main.h" #include "microdesc.h" #include "networkstatus.h" @@ -215,8 +219,6 @@ router_reload_consensus_networkstatus(void) { char *filename; char *s; - struct stat st; - const or_options_t *options = get_options(); const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS; int flav; @@ -259,25 +261,6 @@ router_reload_consensus_networkstatus(void) tor_free(filename); } - if (!current_consensus || - (stat(options->FallbackNetworkstatusFile, &st)==0 && - st.st_mtime > current_consensus->valid_after)) { - s = read_file_to_str(options->FallbackNetworkstatusFile, - RFTS_IGNORE_MISSING, NULL); - if (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); - } else { - log_notice(LD_FS, - "Loaded fallback consensus networkstatus from \"%s\"", - options->FallbackNetworkstatusFile); - } - tor_free(s); - } - } - if (!current_consensus) { if (!named_server_map) named_server_map = strmap_new(); @@ -572,7 +555,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, /* Now see whether we're missing any voters entirely. */ SMARTLIST_FOREACH(router_get_trusted_dir_servers(), - trusted_dir_server_t *, ds, + dir_server_t *, ds, { if ((ds->type & V3_DIRINFO) && !networkstatus_get_voter_by_id(consensus, ds->v3_identity_digest)) @@ -589,7 +572,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, if (warn >= 0) { SMARTLIST_FOREACH(unrecognized, networkstatus_voter_info_t *, voter, { - log(severity, LD_DIR, "Consensus includes unrecognized authority " + tor_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", @@ -597,16 +580,16 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, }); SMARTLIST_FOREACH(need_certs_from, networkstatus_voter_info_t *, voter, { - log(severity, LD_DIR, "Looks like we need to download a new " + tor_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, + SMARTLIST_FOREACH(missing_authorities, dir_server_t *, ds, { - log(severity, LD_DIR, "Consensus does not include configured " + tor_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)); @@ -642,7 +625,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, "because we were missing the keys.", n_missing_key); } joined = smartlist_join_strings(sl, " ", 0, NULL); - log(severity, LD_DIR, "%s", joined); + tor_log(severity, LD_DIR, "%s", joined); tor_free(joined); SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); @@ -678,7 +661,7 @@ networkstatus_get_cache_filename(const char *identity_digest) /** Helper for smartlist_sort: Compare two networkstatus objects by * publication date. */ static int -_compare_networkstatus_v2_published_on(const void **_a, const void **_b) +compare_networkstatus_v2_published_on_(const void **_a, const void **_b) { const networkstatus_v2_t *a = *_a, *b = *_b; if (a->published_on < b->published_on) @@ -746,7 +729,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at, int i, found; time_t now; int skewed = 0; - trusted_dir_server_t *trusted_dir = NULL; + dir_server_t *trusted_dir = NULL; const char *source_desc = NULL; char fp[HEX_DIGEST_LEN+1]; char published[ISO_TIME_LEN+1]; @@ -782,7 +765,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at, long delta = now - ns->published_on; format_time_interval(dbuf, sizeof(dbuf), delta); log_warn(LD_GENERAL, "Network status from %s was published %s in the " - "future (%s GMT). Check your time and date settings! " + "future (%s UTC). Check your time and date settings! " "Not caching.", source_desc, dbuf, published); control_event_general_status(LOG_WARN, @@ -802,7 +785,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at, } if (requested_fingerprints) { - if (smartlist_string_isin(requested_fingerprints, fp)) { + if (smartlist_contains_string(requested_fingerprints, fp)) { smartlist_string_remove(requested_fingerprints, fp); } else { if (source != NS_FROM_DIR_ALL) { @@ -912,7 +895,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at, networkstatus_v2_list_has_changed = 1; smartlist_sort(networkstatus_v2_list, - _compare_networkstatus_v2_published_on); + compare_networkstatus_v2_published_on_); if (!skewed) add_networkstatus_to_cache(s, source, ns); @@ -965,6 +948,17 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member) return tor_memcmp(key, rs->identity_digest, DIGEST_LEN); } +/** Helper for bsearching a list of routerstatus_t pointers: compare a + * digest in the key to the identity digest of a routerstatus_t. */ +int +compare_digest_to_vote_routerstatus_entry(const void *_key, + const void **_member) +{ + const char *key = _key; + const vote_routerstatus_t *vrs = *_member; + return tor_memcmp(key, vrs->status.identity_digest, DIGEST_LEN); +} + /** As networkstatus_v2_find_entry, but do not return a const pointer */ routerstatus_t * networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest) @@ -1151,7 +1145,7 @@ update_v2_networkstatus_cache_downloads(time_t now) if (authority) { /* An authority launches a separate connection for everybody. */ - SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) + SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ds) { char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */ tor_addr_t addr; @@ -1179,7 +1173,7 @@ update_v2_networkstatus_cache_downloads(time_t now) directory_initiate_command_routerstatus( &ds->fake_status, DIR_PURPOSE_FETCH_V2_NETWORKSTATUS, ROUTER_PURPOSE_GENERAL, - 0, /* Not private */ + DIRIND_ONEHOP, resource, NULL, 0 /* No payload. */, 0 /* No I-M-S. */); @@ -1449,18 +1443,6 @@ consensus_is_waiting_for_certs(void) ? 1 : 0; } -/** Return the network status with a given identity digest. */ -networkstatus_v2_t * -networkstatus_v2_get_by_digest(const char *digest) -{ - SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, - { - if (tor_memeq(ns->identity_digest, digest, DIGEST_LEN)) - return ns; - }); - return NULL; -} - /** Return the most recent consensus that we have downloaded, or NULL if we * don't have one. */ networkstatus_t * @@ -1541,13 +1523,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b) a->is_bad_exit != b->is_bad_exit || a->is_bad_directory != b->is_bad_directory || a->is_hs_dir != b->is_hs_dir || - a->version_known != b->version_known || - a->version_supports_begindir != b->version_supports_begindir || - a->version_supports_extrainfo_upload != - b->version_supports_extrainfo_upload || - a->version_supports_conditional_consensus != - b->version_supports_conditional_consensus || - a->version_supports_v3_dir != b->version_supports_v3_dir; + a->version_known != b->version_known; } /** Notify controllers of any router status entries that changed between @@ -1651,6 +1627,7 @@ networkstatus_set_current_consensus(const char *consensus, 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 */ + int old_ewma_enabled; if (flav < 0) { /* XXXX we don't handle unrecognized flavors yet. */ @@ -1686,9 +1663,6 @@ networkstatus_set_current_consensus(const char *consensus, if (from_cache && !accept_obsolete && c->valid_until < now-OLD_ROUTER_DESC_MAX_AGE) { - /* XXXX If 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 expired consensus. Discarding."); goto done; } @@ -1844,7 +1818,18 @@ networkstatus_set_current_consensus(const char *consensus, dirvote_recalculate_timing(options, now); routerstatus_list_update_named_server_map(); - cell_ewma_set_scale_factor(options, current_consensus); + + /* Update ewma and adjust policy if needed; first cache the old value */ + old_ewma_enabled = cell_ewma_enabled(); + /* Change the cell EWMA settings */ + cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus()); + /* If we just enabled ewma, set the cmux policy on all active channels */ + if (cell_ewma_enabled() && !old_ewma_enabled) { + channel_set_cmux_policy_everywhere(&ewma_policy); + } else if (!cell_ewma_enabled() && old_ewma_enabled) { + /* Turn it off everywhere */ + channel_set_cmux_policy_everywhere(NULL); + } /* XXXX024 this call might be unnecessary here: can changing the * current consensus really alter our view of any OR's rate limits? */ @@ -1875,7 +1860,7 @@ networkstatus_set_current_consensus(const char *consensus, format_iso_time(tbuf, c->valid_after); format_time_interval(dbuf, sizeof(dbuf), delta); log_warn(LD_GENERAL, "Our clock is %s behind the time published in the " - "consensus network status document (%s GMT). Tor needs an " + "consensus network status document (%s UTC). Tor needs an " "accurate clock to work correctly. Please check your time and " "date settings!", dbuf, tbuf); control_event_general_status(LOG_WARN, @@ -1904,11 +1889,12 @@ networkstatus_note_certs_arrived(void) if (!waiting->consensus) continue; if (networkstatus_check_consensus_signature(waiting->consensus, 0)>=0) { + char *waiting_body = waiting->body; if (!networkstatus_set_current_consensus( - waiting->body, + waiting_body, networkstatus_get_flavor_name(i), NSSET_WAS_WAITING_FOR_CERTS)) { - tor_free(waiting->body); + tor_free(waiting_body); } } } @@ -2007,7 +1993,7 @@ download_status_map_update_from_v2_networkstatus(void) digestmap_set(dl_status, d, s); } SMARTLIST_FOREACH_END(rs); } SMARTLIST_FOREACH_END(ns); - digestmap_free(v2_download_status_map, _tor_free); + digestmap_free(v2_download_status_map, tor_free_); v2_download_status_map = dl_status; networkstatus_v2_list_has_changed = 0; } @@ -2020,7 +2006,7 @@ routerstatus_list_update_named_server_map(void) if (!current_consensus) return; - strmap_free(named_server_map, _tor_free); + strmap_free(named_server_map, tor_free_); named_server_map = strmap_new(); strmap_free(unnamed_server_map, NULL); unnamed_server_map = strmap_new(); @@ -2043,7 +2029,7 @@ void routers_update_status_from_consensus_networkstatus(smartlist_t *routers, int reset_failures) { - trusted_dir_server_t *ds; + dir_server_t *ds; const or_options_t *options = get_options(); int authdir = authdir_mode_v2(options) || authdir_mode_v3(options); networkstatus_t *ns = current_consensus; @@ -2063,7 +2049,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, /* We have a routerstatus for this router. */ const char *digest = router->cache_info.identity_digest; - ds = router_get_trusteddirserver_by_digest(digest); + ds = router_get_fallback_dirserver_by_digest(digest); /* Is it the same descriptor, or only the same identity? */ if (tor_memeq(router->cache_info.signed_descriptor_digest, @@ -2141,9 +2127,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs) char * networkstatus_getinfo_helper_single(const routerstatus_t *rs) { - char buf[RS_ENTRY_LEN+1]; - routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT); - return tor_strdup(buf); + return routerstatus_format_entry(rs, NULL, NS_CONTROL_PORT, NULL); } /** Alloc and return a string describing routerstatuses for the most @@ -2264,6 +2248,21 @@ networkstatus_get_param(const networkstatus_t *ns, const char *param_name, default_val, min_val, max_val); } +/** + * Retrieve the consensus parameter that governs the + * fixed-point precision of our network balancing 'bandwidth-weights' + * (which are themselves integer consensus values). We divide them + * by this value and ensure they never exceed this value. + */ +int +networkstatus_get_weight_scale_param(networkstatus_t *ns) +{ + return networkstatus_get_param(ns, "bwweightscale", + BW_WEIGHT_SCALE, + BW_MIN_WEIGHT_SCALE, + BW_MAX_WEIGHT_SCALE); +} + /** 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 @@ -2280,7 +2279,7 @@ networkstatus_get_bw_weight(networkstatus_t *ns, const char *weight_name, if (!ns || !ns->weight_params) return default_val; - max = circuit_build_times_get_bw_scale(ns); + max = networkstatus_get_weight_scale_param(ns); param = get_net_param_from_list(ns->weight_params, weight_name, default_val, -1, BW_MAX_WEIGHT_SCALE); @@ -2321,6 +2320,30 @@ networkstatus_parse_flavor_name(const char *flavname) return -1; } +/** Return 0 if this routerstatus is obsolete, too new, isn't + * running, or otherwise not a descriptor that we would make any + * use of even if we had it. Else return 1. */ +int +client_would_use_router(const routerstatus_t *rs, time_t now, + const or_options_t *options) +{ + if (!rs->is_flagged_running && !options->FetchUselessDescriptors) { + /* If we had this router descriptor, we wouldn't even bother using it. + * But, if we want to have a complete list, fetch it anyway. */ + return 0; + } + if (rs->published_on + options->TestingEstimatedDescriptorPropagationTime + > now) { + /* Most caches probably don't have this descriptor yet. */ + return 0; + } + if (rs->published_on + OLD_ROUTER_DESC_MAX_AGE < now) { + /* We'd drop it immediately for being too old. */ + return 0; + } + return 1; +} + /** If <b>question</b> is a string beginning with "ns/" in a format the * control interface expects for a GETINFO question, set *<b>answer</b> to a * newly-allocated string containing networkstatus lines for the appropriate @@ -2351,8 +2374,11 @@ getinfo_helper_networkstatus(control_connection_t *conn, return 0; } else if (!strcmpstart(question, "ns/id/")) { char d[DIGEST_LEN]; + const char *q = question + 6; + if (*q == '$') + ++q; - if (base16_decode(d, DIGEST_LEN, question+6, strlen(question+6))) { + if (base16_decode(d, DIGEST_LEN, q, strlen(q))) { *errmsg = "Data not decodeable as hex"; return -1; } @@ -2383,7 +2409,7 @@ networkstatus_free_all(void) networkstatus_v2_list = NULL; } - digestmap_free(v2_download_status_map, _tor_free); + digestmap_free(v2_download_status_map, tor_free_); v2_download_status_map = NULL; networkstatus_vote_free(current_ns_consensus); networkstatus_vote_free(current_md_consensus); @@ -2398,7 +2424,7 @@ networkstatus_free_all(void) tor_free(waiting->body); } - strmap_free(named_server_map, _tor_free); + 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 index 0af17512dd..761f8e7f0e 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for networkstatus.c. **/ -#ifndef _TOR_NETWORKSTATUS_H -#define _TOR_NETWORKSTATUS_H +#ifndef TOR_NETWORKSTATUS_H +#define TOR_NETWORKSTATUS_H /** How old do we allow a v2 network-status to get before removing it * completely? */ @@ -38,6 +38,8 @@ int router_set_networkstatus_v2(const char *s, time_t arrived_at, void networkstatus_v2_list_clean(time_t now); int compare_digest_to_routerstatus_entry(const void *_key, const void **_member); +int compare_digest_to_vote_routerstatus_entry(const void *_key, + const void **_member); const routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest); const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns, @@ -71,7 +73,8 @@ int should_delay_dir_fetches(const or_options_t *options); void update_networkstatus_downloads(time_t now); void update_certificate_downloads(time_t now); int consensus_is_waiting_for_certs(void); -networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest); +int client_would_use_router(const routerstatus_t *rs, time_t now, + const or_options_t *options); networkstatus_t *networkstatus_get_latest_consensus(void); networkstatus_t *networkstatus_get_latest_consensus_by_flavor( consensus_flavor_t f); @@ -110,6 +113,7 @@ 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); +int networkstatus_get_weight_scale_param(networkstatus_t *ns); #endif diff --git a/src/or/nodelist.c b/src/or/nodelist.c index d17850888d..178f084b69 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -1,23 +1,30 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "or.h" +#include "address.h" #include "config.h" +#include "control.h" #include "dirserv.h" +#include "geoip.h" +#include "main.h" #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" +#include "rendservice.h" #include "router.h" #include "routerlist.h" +#include "routerset.h" #include <string.h> static void nodelist_drop_node(node_t *node, int remove_from_ht); static void node_free(node_t *node); +static void update_router_have_minimum_dir_info(void); /** A nodelist_t holds a node_t object for every router we're "willing to use * for something". Specifically, it should hold a node_t for every node that @@ -115,19 +122,47 @@ node_get_or_create(const char *identity_digest) return node; } -/** Add <b>ri</b> to the nodelist. */ +/** Called when a node's address changes. */ +static void +node_addrs_changed(node_t *node) +{ + node->last_reachable = node->last_reachable6 = 0; + node->country = -1; +} + +/** Add <b>ri</b> to an appropriate node in the nodelist. If we replace an + * old routerinfo, and <b>ri_old_out</b> is not NULL, set *<b>ri_old_out</b> + * to the previous routerinfo. + */ node_t * -nodelist_add_routerinfo(routerinfo_t *ri) +nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out) { node_t *node; + const char *id_digest; + int had_router = 0; + tor_assert(ri); + init_nodelist(); - node = node_get_or_create(ri->cache_info.identity_digest); + id_digest = ri->cache_info.identity_digest; + node = node_get_or_create(id_digest); + + if (node->ri) { + if (!routers_have_same_or_addrs(node->ri, ri)) { + node_addrs_changed(node); + } + had_router = 1; + if (ri_old_out) + *ri_old_out = node->ri; + } else { + if (ri_old_out) + *ri_old_out = NULL; + } node->ri = ri; if (node->country == -1) node_set_country(node); - if (authdir_mode(get_options())) { + if (authdir_mode(get_options()) && !had_router) { const char *discard=NULL; uint32_t status = dirserv_router_get_status(ri, &discard); dirserv_set_node_flags_from_authoritative_status(node, status); @@ -167,7 +202,7 @@ nodelist_add_microdesc(microdesc_t *md) return node; } -/** Tell the nodelist that the current usable consensus to <b>ns</b>. +/** Tell the nodelist that the current usable consensus is <b>ns</b>. * This makes the nodelist change all of the routerstatus entries for * the nodes, drop nodes that no longer have enough info to get used, * and grab microdescriptors into nodes as appropriate. @@ -177,6 +212,7 @@ nodelist_set_consensus(networkstatus_t *ns) { const or_options_t *options = get_options(); int authdir = authdir_mode_v2(options) || authdir_mode_v3(options); + int client = !server_mode(options); init_nodelist(); if (ns->flavor == FLAV_MICRODESC) @@ -213,6 +249,11 @@ nodelist_set_consensus(networkstatus_t *ns) node->is_bad_directory = rs->is_bad_directory; node->is_bad_exit = rs->is_bad_exit; node->is_hs_dir = rs->is_hs_dir; + node->ipv6_preferred = 0; + if (client && options->ClientPreferIPv6ORPort == 1 && + (tor_addr_is_null(&rs->ipv6_addr) == 0 || + (node->md && tor_addr_is_null(&node->md->ipv6_addr) == 0))) + node->ipv6_preferred = 1; } } SMARTLIST_FOREACH_END(rs); @@ -231,7 +272,8 @@ nodelist_set_consensus(networkstatus_t *ns) node->is_valid = node->is_running = node->is_hs_dir = node->is_fast = node->is_stable = node->is_possible_guard = node->is_exit = - node->is_bad_exit = node->is_bad_directory = 0; + node->is_bad_exit = node->is_bad_directory = + node->ipv6_preferred = 0; } } } SMARTLIST_FOREACH_END(node); @@ -582,7 +624,7 @@ node_is_dir(const node_t *node) } /** Return true iff <b>node</b> has either kind of usable descriptor -- that - * is, a routerdecriptor or a microdescriptor. */ + * is, a routerdescriptor or a microdescriptor. */ int node_has_descriptor(const node_t *node) { @@ -646,6 +688,24 @@ node_exit_policy_rejects_all(const node_t *node) return 1; } +/** Return true iff the exit policy for <b>node</b> is such that we can treat + * rejecting an address of type <b>family</b> unexpectedly as a sign of that + * node's failure. */ +int +node_exit_policy_is_exact(const node_t *node, sa_family_t family) +{ + if (family == AF_UNSPEC) { + return 1; /* Rejecting an address but not telling us what address + * is a bad sign. */ + } else if (family == AF_INET) { + return node->ri != NULL; + } else if (family == AF_INET6) { + return 0; + } + tor_fragile_assert(); + return 1; +} + /** Return list of tor_addr_port_t with all OR ports (in the sense IP * addr + TCP port) for <b>node</b>. Caller must free all elements * using tor_free() and free the list using smartlist_free(). @@ -682,19 +742,6 @@ node_get_all_orports(const node_t *node) return sl; } -/** Copy the primary (IPv4) OR port (IP address and TCP port) for - * <b>node</b> into *<b>ap_out</b>. */ -void -node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out) -{ - if (node->ri) { - router_get_prim_orport(node->ri, ap_out); - } else if (node->rs) { - tor_addr_from_ipv4h(&ap_out->addr, node->rs->addr); - ap_out->port = node->rs->or_port; - } -} - /** Wrapper around node_get_prim_orport for backward compatibility. */ void @@ -718,36 +765,6 @@ node_get_prim_addr_ipv4h(const node_t *node) return 0; } -/** Copy the preferred OR port (IP address and TCP port) for - * <b>node</b> into <b>ap_out</b>. */ -void -node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out) -{ - if (node->ri) { - router_get_pref_orport(node->ri, ap_out); - } else if (node->rs) { - /* No IPv6 in routerstatus_t yet. XXXprop186 ok for private - bridges but needs fixing */ - tor_addr_from_ipv4h(&ap_out->addr, node->rs->addr); - ap_out->port = node->rs->or_port; - } -} - -/** Copy the preferred IPv6 OR port (address and TCP port) for - * <b>node</b> into *<b>ap_out</b>. */ -void -node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out) -{ - if (node->ri) { - router_get_pref_ipv6_orport(node->ri, ap_out); - } else if (node->rs) { - /* No IPv6 in routerstatus_t yet. XXXprop186 ok for private - bridges but needs fixing */ - tor_addr_make_unspec(&ap_out->addr); - ap_out->port = 0; - } -} - /** Copy a string representation of an IP address for <b>node</b> into * the <b>len</b>-byte buffer at <b>buf</b>. */ void @@ -818,3 +835,678 @@ node_get_declared_family(const node_t *node) return NULL; } +/** Return 1 if we prefer the IPv6 address and OR TCP port of + * <b>node</b>, else 0. + * + * We prefer the IPv6 address if the router has an IPv6 address and + * i) the node_t says that it prefers IPv6 + * or + * ii) the router has no IPv4 address. */ +int +node_ipv6_preferred(const node_t *node) +{ + tor_addr_port_t ipv4_addr; + node_assert_ok(node); + + if (node->ipv6_preferred || node_get_prim_orport(node, &ipv4_addr)) { + if (node->ri) + return !tor_addr_is_null(&node->ri->ipv6_addr); + if (node->md) + return !tor_addr_is_null(&node->md->ipv6_addr); + if (node->rs) + return !tor_addr_is_null(&node->rs->ipv6_addr); + } + return 0; +} + +/** Copy the primary (IPv4) OR port (IP address and TCP port) for + * <b>node</b> into *<b>ap_out</b>. Return 0 if a valid address and + * port was copied, else return non-zero.*/ +int +node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out) +{ + node_assert_ok(node); + tor_assert(ap_out); + + if (node->ri) { + if (node->ri->addr == 0 || node->ri->or_port == 0) + return -1; + tor_addr_from_ipv4h(&ap_out->addr, node->ri->addr); + ap_out->port = node->ri->or_port; + return 0; + } + if (node->rs) { + if (node->rs->addr == 0 || node->rs->or_port == 0) + return -1; + tor_addr_from_ipv4h(&ap_out->addr, node->rs->addr); + ap_out->port = node->rs->or_port; + return 0; + } + return -1; +} + +/** Copy the preferred OR port (IP address and TCP port) for + * <b>node</b> into *<b>ap_out</b>. */ +void +node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out) +{ + const or_options_t *options = get_options(); + tor_assert(ap_out); + + /* Cheap implementation of config option ClientUseIPv6 -- simply + don't prefer IPv6 when ClientUseIPv6 is not set and we're not a + client running with bridges. See #4455 for more on this subject. + + Note that this filter is too strict since we're hindering not + only clients! Erring on the safe side shouldn't be a problem + though. XXX move this check to where outgoing connections are + made? -LN */ + if ((options->ClientUseIPv6 || options->UseBridges) && + node_ipv6_preferred(node)) { + node_get_pref_ipv6_orport(node, ap_out); + } else { + node_get_prim_orport(node, ap_out); + } +} + +/** Copy the preferred IPv6 OR port (IP address and TCP port) for + * <b>node</b> into *<b>ap_out</b>. */ +void +node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out) +{ + node_assert_ok(node); + tor_assert(ap_out); + + /* We prefer the microdesc over a potential routerstatus here. They + are not being synchronised atm so there might be a chance that + they differ at some point, f.ex. when flipping + UseMicrodescriptors? -LN */ + + if (node->ri) { + tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr); + ap_out->port = node->ri->ipv6_orport; + } else if (node->md) { + tor_addr_copy(&ap_out->addr, &node->md->ipv6_addr); + ap_out->port = node->md->ipv6_orport; + } else if (node->rs) { + tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr); + ap_out->port = node->rs->ipv6_orport; + } +} + +/** Return true iff <b>node</b> has a curve25519 onion key. */ +int +node_has_curve25519_onion_key(const node_t *node) +{ + if (node->ri) + return node->ri->onion_curve25519_pkey != NULL; + else if (node->md) + return node->md->onion_curve25519_pkey != NULL; + else + return 0; +} + +/** Refresh the country code of <b>ri</b>. This function MUST be called on + * each router when the GeoIP database is reloaded, and on all new routers. */ +void +node_set_country(node_t *node) +{ + tor_addr_t addr = TOR_ADDR_NULL; + + /* XXXXipv6 */ + if (node->rs) + tor_addr_from_ipv4h(&addr, node->rs->addr); + else if (node->ri) + tor_addr_from_ipv4h(&addr, node->ri->addr); + + node->country = geoip_get_country_by_addr(&addr); +} + +/** Set the country code of all routers in the routerlist. */ +void +nodelist_refresh_countries(void) +{ + smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, node_t *, node, + node_set_country(node)); +} + +/** Return true iff router1 and router2 have similar enough network addresses + * that we should treat them as being in the same family */ +static INLINE int +addrs_in_same_network_family(const tor_addr_t *a1, + const tor_addr_t *a2) +{ + return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC); +} + +/** Return true if <b>node</b>'s nickname matches <b>nickname</b> + * (case-insensitive), or if <b>node's</b> identity key digest + * matches a hexadecimal value stored in <b>nickname</b>. Return + * false otherwise. */ +static int +node_nickname_matches(const node_t *node, const char *nickname) +{ + const char *n = node_get_nickname(node); + if (n && nickname[0]!='$' && !strcasecmp(n, nickname)) + return 1; + return hex_digest_nickname_matches(nickname, + node->identity, + n, + node_is_named(node)); +} + +/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */ +static INLINE int +node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node) +{ + if (!lst) return 0; + SMARTLIST_FOREACH(lst, const char *, name, { + if (node_nickname_matches(node, name)) + return 1; + }); + return 0; +} + +/** Return true iff r1 and r2 are in the same family, but not the same + * router. */ +int +nodes_in_same_family(const node_t *node1, const node_t *node2) +{ + const or_options_t *options = get_options(); + + /* Are they in the same family because of their addresses? */ + if (options->EnforceDistinctSubnets) { + tor_addr_t a1, a2; + node_get_addr(node1, &a1); + node_get_addr(node2, &a2); + if (addrs_in_same_network_family(&a1, &a2)) + return 1; + } + + /* Are they in the same family because the agree they are? */ + { + const smartlist_t *f1, *f2; + f1 = node_get_declared_family(node1); + f2 = node_get_declared_family(node2); + if (f1 && f2 && + node_in_nickname_smartlist(f1, node2) && + node_in_nickname_smartlist(f2, node1)) + return 1; + } + + /* Are they in the same option because the user says they are? */ + if (options->NodeFamilySets) { + SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { + if (routerset_contains_node(rs, node1) && + routerset_contains_node(rs, node2)) + return 1; + }); + } + + return 0; +} + +/** + * Add all the family of <b>node</b>, including <b>node</b> itself, to + * the smartlist <b>sl</b>. + * + * This is used to make sure we don't pick siblings in a single path, or + * pick more than one relay from a family for our entry guard list. + * Note that a node may be added to <b>sl</b> more than once if it is + * part of <b>node</b>'s family for more than one reason. + */ +void +nodelist_add_node_and_family(smartlist_t *sl, const node_t *node) +{ + const smartlist_t *all_nodes = nodelist_get_list(); + const smartlist_t *declared_family; + const or_options_t *options = get_options(); + + tor_assert(node); + + declared_family = node_get_declared_family(node); + + /* Let's make sure that we have the node itself, if it's a real node. */ + { + const node_t *real_node = node_get_by_id(node->identity); + if (real_node) + smartlist_add(sl, (node_t*)real_node); + } + + /* First, add any nodes with similar network addresses. */ + if (options->EnforceDistinctSubnets) { + tor_addr_t node_addr; + node_get_addr(node, &node_addr); + + SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) { + tor_addr_t a; + node_get_addr(node2, &a); + if (addrs_in_same_network_family(&a, &node_addr)) + smartlist_add(sl, (void*)node2); + } SMARTLIST_FOREACH_END(node2); + } + + /* Now, add all nodes in the declared_family of this node, if they + * also declare this node to be in their family. */ + if (declared_family) { + /* Add every r such that router declares familyness with node, and node + * declares familyhood with router. */ + SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) { + const node_t *node2; + const smartlist_t *family2; + if (!(node2 = node_get_by_nickname(name, 0))) + continue; + if (!(family2 = node_get_declared_family(node2))) + continue; + SMARTLIST_FOREACH_BEGIN(family2, const char *, name2) { + if (node_nickname_matches(node, name2)) { + smartlist_add(sl, (void*)node2); + break; + } + } SMARTLIST_FOREACH_END(name2); + } SMARTLIST_FOREACH_END(name); + } + + /* If the user declared any families locally, honor those too. */ + if (options->NodeFamilySets) { + SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { + if (routerset_contains_node(rs, node)) { + routerset_get_all_nodes(sl, rs, NULL, 0); + } + }); + } +} + +/** Find a router that's up, that has this IP address, and + * that allows exit to this address:port, or return NULL if there + * isn't a good one. + * Don't exit enclave to excluded relays -- it wouldn't actually + * hurt anything, but this way there are fewer confused users. + */ +const node_t * +router_find_exact_exit_enclave(const char *address, uint16_t port) +{/*XXXX MOVE*/ + uint32_t addr; + struct in_addr in; + tor_addr_t a; + const or_options_t *options = get_options(); + + if (!tor_inet_aton(address, &in)) + return NULL; /* it's not an IP already */ + addr = ntohl(in.s_addr); + + tor_addr_from_ipv4h(&a, addr); + + SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, { + if (node_get_addr_ipv4h(node) == addr && + node->is_running && + compare_tor_addr_to_node_policy(&a, port, node) == + ADDR_POLICY_ACCEPTED && + !routerset_contains_node(options->ExcludeExitNodesUnion_, node)) + return node; + }); + return NULL; +} + +/** Return 1 if <b>router</b> is not suitable for these parameters, else 0. + * If <b>need_uptime</b> is non-zero, we require a minimum uptime. + * If <b>need_capacity</b> is non-zero, we require a minimum advertised + * bandwidth. + * If <b>need_guard</b>, we require that the router is a possible entry guard. + */ +int +node_is_unreliable(const node_t *node, int need_uptime, + int need_capacity, int need_guard) +{ + if (need_uptime && !node->is_stable) + return 1; + if (need_capacity && !node->is_fast) + return 1; + if (need_guard && !node->is_possible_guard) + return 1; + return 0; +} + +/** Return 1 if all running sufficiently-stable routers we can use will reject + * addr:port. Return 0 if any might accept it. */ +int +router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port, + int need_uptime) +{ + addr_policy_result_t r; + + SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { + if (node->is_running && + !node_is_unreliable(node, need_uptime, 0, 0)) { + + r = compare_tor_addr_to_node_policy(addr, port, node); + + if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED) + return 0; /* this one could be ok. good enough. */ + } + } SMARTLIST_FOREACH_END(node); + return 1; /* all will reject. */ +} + +/** Mark the router with ID <b>digest</b> as running or non-running + * in our routerlist. */ +void +router_set_status(const char *digest, int up) +{ + node_t *node; + tor_assert(digest); + + SMARTLIST_FOREACH(router_get_fallback_dir_servers(), + dir_server_t *, d, + if (tor_memeq(d->digest, digest, DIGEST_LEN)) + d->is_running = up); + + SMARTLIST_FOREACH(router_get_trusted_dir_servers(), + dir_server_t *, d, + if (tor_memeq(d->digest, digest, DIGEST_LEN)) + d->is_running = up); + + node = node_get_mutable_by_id(digest); + if (node) { +#if 0 + log_debug(LD_DIR,"Marking router %s as %s.", + node_describe(node), up ? "up" : "down"); +#endif + if (!up && node_is_me(node) && !net_is_disabled()) + log_warn(LD_NET, "We just marked ourself as down. Are your external " + "addresses reachable?"); + node->is_running = up; + } + + router_dir_info_changed(); +} + +/** True iff, the last time we checked whether we had enough directory info + * to build circuits, the answer was "yes". */ +static int have_min_dir_info = 0; +/** True iff enough has changed since the last time we checked whether we had + * enough directory info to build circuits that our old answer can no longer + * be trusted. */ +static int need_to_update_have_min_dir_info = 1; +/** String describing what we're missing before we have enough directory + * info. */ +static char dir_info_status[256] = ""; + +/** Return true iff we have enough networkstatus and router information to + * start building circuits. Right now, this means "more than half the + * networkstatus documents, and at least 1/4 of expected routers." */ +//XXX should consider whether we have enough exiting nodes here. +int +router_have_minimum_dir_info(void) +{ + if (PREDICT_UNLIKELY(need_to_update_have_min_dir_info)) { + update_router_have_minimum_dir_info(); + need_to_update_have_min_dir_info = 0; + } + return have_min_dir_info; +} + +/** Called when our internal view of the directory has changed. This can be + * when the authorities change, networkstatuses change, the list of routerdescs + * changes, or number of running routers changes. + */ +void +router_dir_info_changed(void) +{ + need_to_update_have_min_dir_info = 1; + rend_hsdir_routers_changed(); +} + +/** Return a string describing what we're missing before we have enough + * directory info. */ +const char * +get_dir_info_status_string(void) +{ + return dir_info_status; +} + +/** 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>. If <b>in_set</b> is non-NULL, only consider those + * routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes + * with the Exit flag. If *descs_out is present, add a node_t for each + * usable descriptor to it. + */ +static void +count_usable_descriptors(int *num_present, int *num_usable, + smartlist_t *descs_out, + const networkstatus_t *consensus, + const or_options_t *options, time_t now, + routerset_t *in_set, int exit_only) +{ + const int md = (consensus->flavor == FLAV_MICRODESC); + *num_present = 0, *num_usable=0; + + SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs) + { + const node_t *node = node_get_by_id(rs->identity_digest); + if (!node) + continue; /* This would be a bug: every entry in the consensus is + * supposed to have a node. */ + if (exit_only && ! rs->is_exit) + continue; + if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1)) + continue; + if (client_would_use_router(rs, now, options)) { + const char * const digest = rs->descriptor_digest; + int present; + ++*num_usable; /* the consensus says we want it. */ + if (md) + present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest); + else + present = NULL != router_get_by_descriptor_digest(digest); + if (present) { + /* we have the descriptor listed in the consensus. */ + ++*num_present; + } + if (descs_out) + smartlist_add(descs_out, (node_t*)node); + } + } + SMARTLIST_FOREACH_END(rs); + + log_debug(LD_DIR, "%d usable, %d present (%s%s).", + *num_usable, *num_present, + md ? "microdesc" : "desc", exit_only ? " exits" : "s"); +} + +/** Return an extimate of which fraction of usable paths through the Tor + * network we have available for use. */ +static double +compute_frac_paths_available(const networkstatus_t *consensus, + const or_options_t *options, time_t now, + int *num_present_out, int *num_usable_out, + char **status_out) +{ + smartlist_t *guards = smartlist_new(); + smartlist_t *mid = smartlist_new(); + smartlist_t *exits = smartlist_new(); + smartlist_t *myexits= smartlist_new(); + double f_guard, f_mid, f_exit, f_myexit; + int np, nu; /* Ignored */ + const int authdir = authdir_mode_v2(options) || authdir_mode_v3(options); + + count_usable_descriptors(num_present_out, num_usable_out, + mid, consensus, options, now, NULL, 0); + if (options->EntryNodes) { + count_usable_descriptors(&np, &nu, guards, consensus, options, now, + options->EntryNodes, 0); + } else { + SMARTLIST_FOREACH(mid, const node_t *, node, { + if (authdir) { + if (node->rs && node->rs->is_possible_guard) + smartlist_add(guards, (node_t*)node); + } else { + if (node->is_possible_guard) + smartlist_add(guards, (node_t*)node); + } + }); + } + + count_usable_descriptors(&np, &nu, exits, consensus, options, now, + NULL, 1); + count_usable_descriptors(&np, &nu, myexits, consensus, options, now, + options->ExitNodes, 1); + + f_guard = frac_nodes_with_descriptors(guards, WEIGHT_FOR_GUARD); + f_mid = frac_nodes_with_descriptors(mid, WEIGHT_FOR_MID); + f_exit = frac_nodes_with_descriptors(exits, WEIGHT_FOR_EXIT); + f_myexit= frac_nodes_with_descriptors(myexits,WEIGHT_FOR_EXIT); + + smartlist_free(guards); + smartlist_free(mid); + smartlist_free(exits); + smartlist_free(myexits); + + /* This is a tricky point here: we don't want to make it easy for a + * directory to trickle exits to us until it learns which exits we have + * configured, so require that we have a threshold both of total exits + * and usable exits. */ + if (f_myexit < f_exit) + f_exit = f_myexit; + + tor_asprintf(status_out, + "%d%% of guards bw, " + "%d%% of midpoint bw, and " + "%d%% of exit bw", + (int)(f_guard*100), + (int)(f_mid*100), + (int)(f_exit*100)); + + return f_guard * f_mid * f_exit; +} + +/** We just fetched a new set of descriptors. Compute how far through + * the "loading descriptors" bootstrapping phase we are, so we can inform + * the controller of our progress. */ +int +count_loading_descriptors_progress(void) +{ + int num_present = 0, num_usable=0; + time_t now = time(NULL); + const networkstatus_t *consensus = + networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor()); + double fraction; + + if (!consensus) + return 0; /* can't count descriptors if we have no list of them */ + + count_usable_descriptors(&num_present, &num_usable, NULL, + consensus, get_options(), now, NULL, 0); + + if (num_usable == 0) + return 0; /* don't div by 0 */ + fraction = num_present / (num_usable/4.); + if (fraction > 1.0) + return 0; /* it's not the number of descriptors holding us back */ + return BOOTSTRAP_STATUS_LOADING_DESCRIPTORS + (int) + (fraction*(BOOTSTRAP_STATUS_CONN_OR-1 - + BOOTSTRAP_STATUS_LOADING_DESCRIPTORS)); +} + +/** Return the fraction of paths needed before we're willing to build + * circuits, as configured in <b>options</b>, or in the consensus <b>ns</b>. */ +static double +get_frac_paths_needed_for_circs(const or_options_t *options, + const networkstatus_t *ns) +{ +#define DFLT_PCT_USABLE_NEEDED 60 + if (options->PathsNeededToBuildCircuits >= 0.0) { + return options->PathsNeededToBuildCircuits; + } else { + return networkstatus_get_param(ns, "min_paths_for_circs_pct", + DFLT_PCT_USABLE_NEEDED, + 25, 95)/100.0; + } +} + +/** Change the value of have_min_dir_info, setting it true iff we have enough + * network and router information to build circuits. Clear the value of + * need_to_update_have_min_dir_info. */ +static void +update_router_have_minimum_dir_info(void) +{ + time_t now = time(NULL); + int res; + const or_options_t *options = get_options(); + const networkstatus_t *consensus = + networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor()); + int using_md; + + if (!consensus) { + if (!networkstatus_get_latest_consensus()) + strlcpy(dir_info_status, "We have no usable consensus.", + sizeof(dir_info_status)); + else + strlcpy(dir_info_status, "We have no recent usable consensus.", + sizeof(dir_info_status)); + res = 0; + goto done; + } + + if (should_delay_dir_fetches(get_options())) { + log_notice(LD_DIR, "no known bridge descriptors running yet; stalling"); + strlcpy(dir_info_status, "No live bridge descriptors.", + sizeof(dir_info_status)); + res = 0; + goto done; + } + + using_md = consensus->flavor == FLAV_MICRODESC; + + { + char *status = NULL; + int num_present=0, num_usable=0; + double paths = compute_frac_paths_available(consensus, options, now, + &num_present, &num_usable, + &status); + + if (paths < get_frac_paths_needed_for_circs(options,consensus)) { + tor_snprintf(dir_info_status, sizeof(dir_info_status), + "We need more %sdescriptors: we have %d/%d, and " + "can only build %d%% of likely paths. (We have %s.)", + using_md?"micro":"", num_present, num_usable, + (int)(paths*100), status); + /* log_notice(LD_NET, "%s", dir_info_status); */ + tor_free(status); + res = 0; + control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); + goto done; + } + + tor_free(status); + res = 1; + } + + done: + if (res && !have_min_dir_info) { + log_notice(LD_DIR, + "We now have enough directory information to build circuits."); + control_event_client_status(LOG_NOTICE, "ENOUGH_DIR_INFO"); + control_event_bootstrap(BOOTSTRAP_STATUS_CONN_OR, 0); + } + if (!res && have_min_dir_info) { + int quiet = directory_too_idle_to_fetch_descriptors(options, now); + tor_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; + need_to_update_have_min_dir_info = 0; +} + diff --git a/src/or/nodelist.h b/src/or/nodelist.h index 1e9da88d4e..8a4665a8bf 100644 --- a/src/or/nodelist.h +++ b/src/or/nodelist.h @@ -1,21 +1,25 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** - * \file microdesc.h - * \brief Header file for microdesc.c. + * \file nodelist.h + * \brief Header file for nodelist.c. **/ -#ifndef _TOR_NODELIST_H -#define _TOR_NODELIST_H +#ifndef TOR_NODELIST_H +#define TOR_NODELIST_H + +#define node_assert_ok(n) STMT_BEGIN { \ + tor_assert((n)->ri || (n)->rs); \ + } STMT_END node_t *node_get_mutable_by_id(const char *identity_digest); const node_t *node_get_by_id(const char *identity_digest); const node_t *node_get_by_hex_id(const char *identity_digest); -node_t *nodelist_add_routerinfo(routerinfo_t *ri); +node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out); node_t *nodelist_add_microdesc(microdesc_t *md); void nodelist_set_consensus(networkstatus_t *ns); @@ -37,19 +41,21 @@ int node_get_purpose(const node_t *node); (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE) int node_is_me(const node_t *node); int node_exit_policy_rejects_all(const node_t *node); +int node_exit_policy_is_exact(const node_t *node, sa_family_t family); smartlist_t *node_get_all_orports(const node_t *node); -void node_get_prim_orport(const node_t *node, tor_addr_port_t *addr_port_out); -void node_get_pref_orport(const node_t *node, tor_addr_port_t *addr_port_out); -void node_get_pref_ipv6_orport(const node_t *node, - tor_addr_port_t *addr_port_out); -uint32_t node_get_prim_addr_ipv4h(const node_t *node); int node_allows_single_hop_exits(const node_t *node); const char *node_get_nickname(const node_t *node); const char *node_get_platform(const node_t *node); +uint32_t node_get_prim_addr_ipv4h(const node_t *node); void node_get_address_string(const node_t *node, char *cp, size_t len); long node_get_declared_uptime(const node_t *node); time_t node_get_published_on(const node_t *node); const smartlist_t *node_get_declared_family(const node_t *node); +int node_ipv6_preferred(const node_t *node); +int node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out); +void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out); +void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out); +int node_has_curve25519_onion_key(const node_t *node); smartlist_t *nodelist_get_list(void); @@ -57,11 +63,22 @@ smartlist_t *nodelist_get_list(void); void node_get_addr(const node_t *node, tor_addr_t *addr_out); #define node_get_addr_ipv4h(n) node_get_prim_addr_ipv4h((n)) -/* XXXX These need to move out of routerlist.c */ void nodelist_refresh_countries(void); void node_set_country(node_t *node); void nodelist_add_node_and_family(smartlist_t *nodes, const node_t *node); int nodes_in_same_family(const node_t *node1, const node_t *node2); +const node_t *router_find_exact_exit_enclave(const char *address, + uint16_t port); +int node_is_unreliable(const node_t *router, int need_uptime, + int need_capacity, int need_guard); +int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port, + int need_uptime); +void router_set_status(const char *digest, int up); +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); + #endif diff --git a/src/or/ntmain.c b/src/or/ntmain.c index d001f7be13..8b67b86822 100644 --- a/src/or/ntmain.c +++ b/src/or/ntmain.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define MAIN_PRIVATE diff --git a/src/or/ntmain.h b/src/or/ntmain.h index 07fdcf466b..d3027936cd 100644 --- a/src/or/ntmain.h +++ b/src/or/ntmain.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for ntmain.c. **/ -#ifndef _TOR_NTMAIN_H -#define _TOR_NTMAIN_H +#ifndef TOR_NTMAIN_H +#define TOR_NTMAIN_H #ifdef _WIN32 #if !defined (WINCE) diff --git a/src/or/onion.c b/src/or/onion.c index f8c4d72b5a..1a0bcf106e 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -1,74 +1,158 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** * \file onion.c - * \brief Functions to queue create cells, and handle onionskin - * parsing and creation. + * \brief Functions to queue create cells, wrap the various onionskin types, + * and parse and create the CREATE cell and its allies. **/ #include "or.h" #include "circuitlist.h" #include "config.h" +#include "cpuworker.h" +#include "networkstatus.h" #include "onion.h" +#include "onion_fast.h" +#include "onion_ntor.h" +#include "onion_tap.h" +#include "relay.h" #include "rephist.h" +#include "router.h" +#include "tor_queue.h" /** Type for a linked list of circuits that are waiting for a free CPU worker * to process a waiting onion handshake. */ typedef struct onion_queue_t { + TOR_TAILQ_ENTRY(onion_queue_t) next; or_circuit_t *circ; - char *onionskin; + uint16_t handshake_type; + create_cell_t *onionskin; time_t when_added; - struct onion_queue_t *next; } onion_queue_t; /** 5 seconds on the onion queue til we just send back a destroy */ #define ONIONQUEUE_WAIT_CUTOFF 5 -/** First and last elements in the linked list of circuits waiting for CPU - * workers, or NULL if the list is empty. - * @{ */ -static onion_queue_t *ol_list=NULL; -static onion_queue_t *ol_tail=NULL; -/**@}*/ -/** Length of ol_list */ -static int ol_length=0; +/** Array of queues of circuits waiting for CPU workers. An element is NULL + * if that queue is empty.*/ +TOR_TAILQ_HEAD(onion_queue_head_t, onion_queue_t) + ol_list[MAX_ONION_HANDSHAKE_TYPE+1] = { + TOR_TAILQ_HEAD_INITIALIZER(ol_list[0]), /* tap */ + TOR_TAILQ_HEAD_INITIALIZER(ol_list[1]), /* fast */ + TOR_TAILQ_HEAD_INITIALIZER(ol_list[2]), /* ntor */ +}; + +/** Number of entries of each type currently in each element of ol_list[]. */ +static int ol_entries[MAX_ONION_HANDSHAKE_TYPE+1]; + +static int num_ntors_per_tap(void); +static void onion_queue_entry_remove(onion_queue_t *victim); + +/* XXXX024 Check lengths vs MAX_ONIONSKIN_{CHALLENGE,REPLY}_LEN. + * + * (By which I think I meant, "make sure that no + * X_ONIONSKIN_CHALLENGE/REPLY_LEN is greater than + * MAX_ONIONSKIN_CHALLENGE/REPLY_LEN." Also, make sure that we can pass + * over-large values via EXTEND2/EXTENDED2, for future-compatibility.*/ + +/** Return true iff we have room to queue another oninoskin of type + * <b>type</b>. */ +static int +have_room_for_onionskin(uint16_t type) +{ + const or_options_t *options = get_options(); + int num_cpus; + uint64_t tap_usec, ntor_usec; + uint64_t ntor_during_tap_usec, tap_during_ntor_usec; + + /* If we've got fewer than 50 entries, we always have room for one more. */ + if (ol_entries[type] < 50) + return 1; + num_cpus = get_num_cpus(options); + /* Compute how many microseconds we'd expect to need to clear all + * onionskins in various combinations of the queues. */ + + /* How long would it take to process all the TAP cells in the queue? */ + tap_usec = estimated_usec_for_onionskins( + ol_entries[ONION_HANDSHAKE_TYPE_TAP], + ONION_HANDSHAKE_TYPE_TAP) / num_cpus; + + /* How long would it take to process all the NTor cells in the queue? */ + ntor_usec = estimated_usec_for_onionskins( + ol_entries[ONION_HANDSHAKE_TYPE_NTOR], + ONION_HANDSHAKE_TYPE_NTOR) / num_cpus; + + /* How long would it take to process the tap cells that we expect to + * process while draining the ntor queue? */ + tap_during_ntor_usec = estimated_usec_for_onionskins( + MIN(ol_entries[ONION_HANDSHAKE_TYPE_TAP], + ol_entries[ONION_HANDSHAKE_TYPE_NTOR] / num_ntors_per_tap()), + ONION_HANDSHAKE_TYPE_TAP) / num_cpus; + + /* How long would it take to process the ntor cells that we expect to + * process while draining the tap queue? */ + ntor_during_tap_usec = estimated_usec_for_onionskins( + MIN(ol_entries[ONION_HANDSHAKE_TYPE_NTOR], + ol_entries[ONION_HANDSHAKE_TYPE_TAP] * num_ntors_per_tap()), + ONION_HANDSHAKE_TYPE_NTOR) / num_cpus; + + /* See whether that exceeds MaxOnionQueueDelay. If so, we can't queue + * this. */ + if (type == ONION_HANDSHAKE_TYPE_NTOR && + (ntor_usec + tap_during_ntor_usec) / 1000 > + (uint64_t)options->MaxOnionQueueDelay) + return 0; + + if (type == ONION_HANDSHAKE_TYPE_TAP && + (tap_usec + ntor_during_tap_usec) / 1000 > + (uint64_t)options->MaxOnionQueueDelay) + return 0; + +#ifdef CURVE25519_ENABLED + /* If we support the ntor handshake, then don't let TAP handshakes use + * more than 2/3 of the space on the queue. */ + if (type == ONION_HANDSHAKE_TYPE_TAP && + tap_usec / 1000 > (uint64_t)options->MaxOnionQueueDelay * 2 / 3) + return 0; +#else + (void) type; +#endif + + return 1; +} /** Add <b>circ</b> to the end of ol_list and return 0, except * if ol_list is too long, in which case do nothing and return -1. */ int -onion_pending_add(or_circuit_t *circ, char *onionskin) +onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin) { onion_queue_t *tmp; time_t now = time(NULL); + if (onionskin->handshake_type > MAX_ONION_HANDSHAKE_TYPE) { + log_warn(LD_BUG, "Handshake %d out of range! Dropping.", + onionskin->handshake_type); + return -1; + } + tmp = tor_malloc_zero(sizeof(onion_queue_t)); tmp->circ = circ; + tmp->handshake_type = onionskin->handshake_type; tmp->onionskin = onionskin; tmp->when_added = now; - if (!ol_tail) { - tor_assert(!ol_list); - tor_assert(!ol_length); - ol_list = tmp; - ol_tail = tmp; - ol_length++; - return 0; - } - - tor_assert(ol_list); - tor_assert(!ol_tail->next); - - if (ol_length >= get_options()->MaxOnionsPending) { + if (!have_room_for_onionskin(onionskin->handshake_type)) { #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()))) { + if (onionskin->handshake_type == ONION_HANDSHAKE_TYPE_NTOR && + (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 " @@ -80,13 +164,24 @@ onion_pending_add(or_circuit_t *circ, char *onionskin) return -1; } - ol_length++; - ol_tail->next = tmp; - ol_tail = tmp; - while ((int)(now - ol_list->when_added) >= ONIONQUEUE_WAIT_CUTOFF) { - /* cull elderly requests. */ - circ = ol_list->circ; - onion_pending_remove(ol_list->circ); + ++ol_entries[onionskin->handshake_type]; + log_info(LD_OR, "New create (%s). Queues now ntor=%d and tap=%d.", + onionskin->handshake_type == ONION_HANDSHAKE_TYPE_NTOR ? "ntor" : "tap", + ol_entries[ONION_HANDSHAKE_TYPE_NTOR], + ol_entries[ONION_HANDSHAKE_TYPE_TAP]); + + circ->onionqueue_entry = tmp; + TOR_TAILQ_INSERT_TAIL(&ol_list[onionskin->handshake_type], tmp, next); + + /* cull elderly requests. */ + while (1) { + onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[onionskin->handshake_type]); + if (now - head->when_added < (time_t)ONIONQUEUE_WAIT_CUTOFF) + break; + + circ = head->circ; + circ->onionqueue_entry = NULL; + onion_queue_entry_remove(head); log_info(LD_CIRC, "Circuit create request is too old; canceling due to overload."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT); @@ -94,355 +189,993 @@ onion_pending_add(or_circuit_t *circ, char *onionskin) return 0; } -/** Remove the first item from ol_list and return it, or return - * NULL if the list is empty. +/** Return a fairness parameter, to prefer processing NTOR style + * handshakes but still slowly drain the TAP queue so we don't starve + * it entirely. */ +static int +num_ntors_per_tap(void) +{ +#define DEFAULT_NUM_NTORS_PER_TAP 10 +#define MIN_NUM_NTORS_PER_TAP 1 +#define MAX_NUM_NTORS_PER_TAP 100000 + + return networkstatus_get_param(NULL, "NumNTorsPerTAP", + DEFAULT_NUM_NTORS_PER_TAP, + MIN_NUM_NTORS_PER_TAP, + MAX_NUM_NTORS_PER_TAP); +} + +/** Choose which onion queue we'll pull from next. If one is empty choose + * the other; if they both have elements, load balance across them but + * favoring NTOR. */ +static uint16_t +decide_next_handshake_type(void) +{ + /* The number of times we've chosen ntor lately when both were available. */ + static int recently_chosen_ntors = 0; + + if (!ol_entries[ONION_HANDSHAKE_TYPE_NTOR]) + return ONION_HANDSHAKE_TYPE_TAP; /* no ntors? try tap */ + + if (!ol_entries[ONION_HANDSHAKE_TYPE_TAP]) { + + /* Nick wants us to prioritize new tap requests when there aren't + * any in the queue and we've processed k ntor cells since the last + * tap cell. This strategy is maybe a good idea, since it starves tap + * less in the case where tap is rare, or maybe a poor idea, since it + * makes the new tap cell unfairly jump in front of ntor cells that + * got here first. In any case this edge case will only become relevant + * once tap is rare. We should reevaluate whether we like this decision + * once tap gets more rare. */ + if (ol_entries[ONION_HANDSHAKE_TYPE_NTOR] && + recently_chosen_ntors <= num_ntors_per_tap()) + ++recently_chosen_ntors; + + return ONION_HANDSHAKE_TYPE_NTOR; /* no taps? try ntor */ + } + + /* They both have something queued. Pick ntor if we haven't done that + * too much lately. */ + if (++recently_chosen_ntors <= num_ntors_per_tap()) { + return ONION_HANDSHAKE_TYPE_NTOR; + } + + /* Else, it's time to let tap have its turn. */ + recently_chosen_ntors = 0; + return ONION_HANDSHAKE_TYPE_TAP; +} + +/** Remove the highest priority item from ol_list[] and return it, or + * return NULL if the lists are empty. */ or_circuit_t * -onion_next_task(char **onionskin_out) +onion_next_task(create_cell_t **onionskin_out) { or_circuit_t *circ; + uint16_t handshake_to_choose = decide_next_handshake_type(); + onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[handshake_to_choose]); - if (!ol_list) + if (!head) return NULL; /* no onions pending, we're done */ - tor_assert(ol_list->circ); - tor_assert(ol_list->circ->p_conn); /* make sure it's still valid */ - tor_assert(ol_length > 0); - circ = ol_list->circ; - *onionskin_out = ol_list->onionskin; - ol_list->onionskin = NULL; /* prevent free. */ - onion_pending_remove(ol_list->circ); + tor_assert(head->circ); + tor_assert(head->handshake_type <= MAX_ONION_HANDSHAKE_TYPE); +// tor_assert(head->circ->p_chan); /* make sure it's still valid */ +/* XXX I only commented out the above line to make the unit tests + * more manageable. That's probably not good long-term. -RD */ + circ = head->circ; + if (head->onionskin) + --ol_entries[head->handshake_type]; + log_info(LD_OR, "Processing create (%s). Queues now ntor=%d and tap=%d.", + head->handshake_type == ONION_HANDSHAKE_TYPE_NTOR ? "ntor" : "tap", + ol_entries[ONION_HANDSHAKE_TYPE_NTOR], + ol_entries[ONION_HANDSHAKE_TYPE_TAP]); + + *onionskin_out = head->onionskin; + head->onionskin = NULL; /* prevent free. */ + circ->onionqueue_entry = NULL; + onion_queue_entry_remove(head); return circ; } +/** Return the number of <b>handshake_type</b>-style create requests pending. + */ +int +onion_num_pending(uint16_t handshake_type) +{ + return ol_entries[handshake_type]; +} + /** Go through ol_list, find the onion_queue_t element which points to * circ, remove and free that element. Leave circ itself alone. */ void onion_pending_remove(or_circuit_t *circ) { - onion_queue_t *tmpo, *victim; - - if (!ol_list) - return; /* nothing here. */ - - /* first check to see if it's the first entry */ - tmpo = ol_list; - if (tmpo->circ == circ) { - /* it's the first one. remove it from the list. */ - ol_list = tmpo->next; - if (!ol_list) - ol_tail = NULL; - ol_length--; - victim = tmpo; - } else { /* we need to hunt through the rest of the list */ - for ( ;tmpo->next && tmpo->next->circ != circ; tmpo=tmpo->next) ; - if (!tmpo->next) { - log_debug(LD_GENERAL, - "circ (p_circ_id %d) not in list, probably at cpuworker.", - circ->p_circ_id); - return; - } - /* now we know tmpo->next->circ == circ */ - victim = tmpo->next; - tmpo->next = victim->next; - if (ol_tail == victim) - ol_tail = tmpo; - ol_length--; + onion_queue_t *victim; + + if (!circ) + return; + + victim = circ->onionqueue_entry; + if (victim) + onion_queue_entry_remove(victim); +} + +/** Remove a queue entry <b>victim</b> from the queue, unlinking it from + * its circuit and freeing it and any structures it owns.*/ +static void +onion_queue_entry_remove(onion_queue_t *victim) +{ + if (victim->handshake_type > MAX_ONION_HANDSHAKE_TYPE) { + log_warn(LD_BUG, "Handshake %d out of range! Dropping.", + victim->handshake_type); + /* XXX leaks */ + return; } - /* now victim points to the element that needs to be removed */ + TOR_TAILQ_REMOVE(&ol_list[victim->handshake_type], victim, next); + + if (victim->circ) + victim->circ->onionqueue_entry = NULL; + + if (victim->onionskin) + --ol_entries[victim->handshake_type]; tor_free(victim->onionskin); tor_free(victim); } -/*----------------------------------------------------------------------*/ +/** Remove all circuits from the pending list. Called from tor_free_all. */ +void +clear_pending_onions(void) +{ + onion_queue_t *victim; + int i; + for (i=0; i<=MAX_ONION_HANDSHAKE_TYPE; i++) { + while ((victim = TOR_TAILQ_FIRST(&ol_list[i]))) { + onion_queue_entry_remove(victim); + } + } + memset(ol_entries, 0, sizeof(ol_entries)); +} -/** Given a router's 128 byte public key, - * stores the following in onion_skin_out: - * - [42 bytes] OAEP padding - * - [16 bytes] Symmetric key for encrypting blob past RSA - * - [70 bytes] g^x part 1 (inside the RSA) - * - [58 bytes] g^x part 2 (symmetrically encrypted) - * - * Stores the DH private key into handshake_state_out for later completion - * of the handshake. - * - * The meeting point/cookies and auth are zeroed out for now. +/* ============================================================ */ + +/** Fill in a server_onion_keys_t object at <b>keys</b> with all of the keys + * and other info we might need to do onion handshakes. (We make a copy of + * our keys for each cpuworker to avoid race conditions with the main thread, + * and to avoid locking) */ +void +setup_server_onion_keys(server_onion_keys_t *keys) +{ + memset(keys, 0, sizeof(server_onion_keys_t)); + memcpy(keys->my_identity, router_get_my_id_digest(), DIGEST_LEN); + dup_onion_keys(&keys->onion_key, &keys->last_onion_key); +#ifdef CURVE25519_ENABLED + keys->curve25519_key_map = construct_ntor_key_map(); + keys->junk_keypair = tor_malloc_zero(sizeof(curve25519_keypair_t)); + curve25519_keypair_generate(keys->junk_keypair, 0); +#endif +} + +/** Release all storage held in <b>keys</b>, but do not free <b>keys</b> + * itself (as it's likely to be stack-allocated.) */ +void +release_server_onion_keys(server_onion_keys_t *keys) +{ + if (! keys) + return; + + crypto_pk_free(keys->onion_key); + crypto_pk_free(keys->last_onion_key); +#ifdef CURVE25519_ENABLED + ntor_key_map_free(keys->curve25519_key_map); + tor_free(keys->junk_keypair); +#endif + memset(keys, 0, sizeof(server_onion_keys_t)); +} + +/** Release whatever storage is held in <b>state</b>, depending on its + * type, and clear its pointer. */ +void +onion_handshake_state_release(onion_handshake_state_t *state) +{ + switch (state->tag) { + case ONION_HANDSHAKE_TYPE_TAP: + crypto_dh_free(state->u.tap); + state->u.tap = NULL; + break; + case ONION_HANDSHAKE_TYPE_FAST: + fast_handshake_state_free(state->u.fast); + state->u.fast = NULL; + break; +#ifdef CURVE25519_ENABLED + case ONION_HANDSHAKE_TYPE_NTOR: + ntor_handshake_state_free(state->u.ntor); + state->u.ntor = NULL; + break; +#endif + default: + log_warn(LD_BUG, "called with unknown handshake state type %d", + (int)state->tag); + tor_fragile_assert(); + } +} + +/** Perform the first step of a circuit-creation handshake of type <b>type</b> + * (one of ONION_HANDSHAKE_TYPE_*): generate the initial "onion skin" in + * <b>onion_skin_out</b>, and store any state information in <b>state_out</b>. + * Return -1 on failure, and the length of the onionskin on acceptance. */ int -onion_skin_create(crypto_pk_t *dest_router_key, - crypto_dh_t **handshake_state_out, - char *onion_skin_out) /* ONIONSKIN_CHALLENGE_LEN bytes */ +onion_skin_create(int type, + const extend_info_t *node, + onion_handshake_state_t *state_out, + uint8_t *onion_skin_out) { - char challenge[DH_KEY_LEN]; - crypto_dh_t *dh = NULL; - int dhbytes, pkbytes; - - tor_assert(dest_router_key); - tor_assert(handshake_state_out); - tor_assert(onion_skin_out); - *handshake_state_out = NULL; - memset(onion_skin_out, 0, ONIONSKIN_CHALLENGE_LEN); + int r = -1; - if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT))) - goto err; + switch (type) { + case ONION_HANDSHAKE_TYPE_TAP: + if (!node->onion_key) + return -1; - dhbytes = crypto_dh_get_bytes(dh); - pkbytes = (int) crypto_pk_keysize(dest_router_key); - tor_assert(dhbytes == 128); - tor_assert(pkbytes == 128); + if (onion_skin_TAP_create(node->onion_key, + &state_out->u.tap, + (char*)onion_skin_out) < 0) + return -1; - if (crypto_dh_get_public(dh, challenge, dhbytes)) - goto err; + r = TAP_ONIONSKIN_CHALLENGE_LEN; + break; + case ONION_HANDSHAKE_TYPE_FAST: + if (fast_onionskin_create(&state_out->u.fast, onion_skin_out) < 0) + return -1; - note_crypto_pk_op(ENC_ONIONSKIN); + r = CREATE_FAST_LEN; + break; + case ONION_HANDSHAKE_TYPE_NTOR: +#ifdef CURVE25519_ENABLED + if (tor_mem_is_zero((const char*)node->curve25519_onion_key.public_key, + CURVE25519_PUBKEY_LEN)) + return -1; + if (onion_skin_ntor_create((const uint8_t*)node->identity_digest, + &node->curve25519_onion_key, + &state_out->u.ntor, + onion_skin_out) < 0) + return -1; - /* set meeting point, meeting cookie, etc here. Leave zero for now. */ - if (crypto_pk_public_hybrid_encrypt(dest_router_key, onion_skin_out, - ONIONSKIN_CHALLENGE_LEN, - challenge, DH_KEY_LEN, - PK_PKCS1_OAEP_PADDING, 1)<0) - goto err; + r = NTOR_ONIONSKIN_LEN; +#else + return -1; +#endif + break; + default: + log_warn(LD_BUG, "called with unknown handshake state type %d", type); + tor_fragile_assert(); + r = -1; + } - memwipe(challenge, 0, sizeof(challenge)); - *handshake_state_out = dh; + if (r > 0) + state_out->tag = (uint16_t) type; - return 0; - err: - memwipe(challenge, 0, sizeof(challenge)); - if (dh) crypto_dh_free(dh); - return -1; + return r; } -/** Given an encrypted DH public key as generated by onion_skin_create, - * and the private key for this onion router, generate the reply (128-byte - * DH plus the first 20 bytes of shared key material), and store the - * next key_out_len bytes of key material in key_out. +/** Perform the second (server-side) step of a circuit-creation handshake of + * type <b>type</b>, responding to the client request in <b>onion_skin</b> + * using the keys in <b>keys</b>. On success, write our response into + * <b>reply_out</b>, generate <b>keys_out_len</b> bytes worth of key material + * in <b>keys_out_len</b>, a hidden service nonce to <b>rend_nonce_out</b>, + * and return the length of the reply. On failure, return -1. */ int -onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/ - crypto_pk_t *private_key, - crypto_pk_t *prev_private_key, - char *handshake_reply_out, /*ONIONSKIN_REPLY_LEN*/ - char *key_out, - size_t key_out_len) +onion_skin_server_handshake(int type, + const uint8_t *onion_skin, size_t onionskin_len, + const server_onion_keys_t *keys, + uint8_t *reply_out, + uint8_t *keys_out, size_t keys_out_len, + uint8_t *rend_nonce_out) { - char challenge[ONIONSKIN_CHALLENGE_LEN]; - crypto_dh_t *dh = NULL; - ssize_t len; - char *key_material=NULL; - size_t key_material_len=0; - int i; - crypto_pk_t *k; + int r = -1; - len = -1; - for (i=0;i<2;++i) { - k = i==0?private_key:prev_private_key; - if (!k) - break; - note_crypto_pk_op(DEC_ONIONSKIN); - len = crypto_pk_private_hybrid_decrypt(k, challenge, - ONIONSKIN_CHALLENGE_LEN, - onion_skin, ONIONSKIN_CHALLENGE_LEN, - PK_PKCS1_OAEP_PADDING,0); - if (len>0) - break; + switch (type) { + case ONION_HANDSHAKE_TYPE_TAP: + if (onionskin_len != TAP_ONIONSKIN_CHALLENGE_LEN) + return -1; + if (onion_skin_TAP_server_handshake((const char*)onion_skin, + keys->onion_key, keys->last_onion_key, + (char*)reply_out, + (char*)keys_out, keys_out_len)<0) + return -1; + r = TAP_ONIONSKIN_REPLY_LEN; + memcpy(rend_nonce_out, reply_out+DH_KEY_LEN, DIGEST_LEN); + break; + case ONION_HANDSHAKE_TYPE_FAST: + if (onionskin_len != CREATE_FAST_LEN) + return -1; + if (fast_server_handshake(onion_skin, reply_out, keys_out, keys_out_len)<0) + return -1; + r = CREATED_FAST_LEN; + memcpy(rend_nonce_out, reply_out+DIGEST_LEN, DIGEST_LEN); + break; + case ONION_HANDSHAKE_TYPE_NTOR: +#ifdef CURVE25519_ENABLED + if (onionskin_len < NTOR_ONIONSKIN_LEN) + return -1; + { + size_t keys_tmp_len = keys_out_len + DIGEST_LEN; + uint8_t *keys_tmp = tor_malloc(keys_out_len + DIGEST_LEN); + + if (onion_skin_ntor_server_handshake( + onion_skin, keys->curve25519_key_map, + keys->junk_keypair, + keys->my_identity, + reply_out, keys_tmp, keys_tmp_len)<0) { + tor_free(keys_tmp); + return -1; + } + memcpy(keys_out, keys_tmp, keys_out_len); + memcpy(rend_nonce_out, keys_tmp+keys_out_len, DIGEST_LEN); + memwipe(keys_tmp, 0, keys_tmp_len); + tor_free(keys_tmp); + r = NTOR_REPLY_LEN; + } +#else + return -1; +#endif + break; + default: + log_warn(LD_BUG, "called with unknown handshake state type %d", type); + tor_fragile_assert(); + return -1; } - if (len<0) { - log_info(LD_PROTOCOL, - "Couldn't decrypt onionskin: client may be using old onion key"); - goto err; - } else if (len != DH_KEY_LEN) { - log_warn(LD_PROTOCOL, "Unexpected onionskin length after decryption: %ld", - (long)len); - goto err; + + return r; +} + +/** Perform the final (client-side) step of a circuit-creation handshake of + * type <b>type</b>, using our state in <b>handshake_state</b> and the + * server's response in <b>reply</b>. On success, generate <b>keys_out_len</b> + * bytes worth of key material in <b>keys_out_len</b>, set + * <b>rend_authenticator_out</b> to the "KH" field that can be used to + * establish introduction points at this hop, and return 0. On failure, + * return -1. */ +int +onion_skin_client_handshake(int type, + const onion_handshake_state_t *handshake_state, + const uint8_t *reply, size_t reply_len, + uint8_t *keys_out, size_t keys_out_len, + uint8_t *rend_authenticator_out) +{ + if (handshake_state->tag != type) + return -1; + + switch (type) { + case ONION_HANDSHAKE_TYPE_TAP: + if (reply_len != TAP_ONIONSKIN_REPLY_LEN) + return -1; + if (onion_skin_TAP_client_handshake(handshake_state->u.tap, + (const char*)reply, + (char *)keys_out, keys_out_len) < 0) + return -1; + + memcpy(rend_authenticator_out, reply+DH_KEY_LEN, DIGEST_LEN); + + return 0; + case ONION_HANDSHAKE_TYPE_FAST: + if (reply_len != CREATED_FAST_LEN) + return -1; + if (fast_client_handshake(handshake_state->u.fast, reply, + keys_out, keys_out_len) < 0) + return -1; + + memcpy(rend_authenticator_out, reply+DIGEST_LEN, DIGEST_LEN); + return 0; +#ifdef CURVE25519_ENABLED + case ONION_HANDSHAKE_TYPE_NTOR: + if (reply_len < NTOR_REPLY_LEN) + return -1; + { + size_t keys_tmp_len = keys_out_len + DIGEST_LEN; + uint8_t *keys_tmp = tor_malloc(keys_tmp_len); + if (onion_skin_ntor_client_handshake(handshake_state->u.ntor, + reply, + keys_tmp, keys_tmp_len) < 0) { + tor_free(keys_tmp); + return -1; + } + memcpy(keys_out, keys_tmp, keys_out_len); + memcpy(rend_authenticator_out, keys_tmp + keys_out_len, DIGEST_LEN); + memwipe(keys_tmp, 0, keys_tmp_len); + tor_free(keys_tmp); + } + return 0; +#endif + default: + log_warn(LD_BUG, "called with unknown handshake state type %d", type); + tor_fragile_assert(); + return -1; } +} - dh = crypto_dh_new(DH_TYPE_CIRCUIT); - if (!dh) { - log_warn(LD_BUG, "Couldn't allocate DH key"); - goto err; +/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. If + * <b>unknown_ok</b> is true, allow cells with handshake types we don't + * recognize. */ +static int +check_create_cell(const create_cell_t *cell, int unknown_ok) +{ + switch (cell->cell_type) { + case CELL_CREATE: + if (cell->handshake_type != ONION_HANDSHAKE_TYPE_TAP && + cell->handshake_type != ONION_HANDSHAKE_TYPE_NTOR) + return -1; + break; + case CELL_CREATE_FAST: + if (cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST) + return -1; + break; + case CELL_CREATE2: + break; + default: + return -1; } - if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN)) { - log_info(LD_GENERAL, "crypto_dh_get_public failed."); - goto err; + + switch (cell->handshake_type) { + case ONION_HANDSHAKE_TYPE_TAP: + if (cell->handshake_len != TAP_ONIONSKIN_CHALLENGE_LEN) + return -1; + break; + case ONION_HANDSHAKE_TYPE_FAST: + if (cell->handshake_len != CREATE_FAST_LEN) + return -1; + break; +#ifdef CURVE25519_ENABLED + case ONION_HANDSHAKE_TYPE_NTOR: + if (cell->handshake_len != NTOR_ONIONSKIN_LEN) + return -1; + break; +#endif + default: + if (! unknown_ok) + return -1; } - key_material_len = DIGEST_LEN+key_out_len; - key_material = tor_malloc(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; + return 0; +} + +/** Write the various parameters into the create cell. Separate from + * create_cell_parse() to make unit testing easier. + */ +void +create_cell_init(create_cell_t *cell_out, uint8_t cell_type, + uint16_t handshake_type, uint16_t handshake_len, + const uint8_t *onionskin) +{ + memset(cell_out, 0, sizeof(*cell_out)); + + cell_out->cell_type = cell_type; + cell_out->handshake_type = handshake_type; + cell_out->handshake_len = handshake_len; + memcpy(cell_out->onionskin, onionskin, handshake_len); +} + +/** Helper: parse the CREATE2 payload at <b>p</b>, which could be up to + * <b>p_len</b> bytes long, and use it to fill the fields of + * <b>cell_out</b>. Return 0 on success and -1 on failure. + * + * Note that part of the body of an EXTEND2 cell is a CREATE2 payload, so + * this function is also used for parsing those. + */ +static int +parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) +{ + uint16_t handshake_type, handshake_len; + + if (p_len < 4) + return -1; + + handshake_type = ntohs(get_uint16(p)); + handshake_len = ntohs(get_uint16(p+2)); + + if (handshake_len > CELL_PAYLOAD_SIZE - 4 || handshake_len > p_len - 4) + return -1; + if (handshake_type == ONION_HANDSHAKE_TYPE_FAST) + return -1; + + create_cell_init(cell_out, CELL_CREATE2, handshake_type, handshake_len, + p+4); + return 0; +} + +/** Magic string which, in a CREATE or EXTEND cell, indicates that a seeming + * TAP payload is really an ntor payload. We'd do away with this if every + * relay supported EXTEND2, but we want to be able to extend from A to B with + * ntor even when A doesn't understand EXTEND2 and so can't generate a + * CREATE2 cell. + **/ +#define NTOR_CREATE_MAGIC "ntorNTORntorNTOR" + +/** Parse a CREATE, CREATE_FAST, or CREATE2 cell from <b>cell_in</b> into + * <b>cell_out</b>. Return 0 on success, -1 on failure. (We reject some + * syntactically valid CREATE2 cells that we can't generate or react to.) */ +int +create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in) +{ + switch (cell_in->command) { + case CELL_CREATE: + if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) { + create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, + NTOR_ONIONSKIN_LEN, cell_in->payload+16); + } else { + create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, + TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload); + } + break; + case CELL_CREATE_FAST: + create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST, + CREATE_FAST_LEN, cell_in->payload); + break; + case CELL_CREATE2: + if (parse_create2_payload(cell_out, cell_in->payload, + CELL_PAYLOAD_SIZE) < 0) + return -1; + break; + default: + return -1; } - /* send back H(K|0) as proof that we learned K. */ - memcpy(handshake_reply_out+DH_KEY_LEN, key_material, DIGEST_LEN); + return check_create_cell(cell_out, 0); +} - /* use the rest of the key material for our shared keys, digests, etc */ - memcpy(key_out, key_material+DIGEST_LEN, key_out_len); +/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */ +static int +check_created_cell(const created_cell_t *cell) +{ + switch (cell->cell_type) { + case CELL_CREATED: + if (cell->handshake_len != TAP_ONIONSKIN_REPLY_LEN && + cell->handshake_len != NTOR_REPLY_LEN) + return -1; + break; + case CELL_CREATED_FAST: + if (cell->handshake_len != CREATED_FAST_LEN) + return -1; + break; + case CELL_CREATED2: + if (cell->handshake_len > RELAY_PAYLOAD_SIZE-2) + return -1; + break; + } - memwipe(challenge, 0, sizeof(challenge)); - memwipe(key_material, 0, key_material_len); - tor_free(key_material); - crypto_dh_free(dh); return 0; - err: - memwipe(challenge, 0, sizeof(challenge)); - if (key_material) { - memwipe(key_material, 0, key_material_len); - tor_free(key_material); +} + +/** Parse a CREATED, CREATED_FAST, or CREATED2 cell from <b>cell_in</b> into + * <b>cell_out</b>. Return 0 on success, -1 on failure. */ +int +created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in) +{ + memset(cell_out, 0, sizeof(*cell_out)); + + switch (cell_in->command) { + case CELL_CREATED: + cell_out->cell_type = CELL_CREATED; + cell_out->handshake_len = TAP_ONIONSKIN_REPLY_LEN; + memcpy(cell_out->reply, cell_in->payload, TAP_ONIONSKIN_REPLY_LEN); + break; + case CELL_CREATED_FAST: + cell_out->cell_type = CELL_CREATED_FAST; + cell_out->handshake_len = CREATED_FAST_LEN; + memcpy(cell_out->reply, cell_in->payload, CREATED_FAST_LEN); + break; + case CELL_CREATED2: + { + const uint8_t *p = cell_in->payload; + cell_out->cell_type = CELL_CREATED2; + cell_out->handshake_len = ntohs(get_uint16(p)); + if (cell_out->handshake_len > CELL_PAYLOAD_SIZE - 2) + return -1; + memcpy(cell_out->reply, p+2, cell_out->handshake_len); + break; + } } - if (dh) crypto_dh_free(dh); - return -1; + return check_created_cell(cell_out); } -/** Finish the client side of the DH handshake. - * Given the 128 byte DH reply + 20 byte hash as generated by - * onion_skin_server_handshake and the handshake state generated by - * onion_skin_create, verify H(K) with the first 20 bytes of shared - * key material, then generate key_out_len more bytes of shared key - * material and store them in key_out. - * - * After the invocation, call crypto_dh_free on handshake_state. +/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */ +static int +check_extend_cell(const extend_cell_t *cell) +{ + if (tor_digest_is_zero((const char*)cell->node_id)) + return -1; + /* We don't currently allow EXTEND2 cells without an IPv4 address */ + if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC) + return -1; + if (cell->create_cell.cell_type == CELL_CREATE) { + if (cell->cell_type != RELAY_COMMAND_EXTEND) + return -1; + } else if (cell->create_cell.cell_type == CELL_CREATE2) { + if (cell->cell_type != RELAY_COMMAND_EXTEND2 && + cell->cell_type != RELAY_COMMAND_EXTEND) + return -1; + } else { + /* In particular, no CREATE_FAST cells are allowed */ + return -1; + } + if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST) + return -1; + + return check_create_cell(&cell->create_cell, 1); +} + +/** Protocol constants for specifier types in EXTEND2 + * @{ */ +#define SPECTYPE_IPV4 0 +#define SPECTYPE_IPV6 1 +#define SPECTYPE_LEGACY_ID 2 +/** @} */ + +/** Parse an EXTEND or EXTEND2 cell (according to <b>command</b>) from the + * <b>payload_length</b> bytes of <b>payload</b> into <b>cell_out</b>. Return + * 0 on success, -1 on failure. */ int -onion_skin_client_handshake(crypto_dh_t *handshake_state, - const char *handshake_reply, /* ONIONSKIN_REPLY_LEN bytes */ - char *key_out, - size_t key_out_len) +extend_cell_parse(extend_cell_t *cell_out, const uint8_t command, + const uint8_t *payload, size_t payload_length) { - ssize_t len; - char *key_material=NULL; - size_t key_material_len; - tor_assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN); - - key_material_len = DIGEST_LEN + key_out_len; - key_material = tor_malloc(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; - - if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) { - /* H(K) does *not* match. Something fishy. */ - log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. " - "Bug or attack."); - goto err; + const uint8_t *eop; + + memset(cell_out, 0, sizeof(*cell_out)); + if (payload_length > RELAY_PAYLOAD_SIZE) + return -1; + eop = payload + payload_length; + + switch (command) { + case RELAY_COMMAND_EXTEND: + { + if (payload_length != 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN) + return -1; + + cell_out->cell_type = RELAY_COMMAND_EXTEND; + tor_addr_from_ipv4n(&cell_out->orport_ipv4.addr, get_uint32(payload)); + cell_out->orport_ipv4.port = ntohs(get_uint16(payload+4)); + tor_addr_make_unspec(&cell_out->orport_ipv6.addr); + if (tor_memeq(payload + 6, NTOR_CREATE_MAGIC, 16)) { + cell_out->create_cell.cell_type = CELL_CREATE2; + cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_NTOR; + cell_out->create_cell.handshake_len = NTOR_ONIONSKIN_LEN; + memcpy(cell_out->create_cell.onionskin, payload + 22, + NTOR_ONIONSKIN_LEN); + } else { + cell_out->create_cell.cell_type = CELL_CREATE; + cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP; + cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN; + memcpy(cell_out->create_cell.onionskin, payload + 6, + TAP_ONIONSKIN_CHALLENGE_LEN); + } + memcpy(cell_out->node_id, payload + 6 + TAP_ONIONSKIN_CHALLENGE_LEN, + DIGEST_LEN); + break; + } + case RELAY_COMMAND_EXTEND2: + { + uint8_t n_specs = *payload, spectype, speclen; + int i; + int found_ipv4 = 0, found_ipv6 = 0, found_id = 0; + tor_addr_make_unspec(&cell_out->orport_ipv4.addr); + tor_addr_make_unspec(&cell_out->orport_ipv6.addr); + + cell_out->cell_type = RELAY_COMMAND_EXTEND2; + ++payload; + /* Parse the specifiers. We'll only take the first IPv4 and first IPv6 + * addres, and the node ID, and ignore everything else */ + for (i = 0; i < n_specs; ++i) { + if (eop - payload < 2) + return -1; + spectype = payload[0]; + speclen = payload[1]; + payload += 2; + if (eop - payload < speclen) + return -1; + switch (spectype) { + case SPECTYPE_IPV4: + if (speclen != 6) + return -1; + if (!found_ipv4) { + tor_addr_from_ipv4n(&cell_out->orport_ipv4.addr, + get_uint32(payload)); + cell_out->orport_ipv4.port = ntohs(get_uint16(payload+4)); + found_ipv4 = 1; + } + break; + case SPECTYPE_IPV6: + if (speclen != 18) + return -1; + if (!found_ipv6) { + tor_addr_from_ipv6_bytes(&cell_out->orport_ipv6.addr, + (const char*)payload); + cell_out->orport_ipv6.port = ntohs(get_uint16(payload+16)); + found_ipv6 = 1; + } + break; + case SPECTYPE_LEGACY_ID: + if (speclen != 20) + return -1; + if (found_id) + return -1; + memcpy(cell_out->node_id, payload, 20); + found_id = 1; + break; + } + payload += speclen; + } + if (!found_id || !found_ipv4) + return -1; + if (parse_create2_payload(&cell_out->create_cell,payload,eop-payload)<0) + return -1; + break; + } + default: + return -1; } - /* use the rest of the key material for our shared keys, digests, etc */ - memcpy(key_out, key_material+DIGEST_LEN, key_out_len); + return check_extend_cell(cell_out); +} - memwipe(key_material, 0, key_material_len); - tor_free(key_material); - return 0; - err: - memwipe(key_material, 0, key_material_len); - tor_free(key_material); - return -1; +/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */ +static int +check_extended_cell(const extended_cell_t *cell) +{ + if (cell->created_cell.cell_type == CELL_CREATED) { + if (cell->cell_type != RELAY_COMMAND_EXTENDED) + return -1; + } else if (cell->created_cell.cell_type == CELL_CREATED2) { + if (cell->cell_type != RELAY_COMMAND_EXTENDED2) + return -1; + } else { + return -1; + } + + return check_created_cell(&cell->created_cell); } -/** Implement the server side of the CREATE_FAST abbreviated handshake. The - * client has provided DIGEST_LEN key bytes in <b>key_in</b> ("x"). We - * generate a reply of DIGEST_LEN*2 bytes in <b>key_out</b>, consisting of a - * new random "y", followed by H(x|y) to check for correctness. We set - * <b>key_out_len</b> bytes of key material in <b>key_out</b>. - * Return 0 on success, <0 on failure. - **/ +/** Parse an EXTENDED or EXTENDED2 cell (according to <b>command</b>) from the + * <b>payload_length</b> bytes of <b>payload</b> into <b>cell_out</b>. Return + * 0 on success, -1 on failure. */ int -fast_server_handshake(const uint8_t *key_in, /* DIGEST_LEN bytes */ - uint8_t *handshake_reply_out, /* DIGEST_LEN*2 bytes */ - uint8_t *key_out, - size_t key_out_len) +extended_cell_parse(extended_cell_t *cell_out, + const uint8_t command, const uint8_t *payload, + size_t payload_len) { - char tmp[DIGEST_LEN+DIGEST_LEN]; - char *out = NULL; - size_t out_len; - int r = -1; + memset(cell_out, 0, sizeof(*cell_out)); + if (payload_len > RELAY_PAYLOAD_SIZE) + return -1; + + switch (command) { + case RELAY_COMMAND_EXTENDED: + if (payload_len != TAP_ONIONSKIN_REPLY_LEN) + return -1; + cell_out->cell_type = RELAY_COMMAND_EXTENDED; + cell_out->created_cell.cell_type = CELL_CREATED; + cell_out->created_cell.handshake_len = TAP_ONIONSKIN_REPLY_LEN; + memcpy(cell_out->created_cell.reply, payload, TAP_ONIONSKIN_REPLY_LEN); + break; + case RELAY_COMMAND_EXTENDED2: + { + cell_out->cell_type = RELAY_COMMAND_EXTENDED2; + cell_out->created_cell.cell_type = CELL_CREATED2; + cell_out->created_cell.handshake_len = ntohs(get_uint16(payload)); + if (cell_out->created_cell.handshake_len > RELAY_PAYLOAD_SIZE - 2 || + cell_out->created_cell.handshake_len > payload_len - 2) + return -1; + memcpy(cell_out->created_cell.reply, payload+2, + cell_out->created_cell.handshake_len); + } + break; + default: + return -1; + } + + return check_extended_cell(cell_out); +} - if (crypto_rand((char*)handshake_reply_out, DIGEST_LEN)<0) +/** Fill <b>cell_out</b> with a correctly formatted version of the + * CREATE{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on + * failure. This is a cell we didn't originate if <b>relayed</b> is true. */ +static int +create_cell_format_impl(cell_t *cell_out, const create_cell_t *cell_in, + int relayed) +{ + uint8_t *p; + size_t space; + if (check_create_cell(cell_in, relayed) < 0) return -1; - memcpy(tmp, key_in, DIGEST_LEN); - memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN); - out_len = key_out_len+DIGEST_LEN; - out = tor_malloc(out_len); - if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) { - goto done; + memset(cell_out->payload, 0, sizeof(cell_out->payload)); + cell_out->command = cell_in->cell_type; + + p = cell_out->payload; + space = sizeof(cell_out->payload); + + switch (cell_in->cell_type) { + case CELL_CREATE: + if (cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR) { + memcpy(p, NTOR_CREATE_MAGIC, 16); + p += 16; + space -= 16; + } + /* Fall through */ + case CELL_CREATE_FAST: + tor_assert(cell_in->handshake_len <= space); + memcpy(p, cell_in->onionskin, cell_in->handshake_len); + break; + case CELL_CREATE2: + tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)-4); + set_uint16(cell_out->payload, htons(cell_in->handshake_type)); + set_uint16(cell_out->payload+2, htons(cell_in->handshake_len)); + memcpy(cell_out->payload + 4, cell_in->onionskin, cell_in->handshake_len); + break; + default: + return -1; } - memcpy(handshake_reply_out+DIGEST_LEN, out, DIGEST_LEN); - memcpy(key_out, out+DIGEST_LEN, key_out_len); - r = 0; - done: - memwipe(tmp, 0, sizeof(tmp)); - memwipe(out, 0, out_len); - tor_free(out); - return r; + + return 0; } -/** Implement the second half of the client side of the CREATE_FAST handshake. - * We sent the server <b>handshake_state</b> ("x") already, and the server - * told us <b>handshake_reply_out</b> (y|H(x|y)). Make sure that the hash is - * correct, and generate key material in <b>key_out</b>. Return 0 on success, - * true on failure. - * - * NOTE: The "CREATE_FAST" handshake path is distinguishable from regular - * "onionskin" handshakes, and is not secure if an adversary can see or modify - * the messages. Therefore, it should only be used by clients, and only as - * the first hop of a circuit (since the first hop is already authenticated - * and protected by TLS). - */ int -fast_client_handshake(const uint8_t *handshake_state,/*DIGEST_LEN bytes*/ - const uint8_t *handshake_reply_out,/*DIGEST_LEN*2 bytes*/ - uint8_t *key_out, - size_t key_out_len) +create_cell_format(cell_t *cell_out, const create_cell_t *cell_in) { - char tmp[DIGEST_LEN+DIGEST_LEN]; - char *out; - size_t out_len; - int r = -1; + return create_cell_format_impl(cell_out, cell_in, 0); +} + +int +create_cell_format_relayed(cell_t *cell_out, const create_cell_t *cell_in) +{ + return create_cell_format_impl(cell_out, cell_in, 1); +} - memcpy(tmp, handshake_state, DIGEST_LEN); - memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN); - out_len = key_out_len+DIGEST_LEN; - out = tor_malloc(out_len); - if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) { - goto done; +/** Fill <b>cell_out</b> with a correctly formatted version of the + * CREATED{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on + * failure. */ +int +created_cell_format(cell_t *cell_out, const created_cell_t *cell_in) +{ + if (check_created_cell(cell_in) < 0) + return -1; + + memset(cell_out->payload, 0, sizeof(cell_out->payload)); + cell_out->command = cell_in->cell_type; + + switch (cell_in->cell_type) { + case CELL_CREATED: + case CELL_CREATED_FAST: + tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)); + memcpy(cell_out->payload, cell_in->reply, cell_in->handshake_len); + break; + case CELL_CREATED2: + tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)-2); + set_uint16(cell_out->payload, htons(cell_in->handshake_len)); + memcpy(cell_out->payload + 2, cell_in->reply, cell_in->handshake_len); + break; + default: + return -1; } - if (tor_memneq(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) { - /* H(K) does *not* match. Something fishy. */ - log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. " - "Bug or attack."); - goto done; + return 0; +} + +/** Format the EXTEND{,2} cell in <b>cell_in</b>, storing its relay payload in + * <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the + * relay command in *<b>command_out</b>. The <b>payload_out</b> must have + * RELAY_PAYLOAD_SIZE bytes available. Return 0 on success, -1 on failure. */ +int +extend_cell_format(uint8_t *command_out, uint16_t *len_out, + uint8_t *payload_out, const extend_cell_t *cell_in) +{ + uint8_t *p, *eop; + if (check_extend_cell(cell_in) < 0) + return -1; + + p = payload_out; + eop = payload_out + RELAY_PAYLOAD_SIZE; + + memset(p, 0, RELAY_PAYLOAD_SIZE); + + switch (cell_in->cell_type) { + case RELAY_COMMAND_EXTEND: + { + *command_out = RELAY_COMMAND_EXTEND; + *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN; + set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr)); + set_uint16(p+4, ntohs(cell_in->orport_ipv4.port)); + if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) { + memcpy(p+6, NTOR_CREATE_MAGIC, 16); + memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN); + } else { + memcpy(p+6, cell_in->create_cell.onionskin, + TAP_ONIONSKIN_CHALLENGE_LEN); + } + memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN); + } + break; + case RELAY_COMMAND_EXTEND2: + { + uint8_t n = 2; + *command_out = RELAY_COMMAND_EXTEND2; + + *p++ = n; /* 2 identifiers */ + *p++ = SPECTYPE_IPV4; /* First is IPV4. */ + *p++ = 6; /* It's 6 bytes long. */ + set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr)); + set_uint16(p+4, htons(cell_in->orport_ipv4.port)); + p += 6; + *p++ = SPECTYPE_LEGACY_ID; /* Next is an identity digest. */ + *p++ = 20; /* It's 20 bytes long */ + memcpy(p, cell_in->node_id, DIGEST_LEN); + p += 20; + + /* Now we can send the handshake */ + set_uint16(p, htons(cell_in->create_cell.handshake_type)); + set_uint16(p+2, htons(cell_in->create_cell.handshake_len)); + p += 4; + + if (cell_in->create_cell.handshake_len > eop - p) + return -1; + + memcpy(p, cell_in->create_cell.onionskin, + cell_in->create_cell.handshake_len); + + p += cell_in->create_cell.handshake_len; + *len_out = p - payload_out; + } + break; + default: + return -1; } - memcpy(key_out, out+DIGEST_LEN, key_out_len); - r = 0; - done: - memwipe(tmp, 0, sizeof(tmp)); - memwipe(out, 0, out_len); - tor_free(out); - return r; + + return 0; } -/** Remove all circuits from the pending list. Called from tor_free_all. */ -void -clear_pending_onions(void) +/** Format the EXTENDED{,2} cell in <b>cell_in</b>, storing its relay payload + * in <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the + * relay command in *<b>command_out</b>. The <b>payload_out</b> must have + * RELAY_PAYLOAD_SIZE bytes available. Return 0 on success, -1 on failure. */ +int +extended_cell_format(uint8_t *command_out, uint16_t *len_out, + uint8_t *payload_out, const extended_cell_t *cell_in) { - while (ol_list) { - onion_queue_t *victim = ol_list; - ol_list = victim->next; - tor_free(victim->onionskin); - tor_free(victim); + uint8_t *p; + if (check_extended_cell(cell_in) < 0) + return -1; + + p = payload_out; + memset(p, 0, RELAY_PAYLOAD_SIZE); + + switch (cell_in->cell_type) { + case RELAY_COMMAND_EXTENDED: + { + *command_out = RELAY_COMMAND_EXTENDED; + *len_out = TAP_ONIONSKIN_REPLY_LEN; + memcpy(payload_out, cell_in->created_cell.reply, + TAP_ONIONSKIN_REPLY_LEN); + } + break; + case RELAY_COMMAND_EXTENDED2: + { + *command_out = RELAY_COMMAND_EXTENDED2; + *len_out = 2 + cell_in->created_cell.handshake_len; + set_uint16(payload_out, htons(cell_in->created_cell.handshake_len)); + if (2+cell_in->created_cell.handshake_len > RELAY_PAYLOAD_SIZE) + return -1; + memcpy(payload_out+2, cell_in->created_cell.reply, + cell_in->created_cell.handshake_len); + } + break; + default: + return -1; } - ol_list = ol_tail = NULL; - ol_length = 0; + + return 0; } diff --git a/src/or/onion.h b/src/or/onion.h index 7e0f873c73..d62f032b87 100644 --- a/src/or/onion.h +++ b/src/or/onion.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,40 +9,114 @@ * \brief Header file for onion.c. **/ -#ifndef _TOR_ONION_H -#define _TOR_ONION_H +#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); +struct create_cell_t; +int onion_pending_add(or_circuit_t *circ, struct create_cell_t *onionskin); +or_circuit_t *onion_next_task(struct create_cell_t **onionskin_out); +int onion_num_pending(uint16_t handshake_type); void onion_pending_remove(or_circuit_t *circ); +void clear_pending_onions(void); + +typedef struct server_onion_keys_t { + uint8_t my_identity[DIGEST_LEN]; + crypto_pk_t *onion_key; + crypto_pk_t *last_onion_key; +#ifdef CURVE25519_ENABLED + di_digest256_map_t *curve25519_key_map; + curve25519_keypair_t *junk_keypair; +#endif +} server_onion_keys_t; -int onion_skin_create(crypto_pk_t *router_key, - crypto_dh_t **handshake_state_out, - char *onion_skin_out); +#define MAX_ONIONSKIN_CHALLENGE_LEN 255 +#define MAX_ONIONSKIN_REPLY_LEN 255 -int onion_skin_server_handshake(const char *onion_skin, - crypto_pk_t *private_key, - crypto_pk_t *prev_private_key, - char *handshake_reply_out, - char *key_out, - size_t key_out_len); +void setup_server_onion_keys(server_onion_keys_t *keys); +void release_server_onion_keys(server_onion_keys_t *keys); -int onion_skin_client_handshake(crypto_dh_t *handshake_state, - const char *handshake_reply, - char *key_out, - size_t key_out_len); +void onion_handshake_state_release(onion_handshake_state_t *state); -int fast_server_handshake(const uint8_t *key_in, - uint8_t *handshake_reply_out, - uint8_t *key_out, - size_t key_out_len); +int onion_skin_create(int type, + const extend_info_t *node, + onion_handshake_state_t *state_out, + uint8_t *onion_skin_out); +int onion_skin_server_handshake(int type, + const uint8_t *onion_skin, size_t onionskin_len, + const server_onion_keys_t *keys, + uint8_t *reply_out, + uint8_t *keys_out, size_t key_out_len, + uint8_t *rend_nonce_out); +int onion_skin_client_handshake(int type, + const onion_handshake_state_t *handshake_state, + const uint8_t *reply, size_t reply_len, + uint8_t *keys_out, size_t key_out_len, + uint8_t *rend_authenticator_out); -int fast_client_handshake(const uint8_t *handshake_state, - const uint8_t *handshake_reply_out, - uint8_t *key_out, - size_t key_out_len); +/** A parsed CREATE, CREATE_FAST, or CREATE2 cell. */ +typedef struct create_cell_t { + /** The cell command. One of CREATE{,_FAST,2} */ + uint8_t cell_type; + /** One of the ONION_HANDSHAKE_TYPE_* values */ + uint16_t handshake_type; + /** The number of bytes used in <b>onionskin</b>. */ + uint16_t handshake_len; + /** The client-side message for the circuit creation handshake. */ + uint8_t onionskin[CELL_PAYLOAD_SIZE - 4]; +} create_cell_t; -void clear_pending_onions(void); +/** A parsed CREATED, CREATED_FAST, or CREATED2 cell. */ +typedef struct created_cell_t { + /** The cell command. One of CREATED{,_FAST,2} */ + uint8_t cell_type; + /** The number of bytes used in <b>reply</b>. */ + uint16_t handshake_len; + /** The server-side message for the circuit creation handshake. */ + uint8_t reply[CELL_PAYLOAD_SIZE - 2]; +} created_cell_t; + +/** A parsed RELAY_EXTEND or RELAY_EXTEND2 cell */ +typedef struct extend_cell_t { + /** One of RELAY_EXTEND or RELAY_EXTEND2 */ + uint8_t cell_type; + /** An IPv4 address and port for the node we're connecting to. */ + tor_addr_port_t orport_ipv4; + /** An IPv6 address and port for the node we're connecting to. Not currently + * used. */ + tor_addr_port_t orport_ipv6; + /** Identity fingerprint of the node we're conecting to.*/ + uint8_t node_id[DIGEST_LEN]; + /** The "create cell" embedded in this extend cell. Note that unlike the + * create cells we generate ourself, this once can have a handshake type we + * don't recognize. */ + create_cell_t create_cell; +} extend_cell_t; + +/** A parsed RELAY_EXTEND or RELAY_EXTEND2 cell */ +typedef struct extended_cell_t { + /** One of RELAY_EXTENDED or RELAY_EXTENDED2. */ + uint8_t cell_type; + /** The "created cell" embedded in this extended cell. */ + created_cell_t created_cell; +} extended_cell_t; + +void create_cell_init(create_cell_t *cell_out, uint8_t cell_type, + uint16_t handshake_type, uint16_t handshake_len, + const uint8_t *onionskin); +int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in); +int created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in); +int extend_cell_parse(extend_cell_t *cell_out, const uint8_t command, + const uint8_t *payload_in, size_t payload_len); +int extended_cell_parse(extended_cell_t *cell_out, const uint8_t command, + const uint8_t *payload_in, size_t payload_len); + +int create_cell_format(cell_t *cell_out, const create_cell_t *cell_in); +int create_cell_format_relayed(cell_t *cell_out, const create_cell_t *cell_in); +int created_cell_format(cell_t *cell_out, const created_cell_t *cell_in); +int extend_cell_format(uint8_t *command_out, uint16_t *len_out, + uint8_t *payload_out, const extend_cell_t *cell_in); +int extended_cell_format(uint8_t *command_out, uint16_t *len_out, + uint8_t *payload_out, const extended_cell_t *cell_in); #endif diff --git a/src/or/onion_fast.c b/src/or/onion_fast.c new file mode 100644 index 0000000000..aa034a8bd6 --- /dev/null +++ b/src/or/onion_fast.c @@ -0,0 +1,123 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file onion_fast.c + * \brief Functions implement the CREATE_FAST circuit handshake. + **/ + +#include "or.h" +#include "onion_fast.h" + +/** Release all state held in <b>victim</b>. */ +void +fast_handshake_state_free(fast_handshake_state_t *victim) +{ + if (! victim) + return; + memwipe(victim, 0, sizeof(fast_handshake_state_t)); + tor_free(victim); +} + +/** Create the state needed to perform a CREATE_FAST hasnshake. Return 0 + * on success, -1 on failure. */ +int +fast_onionskin_create(fast_handshake_state_t **handshake_state_out, + uint8_t *handshake_out) +{ + fast_handshake_state_t *s; + *handshake_state_out = s = tor_malloc(sizeof(fast_handshake_state_t)); + if (crypto_rand((char*)s->state, sizeof(s->state)) < 0) { + tor_free(s); + return -1; + } + memcpy(handshake_out, s->state, DIGEST_LEN); + return 0; +} + +/** Implement the server side of the CREATE_FAST abbreviated handshake. The + * client has provided DIGEST_LEN key bytes in <b>key_in</b> ("x"). We + * generate a reply of DIGEST_LEN*2 bytes in <b>key_out</b>, consisting of a + * new random "y", followed by H(x|y) to check for correctness. We set + * <b>key_out_len</b> bytes of key material in <b>key_out</b>. + * Return 0 on success, <0 on failure. + **/ +int +fast_server_handshake(const uint8_t *key_in, /* DIGEST_LEN bytes */ + uint8_t *handshake_reply_out, /* DIGEST_LEN*2 bytes */ + uint8_t *key_out, + size_t key_out_len) +{ + uint8_t tmp[DIGEST_LEN+DIGEST_LEN]; + uint8_t *out = NULL; + size_t out_len; + int r = -1; + + if (crypto_rand((char*)handshake_reply_out, DIGEST_LEN)<0) + return -1; + + memcpy(tmp, key_in, DIGEST_LEN); + memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN); + out_len = key_out_len+DIGEST_LEN; + out = tor_malloc(out_len); + if (crypto_expand_key_material_TAP(tmp, sizeof(tmp), out, out_len)) { + goto done; + } + memcpy(handshake_reply_out+DIGEST_LEN, out, DIGEST_LEN); + memcpy(key_out, out+DIGEST_LEN, key_out_len); + r = 0; + done: + memwipe(tmp, 0, sizeof(tmp)); + memwipe(out, 0, out_len); + tor_free(out); + return r; +} + +/** Implement the second half of the client side of the CREATE_FAST handshake. + * We sent the server <b>handshake_state</b> ("x") already, and the server + * told us <b>handshake_reply_out</b> (y|H(x|y)). Make sure that the hash is + * correct, and generate key material in <b>key_out</b>. Return 0 on success, + * true on failure. + * + * NOTE: The "CREATE_FAST" handshake path is distinguishable from regular + * "onionskin" handshakes, and is not secure if an adversary can see or modify + * the messages. Therefore, it should only be used by clients, and only as + * the first hop of a circuit (since the first hop is already authenticated + * and protected by TLS). + */ +int +fast_client_handshake(const fast_handshake_state_t *handshake_state, + const uint8_t *handshake_reply_out,/*DIGEST_LEN*2 bytes*/ + uint8_t *key_out, + size_t key_out_len) +{ + uint8_t tmp[DIGEST_LEN+DIGEST_LEN]; + uint8_t *out; + size_t out_len; + int r = -1; + + memcpy(tmp, handshake_state->state, DIGEST_LEN); + memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN); + out_len = key_out_len+DIGEST_LEN; + out = tor_malloc(out_len); + if (crypto_expand_key_material_TAP(tmp, sizeof(tmp), out, out_len)) { + goto done; + } + if (tor_memneq(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) { + /* H(K) does *not* match. Something fishy. */ + log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. " + "Bug or attack."); + goto done; + } + memcpy(key_out, out+DIGEST_LEN, key_out_len); + r = 0; + done: + memwipe(tmp, 0, sizeof(tmp)); + memwipe(out, 0, out_len); + tor_free(out); + return r; +} + diff --git a/src/or/onion_fast.h b/src/or/onion_fast.h new file mode 100644 index 0000000000..8c078378d2 --- /dev/null +++ b/src/or/onion_fast.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file onion_fast.h + * \brief Header file for onion_fast.c. + **/ + +#ifndef TOR_ONION_FAST_H +#define TOR_ONION_FAST_H + +#define CREATE_FAST_LEN DIGEST_LEN +#define CREATED_FAST_LEN (DIGEST_LEN*2) + +typedef struct fast_handshake_state_t { + uint8_t state[DIGEST_LEN]; +} fast_handshake_state_t; + +void fast_handshake_state_free(fast_handshake_state_t *victim); + +int fast_onionskin_create(fast_handshake_state_t **handshake_state_out, + uint8_t *handshake_out); + +int fast_server_handshake(const uint8_t *message_in, + uint8_t *handshake_reply_out, + uint8_t *key_out, + size_t key_out_len); + +int fast_client_handshake(const fast_handshake_state_t *handshake_state, + const uint8_t *handshake_reply_out, + uint8_t *key_out, + size_t key_out_len); + +#endif + diff --git a/src/or/onion_ntor.c b/src/or/onion_ntor.c new file mode 100644 index 0000000000..9cf7d5dd6e --- /dev/null +++ b/src/or/onion_ntor.c @@ -0,0 +1,295 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#include "crypto.h" +#define ONION_NTOR_PRIVATE +#include "onion_ntor.h" +#include "torlog.h" +#include "util.h" + +/** Free storage held in an ntor handshake state. */ +void +ntor_handshake_state_free(ntor_handshake_state_t *state) +{ + if (!state) + return; + memwipe(state, 0, sizeof(*state)); + tor_free(state); +} + +/** Convenience function to represent HMAC_SHA256 as our instantiation of + * ntor's "tweaked hash'. Hash the <b>inp_len</b> bytes at <b>inp</b> into + * a DIGEST256_LEN-byte digest at <b>out</b>, with the hash changing + * depending on the value of <b>tweak</b>. */ +static void +h_tweak(uint8_t *out, + const uint8_t *inp, size_t inp_len, + const char *tweak) +{ + size_t tweak_len = strlen(tweak); + crypto_hmac_sha256((char*)out, tweak, tweak_len, (const char*)inp, inp_len); +} + +/** Wrapper around a set of tweak-values for use with the ntor handshake. */ +typedef struct tweakset_t { + const char *t_mac; + const char *t_key; + const char *t_verify; + const char *m_expand; +} tweakset_t; + +/** The tweaks to be used with our handshake. */ +const tweakset_t proto1_tweaks = { +#define PROTOID "ntor-curve25519-sha256-1" +#define PROTOID_LEN 24 + PROTOID ":mac", + PROTOID ":key_extract", + PROTOID ":verify", + PROTOID ":key_expand" +}; + +/** Convenience macro: copy <b>len</b> bytes from <b>inp</b> to <b>ptr</b>, + * and advance <b>ptr</b> by the number of bytes copied. */ +#define APPEND(ptr, inp, len) \ + STMT_BEGIN { \ + memcpy(ptr, (inp), (len)); \ + ptr += len; \ + } STMT_END + +/** + * Compute the first client-side step of the ntor handshake for communicating + * with a server whose DIGEST_LEN-byte server identity is <b>router_id</b>, + * and whose onion key is <b>router_key</b>. Store the NTOR_ONIONSKIN_LEN-byte + * message in <b>onion_skin_out</b>, and store the handshake state in + * *<b>handshake_state_out</b>. Return 0 on success, -1 on failure. + */ +int +onion_skin_ntor_create(const uint8_t *router_id, + const curve25519_public_key_t *router_key, + ntor_handshake_state_t **handshake_state_out, + uint8_t *onion_skin_out) +{ + ntor_handshake_state_t *state; + uint8_t *op; + + state = tor_malloc_zero(sizeof(ntor_handshake_state_t)); + + memcpy(state->router_id, router_id, DIGEST_LEN); + memcpy(&state->pubkey_B, router_key, sizeof(curve25519_public_key_t)); + if (curve25519_secret_key_generate(&state->seckey_x, 0) < 0) { + tor_free(state); + return -1; + } + curve25519_public_key_generate(&state->pubkey_X, &state->seckey_x); + + op = onion_skin_out; + APPEND(op, router_id, DIGEST_LEN); + APPEND(op, router_key->public_key, CURVE25519_PUBKEY_LEN); + APPEND(op, state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN); + tor_assert(op == onion_skin_out + NTOR_ONIONSKIN_LEN); + + *handshake_state_out = state; + + return 0; +} + +#define SERVER_STR "Server" +#define SERVER_STR_LEN 6 + +#define SECRET_INPUT_LEN (CURVE25519_PUBKEY_LEN * 3 + \ + CURVE25519_OUTPUT_LEN * 2 + \ + DIGEST_LEN + PROTOID_LEN) +#define AUTH_INPUT_LEN (DIGEST256_LEN + DIGEST_LEN + \ + CURVE25519_PUBKEY_LEN*3 + \ + PROTOID_LEN + SERVER_STR_LEN) + +/** + * Perform the server side of an ntor handshake. Given an + * NTOR_ONIONSKIN_LEN-byte message in <b>onion_skin</b>, our own identity + * fingerprint as <b>my_node_id</b>, and an associative array mapping public + * onion keys to curve25519_keypair_t in <b>private_keys</b>, attempt to + * perform the handshake. Use <b>junk_keys</b> if present if the handshake + * indicates an unrecognized public key. Write an NTOR_REPLY_LEN-byte + * message to send back to the client into <b>handshake_reply_out</b>, and + * generate <b>key_out_len</b> bytes of key material in <b>key_out</b>. Return + * 0 on success, -1 on failure. + */ +int +onion_skin_ntor_server_handshake(const uint8_t *onion_skin, + const di_digest256_map_t *private_keys, + const curve25519_keypair_t *junk_keys, + const uint8_t *my_node_id, + uint8_t *handshake_reply_out, + uint8_t *key_out, + size_t key_out_len) +{ + const tweakset_t *T = &proto1_tweaks; + /* Sensitive stack-allocated material. Kept in an anonymous struct to make + * it easy to wipe. */ + struct { + uint8_t secret_input[SECRET_INPUT_LEN]; + uint8_t auth_input[AUTH_INPUT_LEN]; + curve25519_public_key_t pubkey_X; + curve25519_secret_key_t seckey_y; + curve25519_public_key_t pubkey_Y; + uint8_t verify[DIGEST256_LEN]; + } s; + uint8_t *si = s.secret_input, *ai = s.auth_input; + const curve25519_keypair_t *keypair_bB; + int bad; + + /* Decode the onion skin */ + /* XXXX Does this possible early-return business threaten our security? */ + if (tor_memneq(onion_skin, my_node_id, DIGEST_LEN)) + return -1; + /* Note that on key-not-found, we go through with this operation anyway, + * using "junk_keys". This will result in failed authentication, but won't + * leak whether we recognized the key. */ + keypair_bB = dimap_search(private_keys, onion_skin + DIGEST_LEN, + (void*)junk_keys); + if (!keypair_bB) + return -1; + + memcpy(s.pubkey_X.public_key, onion_skin+DIGEST_LEN+DIGEST256_LEN, + CURVE25519_PUBKEY_LEN); + + /* Make y, Y */ + curve25519_secret_key_generate(&s.seckey_y, 0); + curve25519_public_key_generate(&s.pubkey_Y, &s.seckey_y); + + /* NOTE: If we ever use a group other than curve25519, or a different + * representation for its points, we may need to perform different or + * additional checks on X here and on Y in the client handshake, or lose our + * security properties. What checks we need would depend on the properties + * of the group and its representation. + * + * In short: if you use anything other than curve25519, this aspect of the + * code will need to be reconsidered carefully. */ + + /* build secret_input */ + curve25519_handshake(si, &s.seckey_y, &s.pubkey_X); + bad = safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN); + si += CURVE25519_OUTPUT_LEN; + curve25519_handshake(si, &keypair_bB->seckey, &s.pubkey_X); + bad |= safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN); + si += CURVE25519_OUTPUT_LEN; + + APPEND(si, my_node_id, DIGEST_LEN); + APPEND(si, keypair_bB->pubkey.public_key, CURVE25519_PUBKEY_LEN); + APPEND(si, s.pubkey_X.public_key, CURVE25519_PUBKEY_LEN); + APPEND(si, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN); + APPEND(si, PROTOID, PROTOID_LEN); + tor_assert(si == s.secret_input + sizeof(s.secret_input)); + + /* Compute hashes of secret_input */ + h_tweak(s.verify, s.secret_input, sizeof(s.secret_input), T->t_verify); + + /* Compute auth_input */ + APPEND(ai, s.verify, DIGEST256_LEN); + APPEND(ai, my_node_id, DIGEST_LEN); + APPEND(ai, keypair_bB->pubkey.public_key, CURVE25519_PUBKEY_LEN); + APPEND(ai, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN); + APPEND(ai, s.pubkey_X.public_key, CURVE25519_PUBKEY_LEN); + APPEND(ai, PROTOID, PROTOID_LEN); + APPEND(ai, SERVER_STR, SERVER_STR_LEN); + tor_assert(ai == s.auth_input + sizeof(s.auth_input)); + + /* Build the reply */ + memcpy(handshake_reply_out, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN); + h_tweak(handshake_reply_out+CURVE25519_PUBKEY_LEN, + s.auth_input, sizeof(s.auth_input), + T->t_mac); + + /* Generate the key material */ + crypto_expand_key_material_rfc5869_sha256( + s.secret_input, sizeof(s.secret_input), + (const uint8_t*)T->t_key, strlen(T->t_key), + (const uint8_t*)T->m_expand, strlen(T->m_expand), + key_out, key_out_len); + + /* Wipe all of our local state */ + memwipe(&s, 0, sizeof(s)); + + return bad ? -1 : 0; +} + +/** + * Perform the final client side of the ntor handshake, using the state in + * <b>handshake_state</b> and the server's NTOR_REPLY_LEN-byte reply in + * <b>handshake_reply</b>. Generate <b>key_out_len</b> bytes of key material + * in <b>key_out</b>. Return 0 on success, -1 on failure. + */ +int +onion_skin_ntor_client_handshake( + const ntor_handshake_state_t *handshake_state, + const uint8_t *handshake_reply, + uint8_t *key_out, + size_t key_out_len) +{ + const tweakset_t *T = &proto1_tweaks; + /* Sensitive stack-allocated material. Kept in an anonymous struct to make + * it easy to wipe. */ + struct { + curve25519_public_key_t pubkey_Y; + uint8_t secret_input[SECRET_INPUT_LEN]; + uint8_t verify[DIGEST256_LEN]; + uint8_t auth_input[AUTH_INPUT_LEN]; + uint8_t auth[DIGEST256_LEN]; + } s; + uint8_t *ai = s.auth_input, *si = s.secret_input; + const uint8_t *auth_candidate; + int bad; + + /* Decode input */ + memcpy(s.pubkey_Y.public_key, handshake_reply, CURVE25519_PUBKEY_LEN); + auth_candidate = handshake_reply + CURVE25519_PUBKEY_LEN; + + /* See note in server_handshake above about checking points. The + * circumstances under which we'd need to check Y for membership are + * different than those under which we'd be checking X. */ + + /* Compute secret_input */ + curve25519_handshake(si, &handshake_state->seckey_x, &s.pubkey_Y); + bad = safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN); + si += CURVE25519_OUTPUT_LEN; + curve25519_handshake(si, &handshake_state->seckey_x, + &handshake_state->pubkey_B); + bad |= safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN); + si += CURVE25519_OUTPUT_LEN; + APPEND(si, handshake_state->router_id, DIGEST_LEN); + APPEND(si, handshake_state->pubkey_B.public_key, CURVE25519_PUBKEY_LEN); + APPEND(si, handshake_state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN); + APPEND(si, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN); + APPEND(si, PROTOID, PROTOID_LEN); + tor_assert(si == s.secret_input + sizeof(s.secret_input)); + + /* Compute verify from secret_input */ + h_tweak(s.verify, s.secret_input, sizeof(s.secret_input), T->t_verify); + + /* Compute auth_input */ + APPEND(ai, s.verify, DIGEST256_LEN); + APPEND(ai, handshake_state->router_id, DIGEST_LEN); + APPEND(ai, handshake_state->pubkey_B.public_key, CURVE25519_PUBKEY_LEN); + APPEND(ai, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN); + APPEND(ai, handshake_state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN); + APPEND(ai, PROTOID, PROTOID_LEN); + APPEND(ai, SERVER_STR, SERVER_STR_LEN); + tor_assert(ai == s.auth_input + sizeof(s.auth_input)); + + /* Compute auth */ + h_tweak(s.auth, s.auth_input, sizeof(s.auth_input), T->t_mac); + + bad |= tor_memneq(s.auth, auth_candidate, DIGEST256_LEN); + + crypto_expand_key_material_rfc5869_sha256( + s.secret_input, sizeof(s.secret_input), + (const uint8_t*)T->t_key, strlen(T->t_key), + (const uint8_t*)T->m_expand, strlen(T->m_expand), + key_out, key_out_len); + + memwipe(&s, 0, sizeof(s)); + return bad ? -1 : 0; +} + diff --git a/src/or/onion_ntor.h b/src/or/onion_ntor.h new file mode 100644 index 0000000000..c942e6e0f0 --- /dev/null +++ b/src/or/onion_ntor.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_ONION_NTOR_H +#define TOR_ONION_NTOR_H + +#include "torint.h" +#include "crypto_curve25519.h" +#include "di_ops.h" + +/** State to be maintained by a client between sending an ntor onionskin + * and receiving a reply. */ +typedef struct ntor_handshake_state_t ntor_handshake_state_t; + +/** Length of an ntor onionskin, as sent from the client to server. */ +#define NTOR_ONIONSKIN_LEN 84 +/** Length of an ntor reply, as sent from server to client. */ +#define NTOR_REPLY_LEN 64 + +#ifdef CURVE25519_ENABLED +void ntor_handshake_state_free(ntor_handshake_state_t *state); + +int onion_skin_ntor_create(const uint8_t *router_id, + const curve25519_public_key_t *router_key, + ntor_handshake_state_t **handshake_state_out, + uint8_t *onion_skin_out); + +int onion_skin_ntor_server_handshake(const uint8_t *onion_skin, + const di_digest256_map_t *private_keys, + const curve25519_keypair_t *junk_keypair, + const uint8_t *my_node_id, + uint8_t *handshake_reply_out, + uint8_t *key_out, + size_t key_out_len); + +int onion_skin_ntor_client_handshake( + const ntor_handshake_state_t *handshake_state, + const uint8_t *handshake_reply, + uint8_t *key_out, + size_t key_out_len); + +#ifdef ONION_NTOR_PRIVATE + +/** Storage held by a client while waiting for an ntor reply from a server. */ +struct ntor_handshake_state_t { + /** Identity digest of the router we're talking to. */ + uint8_t router_id[DIGEST_LEN]; + /** Onion key of the router we're talking to. */ + curve25519_public_key_t pubkey_B; + + /** + * Short-lived keypair for use with this handshake. + * @{ */ + curve25519_secret_key_t seckey_x; + curve25519_public_key_t pubkey_X; + /** @} */ +}; +#endif + +#endif + +#endif + diff --git a/src/or/onion_tap.c b/src/or/onion_tap.c new file mode 100644 index 0000000000..3782e75abf --- /dev/null +++ b/src/or/onion_tap.c @@ -0,0 +1,218 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file onion_tap.c + * \brief Functions to implement the original Tor circuit extension handshake + * (a.k.a TAP). + * + * We didn't call it "TAP" ourselves -- Ian Goldberg named it in "On the + * Security of the Tor Authentication Protocol". (Spoiler: it's secure, but + * its security is kind of fragile and implementation dependent. Never modify + * this implementation without reading and understanding that paper at least.) + **/ + +#include "or.h" +#include "config.h" +#include "onion_tap.h" +#include "rephist.h" + +/*----------------------------------------------------------------------*/ + +/** Given a router's 128 byte public key, + * stores the following in onion_skin_out: + * - [42 bytes] OAEP padding + * - [16 bytes] Symmetric key for encrypting blob past RSA + * - [70 bytes] g^x part 1 (inside the RSA) + * - [58 bytes] g^x part 2 (symmetrically encrypted) + * + * Stores the DH private key into handshake_state_out for later completion + * of the handshake. + * + * The meeting point/cookies and auth are zeroed out for now. + */ +int +onion_skin_TAP_create(crypto_pk_t *dest_router_key, + crypto_dh_t **handshake_state_out, + char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */ +{ + char challenge[DH_KEY_LEN]; + crypto_dh_t *dh = NULL; + int dhbytes, pkbytes; + + tor_assert(dest_router_key); + tor_assert(handshake_state_out); + tor_assert(onion_skin_out); + *handshake_state_out = NULL; + memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN); + + if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT))) + goto err; + + dhbytes = crypto_dh_get_bytes(dh); + pkbytes = (int) crypto_pk_keysize(dest_router_key); + tor_assert(dhbytes == 128); + tor_assert(pkbytes == 128); + + if (crypto_dh_get_public(dh, challenge, dhbytes)) + goto err; + + note_crypto_pk_op(ENC_ONIONSKIN); + + /* set meeting point, meeting cookie, etc here. Leave zero for now. */ + if (crypto_pk_public_hybrid_encrypt(dest_router_key, onion_skin_out, + TAP_ONIONSKIN_CHALLENGE_LEN, + challenge, DH_KEY_LEN, + PK_PKCS1_OAEP_PADDING, 1)<0) + goto err; + + memwipe(challenge, 0, sizeof(challenge)); + *handshake_state_out = dh; + + return 0; + err: + memwipe(challenge, 0, sizeof(challenge)); + if (dh) crypto_dh_free(dh); + return -1; +} + +/** Given an encrypted DH public key as generated by onion_skin_create, + * and the private key for this onion router, generate the reply (128-byte + * DH plus the first 20 bytes of shared key material), and store the + * next key_out_len bytes of key material in key_out. + */ +int +onion_skin_TAP_server_handshake( + /*TAP_ONIONSKIN_CHALLENGE_LEN*/ + const char *onion_skin, + crypto_pk_t *private_key, + crypto_pk_t *prev_private_key, + /*TAP_ONIONSKIN_REPLY_LEN*/ + char *handshake_reply_out, + char *key_out, + size_t key_out_len) +{ + char challenge[TAP_ONIONSKIN_CHALLENGE_LEN]; + crypto_dh_t *dh = NULL; + ssize_t len; + char *key_material=NULL; + size_t key_material_len=0; + int i; + crypto_pk_t *k; + + len = -1; + for (i=0;i<2;++i) { + k = i==0?private_key:prev_private_key; + if (!k) + break; + note_crypto_pk_op(DEC_ONIONSKIN); + len = crypto_pk_private_hybrid_decrypt(k, challenge, + TAP_ONIONSKIN_CHALLENGE_LEN, + onion_skin, + TAP_ONIONSKIN_CHALLENGE_LEN, + PK_PKCS1_OAEP_PADDING,0); + if (len>0) + break; + } + if (len<0) { + log_info(LD_PROTOCOL, + "Couldn't decrypt onionskin: client may be using old onion key"); + goto err; + } else if (len != DH_KEY_LEN) { + log_warn(LD_PROTOCOL, "Unexpected onionskin length after decryption: %ld", + (long)len); + goto err; + } + + dh = crypto_dh_new(DH_TYPE_CIRCUIT); + if (!dh) { + log_warn(LD_BUG, "Couldn't allocate DH key"); + goto err; + } + if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN)) { + log_info(LD_GENERAL, "crypto_dh_get_public failed."); + goto err; + } + + key_material_len = DIGEST_LEN+key_out_len; + key_material = tor_malloc(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; + } + + /* send back H(K|0) as proof that we learned K. */ + memcpy(handshake_reply_out+DH_KEY_LEN, key_material, DIGEST_LEN); + + /* use the rest of the key material for our shared keys, digests, etc */ + memcpy(key_out, key_material+DIGEST_LEN, key_out_len); + + memwipe(challenge, 0, sizeof(challenge)); + memwipe(key_material, 0, key_material_len); + tor_free(key_material); + crypto_dh_free(dh); + return 0; + err: + memwipe(challenge, 0, sizeof(challenge)); + if (key_material) { + memwipe(key_material, 0, key_material_len); + tor_free(key_material); + } + if (dh) crypto_dh_free(dh); + + return -1; +} + +/** Finish the client side of the DH handshake. + * Given the 128 byte DH reply + 20 byte hash as generated by + * onion_skin_server_handshake and the handshake state generated by + * onion_skin_create, verify H(K) with the first 20 bytes of shared + * key material, then generate key_out_len more bytes of shared key + * material and store them in key_out. + * + * After the invocation, call crypto_dh_free on handshake_state. + */ +int +onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state, + const char *handshake_reply, /* TAP_ONIONSKIN_REPLY_LEN bytes */ + char *key_out, + size_t key_out_len) +{ + ssize_t len; + char *key_material=NULL; + size_t key_material_len; + tor_assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN); + + key_material_len = DIGEST_LEN + key_out_len; + key_material = tor_malloc(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; + + if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) { + /* H(K) does *not* match. Something fishy. */ + log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. " + "Bug or attack."); + goto err; + } + + /* use the rest of the key material for our shared keys, digests, etc */ + memcpy(key_out, key_material+DIGEST_LEN, key_out_len); + + memwipe(key_material, 0, key_material_len); + tor_free(key_material); + return 0; + err: + memwipe(key_material, 0, key_material_len); + tor_free(key_material); + return -1; +} + diff --git a/src/or/onion_tap.h b/src/or/onion_tap.h new file mode 100644 index 0000000000..b978b66737 --- /dev/null +++ b/src/or/onion_tap.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-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file onion_tap.h + * \brief Header file for onion_tap.c. + **/ + +#ifndef TOR_ONION_TAP_H +#define TOR_ONION_TAP_H + +#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\ + CIPHER_KEY_LEN+\ + DH_KEY_LEN) +#define TAP_ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN) + +int onion_skin_TAP_create(crypto_pk_t *router_key, + crypto_dh_t **handshake_state_out, + char *onion_skin_out); + +int onion_skin_TAP_server_handshake(const char *onion_skin, + crypto_pk_t *private_key, + crypto_pk_t *prev_private_key, + char *handshake_reply_out, + char *key_out, + size_t key_out_len); + +int onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state, + const char *handshake_reply, + char *key_out, + size_t key_out_len); + +#endif + diff --git a/src/or/or.h b/src/or/or.h index 462239190b..3eaf3447dc 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Master header file for Tor-specific functionality. **/ -#ifndef _TOR_OR_H -#define _TOR_OR_H +#ifndef TOR_OR_H +#define TOR_OR_H #include "orconfig.h" @@ -81,7 +81,6 @@ #include <process.h> #include <direct.h> #include <windows.h> -#define snprintf _snprintf #endif #ifdef USE_BUFFEREVENTS @@ -98,6 +97,8 @@ #include "address.h" #include "compat_libevent.h" #include "ht.h" +#include "replaycache.h" +#include "crypto_curve25519.h" /* These signals are defined to help handle_control_signal work. */ @@ -176,8 +177,6 @@ #define MIN_ONION_KEY_LIFETIME (7*24*60*60) /** How often do we rotate TLS contexts? */ #define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60) -/** What expiry time shall we place on our SSL certs? */ -#define MAX_SSL_KEY_LIFETIME_ADVERTISED (365*24*60*60) /** How old do we allow a router to get before removing it * from the router list? In seconds. */ @@ -197,7 +196,7 @@ typedef enum { CIRC_ID_TYPE_NEITHER=2 } circ_id_type_t; -#define _CONN_TYPE_MIN 3 +#define CONN_TYPE_MIN_ 3 /** Type for sockets listening for OR connections. */ #define CONN_TYPE_OR_LISTENER 3 /** A bidirectional TLS connection transmitting a sequence of cells. @@ -228,8 +227,8 @@ typedef enum { #define CONN_TYPE_AP_NATD_LISTENER 14 /** Type for sockets listening for DNS requests. */ #define CONN_TYPE_AP_DNS_LISTENER 15 -#define _CONN_TYPE_MAX 15 -/* !!!! If _CONN_TYPE_MAX is ever over 15, we must grow the type field in +#define CONN_TYPE_MAX_ 15 +/* !!!! If CONN_TYPE_MAX_ is ever over 15, we must grow the type field in * connection_t. */ /* Proxy client types */ @@ -269,17 +268,18 @@ typedef enum { /** State for any listener connection. */ #define LISTENER_STATE_READY 0 -#define _CPUWORKER_STATE_MIN 1 +#define CPUWORKER_STATE_MIN_ 1 /** State for a connection to a cpuworker process that's idle. */ #define CPUWORKER_STATE_IDLE 1 /** State for a connection to a cpuworker process that's processing a * handshake. */ #define CPUWORKER_STATE_BUSY_ONION 2 -#define _CPUWORKER_STATE_MAX 2 +#define CPUWORKER_STATE_MAX_ 2 #define CPUWORKER_TASK_ONION CPUWORKER_STATE_BUSY_ONION +#define CPUWORKER_TASK_SHUTDOWN 255 -#define _OR_CONN_STATE_MIN 1 +#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 handshake to complete */ @@ -304,9 +304,9 @@ typedef enum { #define OR_CONN_STATE_OR_HANDSHAKING_V3 7 /** State for an OR connection: Ready to send/receive cells. */ #define OR_CONN_STATE_OPEN 8 -#define _OR_CONN_STATE_MAX 8 +#define OR_CONN_STATE_MAX_ 8 -#define _EXIT_CONN_STATE_MIN 1 +#define EXIT_CONN_STATE_MIN_ 1 /** State for an exit connection: waiting for response from DNS farm. */ #define EXIT_CONN_STATE_RESOLVING 1 /** State for an exit connection: waiting for connect() to finish. */ @@ -315,10 +315,10 @@ typedef enum { #define EXIT_CONN_STATE_OPEN 3 /** State for an exit connection: waiting to be removed. */ #define EXIT_CONN_STATE_RESOLVEFAILED 4 -#define _EXIT_CONN_STATE_MAX 4 +#define EXIT_CONN_STATE_MAX_ 4 /* The AP state values must be disjoint from the EXIT state values. */ -#define _AP_CONN_STATE_MIN 5 +#define AP_CONN_STATE_MIN_ 5 /** State for a SOCKS connection: waiting for SOCKS request. */ #define AP_CONN_STATE_SOCKS_WAIT 5 /** State for a SOCKS connection: got a y.onion URL; waiting to receive @@ -338,14 +338,14 @@ typedef enum { /** State for a transparent natd connection: waiting for original * destination. */ #define AP_CONN_STATE_NATD_WAIT 12 -#define _AP_CONN_STATE_MAX 12 +#define AP_CONN_STATE_MAX_ 12 /** True iff the AP_CONN_STATE_* value <b>s</b> means that the corresponding * edge connection is not attached to any circuit. */ #define AP_CONN_STATE_IS_UNATTACHED(s) \ ((s) <= AP_CONN_STATE_CIRCUIT_WAIT || (s) == AP_CONN_STATE_NATD_WAIT) -#define _DIR_CONN_STATE_MIN 1 +#define DIR_CONN_STATE_MIN_ 1 /** State for connection to directory server: waiting for connect(). */ #define DIR_CONN_STATE_CONNECTING 1 /** State for connection to directory server: sending HTTP request. */ @@ -358,21 +358,21 @@ typedef enum { #define DIR_CONN_STATE_SERVER_COMMAND_WAIT 5 /** State for connection at directory server: sending HTTP response. */ #define DIR_CONN_STATE_SERVER_WRITING 6 -#define _DIR_CONN_STATE_MAX 6 +#define DIR_CONN_STATE_MAX_ 6 /** True iff the purpose of <b>conn</b> means that it's a server-side * directory connection. */ #define DIR_CONN_IS_SERVER(conn) ((conn)->purpose == DIR_PURPOSE_SERVER) -#define _CONTROL_CONN_STATE_MIN 1 +#define CONTROL_CONN_STATE_MIN_ 1 /** State for a control connection: Authenticated and accepting v1 commands. */ #define CONTROL_CONN_STATE_OPEN 1 /** State for a control connection: Waiting for authentication; speaking * protocol v1. */ #define CONTROL_CONN_STATE_NEEDAUTH 2 -#define _CONTROL_CONN_STATE_MAX 2 +#define CONTROL_CONN_STATE_MAX_ 2 -#define _DIR_PURPOSE_MIN 3 +#define DIR_PURPOSE_MIN_ 3 /** A connection to a directory server: download a rendezvous * descriptor. */ #define DIR_PURPOSE_FETCH_RENDDESC 3 @@ -420,7 +420,7 @@ typedef enum { #define DIR_PURPOSE_FETCH_RENDDESC_V2 18 /** A connection to a directory server: download a microdescriptor. */ #define DIR_PURPOSE_FETCH_MICRODESC 19 -#define _DIR_PURPOSE_MAX 19 +#define DIR_PURPOSE_MAX_ 19 /** True iff <b>p</b> is a purpose corresponding to uploading data to a * directory server. */ @@ -430,12 +430,12 @@ typedef enum { (p)==DIR_PURPOSE_UPLOAD_VOTE || \ (p)==DIR_PURPOSE_UPLOAD_SIGNATURES) -#define _EXIT_PURPOSE_MIN 1 +#define EXIT_PURPOSE_MIN_ 1 /** This exit stream wants to do an ordinary connect. */ #define EXIT_PURPOSE_CONNECT 1 /** This exit stream wants to do a resolve (either normal or reverse). */ #define EXIT_PURPOSE_RESOLVE 2 -#define _EXIT_PURPOSE_MAX 2 +#define EXIT_PURPOSE_MAX_ 2 /* !!!! If any connection purpose is ever over 31, we must grow the type * field in connection_t. */ @@ -444,16 +444,16 @@ typedef enum { #define CIRCUIT_STATE_BUILDING 0 /** Circuit state: Waiting to process the onionskin. */ #define CIRCUIT_STATE_ONIONSKIN_PENDING 1 -/** Circuit state: I'd like to deliver a create, but my n_conn is still +/** Circuit state: I'd like to deliver a create, but my n_chan is still * connecting. */ -#define CIRCUIT_STATE_OR_WAIT 2 +#define CIRCUIT_STATE_CHAN_WAIT 2 /** Circuit state: onionskin(s) processed, ready to send/receive cells. */ #define CIRCUIT_STATE_OPEN 3 -#define _CIRCUIT_PURPOSE_MIN 1 +#define CIRCUIT_PURPOSE_MIN_ 1 /* these circuits were initiated elsewhere */ -#define _CIRCUIT_PURPOSE_OR_MIN 1 +#define CIRCUIT_PURPOSE_OR_MIN_ 1 /** OR-side circuit purpose: normal circuit, at OR. */ #define CIRCUIT_PURPOSE_OR 1 /** OR-side circuit purpose: At OR, from Bob, waiting for intro from Alices. */ @@ -462,7 +462,7 @@ typedef enum { #define CIRCUIT_PURPOSE_REND_POINT_WAITING 3 /** OR-side circuit purpose: At OR, both circuits have this purpose. */ #define CIRCUIT_PURPOSE_REND_ESTABLISHED 4 -#define _CIRCUIT_PURPOSE_OR_MAX 4 +#define CIRCUIT_PURPOSE_OR_MAX_ 4 /* these circuits originate at this node */ @@ -505,7 +505,7 @@ typedef enum { #define CIRCUIT_PURPOSE_C_REND_JOINED 12 /** This circuit is used for build time measurement only */ #define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 13 -#define _CIRCUIT_PURPOSE_C_MAX 13 +#define CIRCUIT_PURPOSE_C_MAX_ 13 /** Hidden-service-side circuit purpose: at Bob, waiting for introductions. */ #define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 14 /** Hidden-service-side circuit purpose: at Bob, successfully established @@ -519,19 +519,21 @@ typedef enum { #define CIRCUIT_PURPOSE_TESTING 18 /** A controller made this circuit and Tor should not use it. */ #define CIRCUIT_PURPOSE_CONTROLLER 19 -#define _CIRCUIT_PURPOSE_MAX 19 +/** This circuit is used for path bias probing only */ +#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING 20 +#define CIRCUIT_PURPOSE_MAX_ 20 /** 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 /** True iff the circuit purpose <b>p</b> is for a circuit that * originated at this node. */ -#define CIRCUIT_PURPOSE_IS_ORIGIN(p) ((p)>_CIRCUIT_PURPOSE_OR_MAX) +#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) \ - ((p)> _CIRCUIT_PURPOSE_OR_MAX && \ - (p)<=_CIRCUIT_PURPOSE_C_MAX) + ((p)> CIRCUIT_PURPOSE_OR_MAX_ && \ + (p)<=CIRCUIT_PURPOSE_C_MAX_) /** True iff the circuit_t <b>c</b> is actually an origin_circuit_t. */ #define CIRCUIT_IS_ORIGIN(c) (CIRCUIT_PURPOSE_IS_ORIGIN((c)->purpose)) /** True iff the circuit purpose <b>p</b> is for an established rendezvous @@ -561,6 +563,8 @@ typedef enum { #define RELAY_COMMAND_RESOLVE 11 #define RELAY_COMMAND_RESOLVED 12 #define RELAY_COMMAND_BEGIN_DIR 13 +#define RELAY_COMMAND_EXTEND2 14 +#define RELAY_COMMAND_EXTENDED2 15 #define RELAY_COMMAND_ESTABLISH_INTRO 32 #define RELAY_COMMAND_ESTABLISH_RENDEZVOUS 33 @@ -666,7 +670,7 @@ typedef enum { /* Reasons why we (or a remote OR) might close a circuit. See tor-spec.txt for * documentation of these. */ -#define _END_CIRC_REASON_MIN 0 +#define END_CIRC_REASON_MIN_ 0 #define END_CIRC_REASON_NONE 0 #define END_CIRC_REASON_TORPROTOCOL 1 #define END_CIRC_REASON_INTERNAL 2 @@ -675,12 +679,12 @@ typedef enum { #define END_CIRC_REASON_RESOURCELIMIT 5 #define END_CIRC_REASON_CONNECTFAILED 6 #define END_CIRC_REASON_OR_IDENTITY 7 -#define END_CIRC_REASON_OR_CONN_CLOSED 8 +#define END_CIRC_REASON_CHANNEL_CLOSED 8 #define END_CIRC_REASON_FINISHED 9 #define END_CIRC_REASON_TIMEOUT 10 #define END_CIRC_REASON_DESTROYED 11 #define END_CIRC_REASON_NOSUCHSERVICE 12 -#define _END_CIRC_REASON_MAX 12 +#define END_CIRC_REASON_MAX_ 12 /** Bitwise-OR this with the argument to circuit_mark_for_close() or * control_event_circuit_status() to indicate that the reason was @@ -834,6 +838,8 @@ typedef enum { #define CELL_VERSIONS 7 #define CELL_NETINFO 8 #define CELL_RELAY_EARLY 9 +#define CELL_CREATE2 10 +#define CELL_CREATED2 11 #define CELL_VPADDING 128 #define CELL_CERTS 129 @@ -870,11 +876,29 @@ typedef enum { /** Number of bytes in a cell, minus cell header. */ #define CELL_PAYLOAD_SIZE 509 -/** Number of bytes in a cell transmitted over the network. */ -#define CELL_NETWORK_SIZE 512 +/** Number of bytes in a cell transmitted over the network, in the longest + * form */ +#define CELL_MAX_NETWORK_SIZE 514 -/** Length of a header on a variable-length cell. */ -#define VAR_CELL_HEADER_SIZE 5 +/** Maximum length of a header on a variable-length cell. */ +#define VAR_CELL_MAX_HEADER_SIZE 7 + +static int get_cell_network_size(int wide_circ_ids); +static INLINE int get_cell_network_size(int wide_circ_ids) +{ + return wide_circ_ids ? CELL_MAX_NETWORK_SIZE : CELL_MAX_NETWORK_SIZE - 2; +} +static int get_var_cell_header_size(int wide_circ_ids); +static INLINE int get_var_cell_header_size(int wide_circ_ids) +{ + return wide_circ_ids ? VAR_CELL_MAX_HEADER_SIZE : + VAR_CELL_MAX_HEADER_SIZE - 2; +} +static int get_circ_id_size(int wide_circ_ids); +static INLINE int get_circ_id_size(int wide_circ_ids) +{ + return wide_circ_ids ? 4 : 2; +} /** Number of bytes in a relay cell's header (not including general cell * header). */ @@ -883,10 +907,151 @@ typedef enum { #define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) /** Identifies a circuit on an or_connection */ -typedef uint16_t circid_t; +typedef uint32_t circid_t; /** Identifies a stream on a circuit */ typedef uint16_t streamid_t; +/* channel_t typedef; struct channel_s is in channel.h */ + +typedef struct channel_s channel_t; + +/* channel_listener_t typedef; struct channel_listener_s is in channel.h */ + +typedef struct channel_listener_s channel_listener_t; + +/* channel states for channel_t */ + +typedef enum { + /* + * Closed state - channel is inactive + * + * Permitted transitions from: + * - CHANNEL_STATE_CLOSING + * Permitted transitions to: + * - CHANNEL_STATE_OPENING + */ + CHANNEL_STATE_CLOSED = 0, + /* + * Opening state - channel is trying to connect + * + * Permitted transitions from: + * - CHANNEL_STATE_CLOSED + * Permitted transitions to: + * - CHANNEL_STATE_CLOSING + * - CHANNEL_STATE_ERROR + * - CHANNEL_STATE_OPEN + */ + CHANNEL_STATE_OPENING, + /* + * Open state - channel is active and ready for use + * + * Permitted transitions from: + * - CHANNEL_STATE_MAINT + * - CHANNEL_STATE_OPENING + * Permitted transitions to: + * - CHANNEL_STATE_CLOSING + * - CHANNEL_STATE_ERROR + * - CHANNEL_STATE_MAINT + */ + CHANNEL_STATE_OPEN, + /* + * Maintenance state - channel is temporarily offline for subclass specific + * maintenance activities such as TLS renegotiation. + * + * Permitted transitions from: + * - CHANNEL_STATE_OPEN + * Permitted transitions to: + * - CHANNEL_STATE_CLOSING + * - CHANNEL_STATE_ERROR + * - CHANNEL_STATE_OPEN + */ + CHANNEL_STATE_MAINT, + /* + * Closing state - channel is shutting down + * + * Permitted transitions from: + * - CHANNEL_STATE_MAINT + * - CHANNEL_STATE_OPEN + * Permitted transitions to: + * - CHANNEL_STATE_CLOSED, + * - CHANNEL_STATE_ERROR + */ + CHANNEL_STATE_CLOSING, + /* + * Error state - channel has experienced a permanent error + * + * Permitted transitions from: + * - CHANNEL_STATE_CLOSING + * - CHANNEL_STATE_MAINT + * - CHANNEL_STATE_OPENING + * - CHANNEL_STATE_OPEN + * Permitted transitions to: + * - None + */ + CHANNEL_STATE_ERROR, + /* + * Placeholder for maximum state value + */ + CHANNEL_STATE_LAST +} channel_state_t; + +/* channel listener states for channel_listener_t */ + +typedef enum { + /* + * Closed state - channel listener is inactive + * + * Permitted transitions from: + * - CHANNEL_LISTENER_STATE_CLOSING + * Permitted transitions to: + * - CHANNEL_LISTENER_STATE_LISTENING + */ + CHANNEL_LISTENER_STATE_CLOSED = 0, + /* + * Listening state - channel listener is listening for incoming + * connections + * + * Permitted transitions from: + * - CHANNEL_LISTENER_STATE_CLOSED + * Permitted transitions to: + * - CHANNEL_LISTENER_STATE_CLOSING + * - CHANNEL_LISTENER_STATE_ERROR + */ + CHANNEL_LISTENER_STATE_LISTENING, + /* + * Closing state - channel listener is shutting down + * + * Permitted transitions from: + * - CHANNEL_LISTENER_STATE_LISTENING + * Permitted transitions to: + * - CHANNEL_LISTENER_STATE_CLOSED, + * - CHANNEL_LISTENER_STATE_ERROR + */ + CHANNEL_LISTENER_STATE_CLOSING, + /* + * Error state - channel listener has experienced a permanent error + * + * Permitted transitions from: + * - CHANNEL_STATE_CLOSING + * - CHANNEL_STATE_LISTENING + * Permitted transitions to: + * - None + */ + CHANNEL_LISTENER_STATE_ERROR, + /* + * Placeholder for maximum state value + */ + CHANNEL_LISTENER_STATE_LAST +} channel_listener_state_t; + +/* TLS channel stuff */ + +typedef struct channel_tls_s channel_tls_t; + +/* circuitmux_t typedef; struct circuitmux_s is in circuitmux.h */ + +typedef struct circuitmux_s circuitmux_t; + /** Parsed onion routing cell. All communication between nodes * is via cells. */ typedef struct cell_t { @@ -911,36 +1076,17 @@ typedef struct var_cell_t { /** A cell as packed for writing to the network. */ typedef struct packed_cell_t { struct packed_cell_t *next; /**< Next cell queued on this circuit. */ - char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */ + char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */ uint32_t inserted_time; /**< Time (in milliseconds since epoch, with high * bits truncated) when this cell was inserted. */ } packed_cell_t; -/* XXXX This next structure may be obsoleted by inserted_time in - * 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. */ @@ -1077,14 +1223,11 @@ typedef struct connection_t { /** Unique identifier for this connection on this Tor instance. */ uint64_t global_identifier; - - /** Unique ID for measuring tunneled network status requests. */ - uint64_t dirreq_id; } connection_t; /** Subtype of connection_t; used for a listener socket. */ typedef struct listener_connection_t { - connection_t _base; + connection_t base_; /** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points * to the evdns_server_port it uses to listen to and answer connections. */ @@ -1102,6 +1245,40 @@ typedef struct listener_connection_t { /** One or more ISO_ flags to describe how to isolate streams. */ uint8_t isolation_flags; /**@}*/ + /** For SOCKS connections only: If this is set, we will choose "no + * authentication" instead of "username/password" authentication if both + * are offered. Used as input to parse_socks. */ + unsigned int socks_prefer_no_auth : 1; + + /** For a SOCKS listeners, these fields describe whether we should + * allow IPv4 and IPv6 addresses from our exit nodes, respectively. + * + * @{ + */ + unsigned int socks_ipv4_traffic : 1; + unsigned int socks_ipv6_traffic : 1; + /** @} */ + /** For a socks listener: should we tell the exit that we prefer IPv6 + * addresses? */ + unsigned int socks_prefer_ipv6 : 1; + + /** For a socks listener: should we cache IPv4/IPv6 DNS information that + * exit nodes tell us? + * + * @{ */ + unsigned int cache_ipv4_answers : 1; + unsigned int cache_ipv6_answers : 1; + /** @} */ + /** For a socks listeners: if we find an answer in our client-side DNS cache, + * should we use it? + * + * @{ */ + unsigned int use_cached_ipv4_answers : 1; + unsigned int use_cached_ipv6_answers : 1; + /** @} */ + /** For socks listeners: When we can automap an address to IPv4 or IPv6, + * do we prefer IPv6? */ + unsigned int prefer_ipv6_virtaddr : 1; } listener_connection_t; @@ -1210,7 +1387,7 @@ typedef struct or_handshake_state_t { /** Subtype of connection_t for an "OR connection" -- that is, one that speaks * cells over TLS. */ typedef struct or_connection_t { - connection_t _base; + connection_t base_; /** Hash of the public RSA key for the other side's identity key, or zeroes * if the other side hasn't shown us a valid identity key. */ @@ -1221,29 +1398,22 @@ typedef struct or_connection_t { int tls_error; /**< Last tor_tls error code. */ /** When we last used this conn for any client traffic. If not * recent, we can rate limit it further. */ - time_t client_used; + + /* Channel using this connection */ + channel_tls_t *chan; tor_addr_t real_addr; /**< The actual address that this connection came from * or went to. The <b>addr</b> field is prone to * getting overridden by the address from the router * descriptor matching <b>identity_digest</b>. */ - circ_id_type_t circ_id_type:2; /**< When we send CREATE cells along this - * connection, which half of the space should - * we use? */ /** Should this connection be used for extending circuits to the server * matching the <b>identity_digest</b> field? Set to true if we're pretty * sure we aren't getting MITMed, either because we're connected to an * address listed in a server descriptor, or because an authenticated * 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. - * 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; + /** True iff we have decided that the other end of this connection * is a client. Connections with this flag set should never be used * to satisfy an EXTEND request. */ @@ -1251,14 +1421,13 @@ typedef struct or_connection_t { /** True iff this is an outgoing connection. */ unsigned int is_outgoing:1; unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */ - uint8_t link_proto; /**< What protocol version are we using? 0 for - * "none negotiated yet." */ - circid_t next_circ_id; /**< Which circ_id do we try to use next on - * this connection? This is always in the - * range 0..1<<15-1. */ + unsigned int wide_circ_ids:1; + uint16_t link_proto; /**< What protocol version are we using? 0 for + * "none negotiated yet." */ or_handshake_state_t *handshake_state; /**< If we are setting this connection * up, state information to do so. */ + time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/ time_t timestamp_last_added_nonpadding; /** When did we last add a * non-padding cell to the outbuf? */ @@ -1277,24 +1446,7 @@ typedef struct or_connection_t { /* XXXX we could share this among all connections. */ struct ev_token_bucket_cfg *bucket_cfg; #endif - int n_circuits; /**< How many circuits use this connection as p_conn or - * n_conn ? */ - - /** Double-linked ring of circuits with queued cells waiting for room to - * 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; @@ -1302,7 +1454,7 @@ typedef struct or_connection_t { /** Subtype of connection_t for an "edge connection" -- that is, an entry (ap) * connection, or an exit. */ typedef struct edge_connection_t { - connection_t _base; + connection_t base_; struct edge_connection_t *next_stream; /**< Points to the next stream at this * edge, if any */ @@ -1322,6 +1474,8 @@ typedef struct edge_connection_t { uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit * connection. Exit connections only. */ + uint32_t begincell_flags; /** Flags sent or received in the BEGIN cell + * for this connection */ streamid_t stream_id; /**< The stream ID used for this edge connection on its * circuit */ @@ -1337,6 +1491,8 @@ typedef struct edge_connection_t { /** True iff this connection is for a DNS request only. */ unsigned int is_dns_request:1; + /** True iff this connection is for a PTR DNS request. (exit only) */ + unsigned int is_reverse_dns_lookup:1; unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge * connections. Set once we've set the stream end, @@ -1346,12 +1502,16 @@ typedef struct edge_connection_t { * cells. */ unsigned int edge_blocked_on_circ:1; + /** Unique ID for directory requests; this used to be in connection_t, but + * that's going away and being used on channels instead. We still tag + * edge connections with dirreq_id from circuits, so it's copied here. */ + uint64_t dirreq_id; } edge_connection_t; /** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS * connection, a DNS request, a TransPort connection or a NATD connection */ typedef struct entry_connection_t { - edge_connection_t _edge; + edge_connection_t edge_; /** Nickname of planned exit node -- used with .exit support. */ char *chosen_exit_name; @@ -1424,12 +1584,46 @@ typedef struct entry_connection_t { */ unsigned int may_use_optimistic_data : 1; + /** Should we permit IPv4 and IPv6 traffic to use this connection? + * + * @{ */ + unsigned int ipv4_traffic_ok : 1; + unsigned int ipv6_traffic_ok : 1; + /** @} */ + /** Should we say we prefer IPv6 traffic? */ + unsigned int prefer_ipv6_traffic : 1; + + /** For a socks listener: should we cache IPv4/IPv6 DNS information that + * exit nodes tell us? + * + * @{ */ + unsigned int cache_ipv4_answers : 1; + unsigned int cache_ipv6_answers : 1; + /** @} */ + /** For a socks listeners: if we find an answer in our client-side DNS cache, + * should we use it? + * + * @{ */ + unsigned int use_cached_ipv4_answers : 1; + unsigned int use_cached_ipv6_answers : 1; + /** @} */ + /** For socks listeners: When we can automap an address to IPv4 or IPv6, + * do we prefer IPv6? */ + unsigned int prefer_ipv6_virtaddr : 1; + } entry_connection_t; +typedef 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_MICRODESC, /* NOTE: if we add another entry, add another bit. */ +} dir_spool_source_t; + /** Subtype of connection_t for an "directory connection" -- that is, an HTTP * connection to retrieve or serve directory material. */ typedef struct dir_connection_t { - connection_t _base; + connection_t base_; /** Which 'resource' did we ask the directory for? This is typically the part * of the URL string that defines, relative to the directory conn purpose, @@ -1444,12 +1638,8 @@ typedef struct dir_connection_t { * "spooling" of directory material to the outbuf. Otherwise, we'd have * to append everything to the outbuf in one enormous chunk. */ /** What exactly are we spooling right now? */ - 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_MICRODESC, /* NOTE: if we add another entry, add another bit. */ - } dir_spool_src : 3; + ENUM_BF(dir_spool_source_t) dir_spool_src : 3; + /** If we're fetching descriptors, what router purpose shall we assign * to them? */ uint8_t router_purpose; @@ -1468,11 +1658,15 @@ typedef struct dir_connection_t { char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for * the directory server's signing key. */ + /** Unique ID for directory requests; this used to be in connection_t, but + * that's going away and being used on channels instead. The dirserver still + * needs this for the incoming side, so it's moved here. */ + uint64_t dirreq_id; } dir_connection_t; /** Subtype of connection_t for an connection to a controller. */ typedef struct control_connection_t { - connection_t _base; + connection_t base_; uint32_t event_mask; /**< Bitfield: which events does this controller * care about? */ @@ -1499,12 +1693,12 @@ typedef struct control_connection_t { } control_connection_t; /** Cast a connection_t subtype pointer to a connection_t **/ -#define TO_CONN(c) (&(((c)->_base))) -/** Helper macro: Given a pointer to to._base, of type from*, return &to. */ -#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, _base)) +#define TO_CONN(c) (&(((c)->base_))) +/** Helper macro: Given a pointer to to.base_, of type from*, return &to. */ +#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_)) /** Cast a entry_connection_t subtype pointer to a edge_connection_t **/ -#define ENTRY_TO_EDGE_CONN(c) (&(((c))->_edge)) +#define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_)) /** Cast a entry_connection_t subtype pointer to a connection_t **/ #define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c))) @@ -1549,12 +1743,12 @@ static INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c) static INLINE entry_connection_t *TO_ENTRY_CONN(connection_t *c) { tor_assert(c->magic == ENTRY_CONNECTION_MAGIC); - return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge._base); + return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_.base_); } static INLINE entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *c) { - tor_assert(c->_base.magic == ENTRY_CONNECTION_MAGIC); - return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge); + tor_assert(c->base_.magic == ENTRY_CONNECTION_MAGIC); + return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_); } static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c) { @@ -1621,7 +1815,8 @@ typedef enum { /** A reference-counted address policy rule. */ typedef struct addr_policy_t { int refcnt; /**< Reference count */ - addr_policy_action_t policy_type:2;/**< What to do when the policy matches.*/ + /** What to do when the policy matches.*/ + ENUM_BF(addr_policy_action_t) policy_type:2; unsigned int is_private:1; /**< True iff this is the pseudo-address, * "private". */ unsigned int is_canonical:1; /**< True iff this policy is the canonical @@ -1630,7 +1825,15 @@ typedef struct addr_policy_t { maskbits_t maskbits; /**< Accept/reject all addresses <b>a</b> such that the * first <b>maskbits</b> bits of <b>a</b> match * <b>addr</b>. */ - tor_addr_t addr; /**< Base address to accept or reject. */ + /** Base address to accept or reject. + * + * Note that wildcards are treated + * differntly depending on address family. An AF_UNSPEC address means + * "All addresses, IPv4 or IPv6." An AF_INET address with maskbits==0 means + * "All IPv4 addresses" and an AF_INET6 address with maskbits == 0 means + * "All IPv6 addresses". + **/ + tor_addr_t addr; uint16_t prt_min; /**< Lowest port number to accept/reject. */ uint16_t prt_max; /**< Highest port number to accept/reject. */ } addr_policy_t; @@ -1681,7 +1884,7 @@ typedef struct download_status_t { * again? */ uint8_t n_download_failures; /**< Number of failures trying to download the * most recent descriptor. */ - download_schedule_t schedule : 8; + ENUM_BF(download_schedule_t) schedule : 8; } download_status_t; /** If n_download_failures is this high, the download can never happen. */ @@ -1760,6 +1963,8 @@ typedef struct { crypto_pk_t *onion_pkey; /**< Public RSA key for onions. */ crypto_pk_t *identity_pkey; /**< Public RSA key for signing. */ + /** Public curve25519 key for onions */ + curve25519_public_key_t *onion_curve25519_pkey; char *platform; /**< What software/operating system is this OR using? */ @@ -1770,7 +1975,10 @@ typedef struct { /** How many bytes/s is this router known to handle? */ uint32_t bandwidthcapacity; smartlist_t *exit_policy; /**< What streams will this OR permit - * to exit? NULL for 'reject *:*'. */ + * to exit on IPv4? NULL for 'reject *:*'. */ + /** What streams will this OR permit to exit on IPv6? + * NULL for 'reject *:*' */ + struct short_policy_t *ipv6_exit_policy; long uptime; /**< How many seconds the router claims to have been up */ smartlist_t *declared_family; /**< Nicknames of router which this router * claims are its family. */ @@ -1789,8 +1997,6 @@ typedef struct { /** True if, after we have added this router, we should re-launch * tests for it. */ unsigned int needs_retest_if_added:1; - /** True if ipv6_addr:ipv6_orport is preferred. */ - unsigned int ipv6_preferred:1; /** Tor can use this router for general positions in circuits; we got it * from a directory server as usual, or we're an authority and a server @@ -1813,15 +2019,6 @@ typedef struct { * things; see notes on ROUTER_PURPOSE_* macros above. */ uint8_t purpose; - - /* The below items are used only by authdirservers for - * reachability testing. */ - - /** When was the last time we could reach this OR? */ - time_t last_reachable; - /** When did we start testing reachability for this OR? */ - time_t testing_since; - } routerinfo_t; /** Information needed to keep and cache a signed extra-info document. */ @@ -1853,6 +2050,8 @@ typedef struct routerstatus_t { uint32_t addr; /**< IPv4 address for this router. */ uint16_t or_port; /**< OR port for this router. */ uint16_t dir_port; /**< Directory port for this router. */ + tor_addr_t ipv6_addr; /**< IPv6 address for this router. */ + uint16_t ipv6_orport; /**<IPV6 OR port for this router. */ unsigned int is_authority:1; /**< True iff this router is an authority. */ unsigned int is_exit:1; /**< True iff this router is a good exit. */ unsigned int is_stable:1; /**< True iff this router stays up a long time. */ @@ -1882,30 +2081,23 @@ typedef struct routerstatus_t { * included.) We'll replace all these with a big tor_version_t or a char[] * if the number of traits we care about ever becomes incredibly big. */ unsigned int version_known:1; - /** True iff this router is a version that supports BEGIN_DIR cells. */ - unsigned int version_supports_begindir:1; - /** True iff this router is a version that supports conditional consensus - * downloads (signed by list of authorities). */ - unsigned int version_supports_conditional_consensus:1; - /** True iff this router is a version that we can post extrainfo docs to. */ - unsigned int version_supports_extrainfo_upload:1; - /** True iff this router is a version that, if it caches directory info, - * we can get v3 downloads from. */ - unsigned int version_supports_v3_dir:1; + /** True iff this router is a version that, if it caches directory info, * we can get microdescriptors from. */ unsigned int version_supports_microdesc_cache:1; /** True iff this router is a version that allows DATA cells to arrive on * a stream before it has sent a CONNECTED cell. */ unsigned int version_supports_optimistic_data:1; + /** True iff this router has a version that allows it to accept EXTEND2 + * cells */ + unsigned int version_supports_extend2_cells:1; 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 */ + unsigned int bw_is_unmeasured:1; /**< This is a consensus entry, with + * the Unmeasured flag set. */ - uint32_t bandwidth; /**< Bandwidth (capacity) of the router as reported in + uint32_t bandwidth_kb; /**< Bandwidth (capacity) of the router as reported in * the vote/consensus, in kilobytes/sec. */ char *exitsummary; /**< exit policy summary - * XXX weasel: this probably should not stay a string. */ @@ -1960,7 +2152,7 @@ typedef struct microdesc_t { */ time_t last_listed; /** Where is this microdescriptor currently stored? */ - saved_location_t saved_location : 3; + ENUM_BF(saved_location_t) saved_location : 3; /** If true, do not attempt to cache this microdescriptor on disk. */ unsigned int no_save : 1; /** If true, this microdesc has an entry in the microdesc_map */ @@ -1988,10 +2180,19 @@ typedef struct microdesc_t { /** As routerinfo_t.onion_pkey */ crypto_pk_t *onion_pkey; + /** As routerinfo_t.onion_curve25519_pkey */ + curve25519_public_key_t *onion_curve25519_pkey; + /** As routerinfo_t.ipv6_add */ + tor_addr_t ipv6_addr; + /** As routerinfo_t.ipv6_orport */ + uint16_t ipv6_orport; /** As routerinfo_t.family */ smartlist_t *family; - /** Exit policy summary */ + /** IPv4 exit policy summary */ short_policy_t *exit_policy; + /** IPv6 exit policy summary */ + short_policy_t *ipv6_exit_policy; + } microdesc_t; /** A node_t represents a Tor router. @@ -2026,13 +2227,13 @@ typedef struct node_t { routerstatus_t *rs; /* local info: copied from routerstatus, then possibly frobbed based - * on experience. Authorities set this stuff directly. */ + * on experience. Authorities set this stuff directly. Note that + * these reflect knowledge of the primary (IPv4) OR port only. */ unsigned int is_running:1; /**< As far as we know, is this OR currently * running? */ unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR? - * (For Authdir: Have we validated this OR?) - */ + * (For Authdir: Have we validated this OR?) */ unsigned int is_fast:1; /** Do we think this is a fast OR? */ unsigned int is_stable:1; /** Do we think this is a stable OR? */ unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */ @@ -2053,10 +2254,25 @@ typedef struct node_t { /** Local info: we treat this node as if it rejects everything */ unsigned int rejects_all:1; + /** Local info: this node is in our list of guards */ + unsigned int using_as_guard:1; + /* Local info: derived. */ + /** True if the IPv6 OR port is preferred over the IPv4 OR port. */ + unsigned int ipv6_preferred:1; + /** According to the geoip db what country is this router in? */ + /* XXXprop186 what is this suppose to mean with multiple OR ports? */ country_t country; + + /* The below items are used only by authdirservers for + * reachability testing. */ + + /** When was the last time we could reach this OR? */ + time_t last_reachable; /* IPv4. */ + time_t last_reachable6; /* IPv6. */ + } node_t; /** How many times will we try to download a router's descriptor before giving @@ -2111,7 +2327,8 @@ typedef struct networkstatus_v2_t { typedef struct vote_microdesc_hash_t { /** Next element in the list, or NULL. */ struct vote_microdesc_hash_t *next; - /** The raw contents of the microdesc hash line, excluding the "m". */ + /** The raw contents of the microdesc hash line, from the "m" through the + * newline. */ char *microdesc_hash_line; } vote_microdesc_hash_t; @@ -2119,10 +2336,15 @@ typedef struct vote_microdesc_hash_t { typedef struct vote_routerstatus_t { routerstatus_t status; /**< Underlying 'status' object for this router. * Flags are redundant. */ + /** How many known-flags are allowed in a vote? This is the width of + * the flags field of vote_routerstatus_t */ +#define MAX_KNOWN_FLAGS_IN_VOTE 64 uint64_t flags; /**< Bit-field for all recognized flags; index into * networkstatus_t.known_flags. */ char *version; /**< The version that the authority says this router is * running. */ + unsigned int has_measured_bw:1; /**< The vote had a measured bw */ + uint32_t measured_bw_kb; /**< Measured bandwidth (capacity) of the router */ /** The hash or hashes that the authority claims this microdesc has. */ vote_microdesc_hash_t *microdesc; } vote_routerstatus_t; @@ -2186,8 +2408,11 @@ typedef enum { /** A common structure to hold a v3 network status vote, or a v3 network * status consensus. */ typedef struct networkstatus_t { - networkstatus_type_t type : 8; /**< Vote, consensus, or opinion? */ - consensus_flavor_t flavor : 8; /**< If a consensus, what kind? */ + ENUM_BF(networkstatus_type_t) type : 8; /**< Vote, consensus, or opinion? */ + ENUM_BF(consensus_flavor_t) flavor : 8; /**< If a consensus, what kind? */ + unsigned int has_measured_bws : 1;/**< True iff this networkstatus contains + * measured= bandwidth values. */ + 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 @@ -2325,6 +2550,9 @@ typedef struct extend_info_t { uint16_t port; /**< OR port. */ tor_addr_t addr; /**< IP address. */ crypto_pk_t *onion_key; /**< Current onionskin key. */ +#ifdef CURVE25519_ENABLED + curve25519_public_key_t curve25519_onion_key; +#endif } extend_info_t; /** Certificate for v3 directory protocol: binds long-term authority identity @@ -2377,8 +2605,25 @@ typedef enum { MICRODESC_DIRINFO=1 << 6, } dirinfo_type_t; +#define ALL_DIRINFO ((dirinfo_type_t)((1<<7)-1)) + #define CRYPT_PATH_MAGIC 0x70127012u +struct fast_handshake_state_t; +struct ntor_handshake_state_t; +#define ONION_HANDSHAKE_TYPE_TAP 0x0000 +#define ONION_HANDSHAKE_TYPE_FAST 0x0001 +#define ONION_HANDSHAKE_TYPE_NTOR 0x0002 +#define MAX_ONION_HANDSHAKE_TYPE 0x0002 +typedef struct { + uint16_t tag; + union { + struct fast_handshake_state_t *fast; + crypto_dh_t *tap; + struct ntor_handshake_state_t *ntor; + } u; +} onion_handshake_state_t; + /** Holds accounting information for a single step in the layered encryption * performed by a circuit. Used only at the client edge of a circuit. */ typedef struct crypt_path_t { @@ -2397,17 +2642,15 @@ typedef struct crypt_path_t { /** Digest state for cells heading away from the OR at this step. */ crypto_digest_t *b_digest; - /** Current state of Diffie-Hellman key negotiation with the OR at this + /** Current state of the handshake as performed with the OR at this * step. */ - crypto_dh_t *dh_handshake_state; - /** Current state of 'fast' (non-PK) key negotiation with the OR at this - * step. Used to save CPU when TLS is already providing all the - * authentication, secrecy, and integrity we need, and we're already - * distinguishable from an OR. - */ - uint8_t fast_handshake_state[DIGEST_LEN]; + onion_handshake_state_t handshake_state; + /** Diffie-hellman handshake state for performing an introduction + * operations */ + crypto_dh_t *rend_dh_handshake_state; + /** Negotiated key material shared with the OR at this step. */ - char handshake_digest[DIGEST_LEN];/* KH in tor-spec.txt */ + char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */ /** Information to extend to the OR at this step. */ extend_info_t *extend_info; @@ -2448,10 +2691,6 @@ typedef struct { #define CPATH_KEY_MATERIAL_LEN (20*2+16*2) #define DH_KEY_LEN DH_BYTES -#define ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\ - CIPHER_KEY_LEN+\ - DH_KEY_LEN) -#define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN) /** Information used to build a circuit. */ typedef struct { @@ -2480,32 +2719,11 @@ 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 +struct create_cell_t; + /** * A circuit is a path over the onion routing * network. Applications can connect to one end of the circuit, and can @@ -2533,23 +2751,39 @@ typedef struct circuit_t { uint32_t magic; /**< For memory and type debugging: must equal * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */ - /** Queue of cells waiting to be transmitted on n_conn. */ - cell_queue_t n_conn_cells; - /** The OR connection that is next in this circuit. */ - or_connection_t *n_conn; - /** The circuit_id used in the next (forward) hop of this circuit. */ + /** The channel that is next in this circuit. */ + channel_t *n_chan; + + /** + * The circuit_id used in the next (forward) hop of this circuit; + * this is unique to n_chan, but this ordered pair is globally + * unique: + * + * (n_chan->global_identifier, n_circ_id) + */ circid_t n_circ_id; - /** The hop to which we want to extend this circuit. Should be NULL if - * the circuit has attached to a connection. */ + /** + * Circuit mux associated with n_chan to which this circuit is attached; + * NULL if we have no n_chan. + */ + circuitmux_t *n_mux; + + /** Queue of cells waiting to be transmitted on n_chan */ + cell_queue_t n_chan_cells; + + /** + * The hop to which we want to extend this circuit. Should be NULL if + * the circuit has attached to a channel. + */ extend_info_t *n_hop; - /** True iff we are waiting for n_conn_cells to become less full before + /** True iff we are waiting for n_chan_cells to become less full before * allowing p_streams to add any more cells. (Origin circuit only.) */ - unsigned int streams_blocked_on_n_conn : 1; - /** True iff we are waiting for p_conn_cells to become less full before + unsigned int streams_blocked_on_n_chan : 1; + /** True iff we are waiting for p_chan_cells to become less full before * allowing n_streams to add any more cells. (OR circuit only.) */ - unsigned int streams_blocked_on_p_conn : 1; + unsigned int streams_blocked_on_p_chan : 1; uint8_t state; /**< Current status of this circuit. */ uint8_t purpose; /**< Why are we creating this circuit? */ @@ -2564,15 +2798,24 @@ typedef struct circuit_t { * more. */ int deliver_window; - /** For storage while n_conn is pending - * (state CIRCUIT_STATE_OR_WAIT). When defined, it is always - * length ONIONSKIN_CHALLENGE_LEN. */ - char *n_conn_onionskin; + /** For storage while n_chan is pending (state CIRCUIT_STATE_CHAN_WAIT). */ + struct create_cell_t *n_chan_create_cell; + + /** When did circuit construction actually begin (ie send the + * CREATE cell or begin cannibalization). + * + * Note: This timer will get reset if we decide to cannibalize + * a circuit. It may also get reset during certain phases of hidden + * service circuit use. + * + * We keep this timestamp with a higher resolution than most so that the + * circuit-build-time tracking code can get millisecond resolution. + */ + struct timeval timestamp_began; - /** When was this circuit created? We keep this timestamp with a higher - * resolution than most so that the circuit-build-time tracking code can - * get millisecond resolution. */ + /** This timestamp marks when the init_circuit_base constructor ran. */ struct timeval timestamp_created; + /** When the circuit was first used, or 0 if the circuit is clean. * * XXXX023 Note that some code will artifically adjust this value backward @@ -2593,23 +2836,19 @@ typedef struct circuit_t { const char *marked_for_close_file; /**< For debugging: in which file was this * circuit marked for close? */ + /** Unique ID for measuring tunneled network status requests. */ + uint64_t dirreq_id; + + struct circuit_t *next; /**< Next circuit in linked list of all circuits. */ + /** Next circuit in the doubly-linked ring of circuits waiting to add * cells to n_conn. NULL if we have no cells pending, or if we're not * linked to an OR connection. */ - struct circuit_t *next_active_on_n_conn; + struct circuit_t *next_active_on_n_chan; /** Previous circuit in the doubly-linked ring of circuits waiting to add * cells to n_conn. NULL if we have no cells pending, or if we're not * 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; + struct circuit_t *prev_active_on_n_chan; } circuit_t; /** Largest number of relay_early cells that we can send on a given @@ -2618,25 +2857,64 @@ typedef struct circuit_t { /** * Describes the circuit building process in simplified terms based - * on the path bias accounting state for a circuit. Created to prevent - * overcounting due to unknown cases of circuit reuse. See Bug #6475. + * on the path bias accounting state for a circuit. + * + * NOTE: These state values are enumerated in the order for which we + * expect circuits to transition through them. If you add states, + * you need to preserve this overall ordering. The various pathbias + * state transition and accounting functions (pathbias_mark_* and + * pathbias_count_*) contain ordinal comparisons to enforce proper + * state transitions for corrections. + * + * This state machine and the associated logic was created to prevent + * miscounting due to unknown cases of circuit reuse. See also tickets + * #6475 and #7802. */ typedef enum { /** This circuit is "new". It has not yet completed a first hop * or been counted by the path bias code. */ PATH_STATE_NEW_CIRC = 0, - /** This circuit has completed a first hop, and has been counted by + /** This circuit has completed one/two hops, and has been counted by * the path bias logic. */ - PATH_STATE_DID_FIRST_HOP = 1, - /** This circuit has been completely built, and has been counted as - * successful by the path bias logic. */ - PATH_STATE_SUCCEEDED = 2, + PATH_STATE_BUILD_ATTEMPTED = 1, + /** This circuit has been completely built */ + PATH_STATE_BUILD_SUCCEEDED = 2, + /** Did we try to attach any SOCKS streams or hidserv introductions to + * this circuit? + * + * Note: If we ever implement end-to-end stream timing through test + * stream probes (#5707), we must *not* set this for those probes + * (or any other automatic streams) because the adversary could + * just tag at a later point. + */ + PATH_STATE_USE_ATTEMPTED = 3, + /** Did any SOCKS streams or hidserv introductions actually succeed on + * this circuit? + * + * If any streams detatch/fail from this circuit, the code transitions + * the circuit back to PATH_STATE_USE_ATTEMPTED to ensure we probe. See + * pathbias_mark_use_rollback() for that. + */ + PATH_STATE_USE_SUCCEEDED = 4, + + /** + * This is a special state to indicate that we got a corrupted + * relay cell on a circuit and we don't intend to probe it. + */ + PATH_STATE_USE_FAILED = 5, + + /** + * This is a special state to indicate that we already counted + * the circuit. Used to guard against potential state machine + * violations. + */ + PATH_STATE_ALREADY_COUNTED = 6, } path_state_t; /** An origin_circuit_t holds data necessary to build and use a circuit. */ typedef struct origin_circuit_t { - circuit_t _base; + circuit_t base_; /** Linked list of AP streams (or EXIT streams if hidden service) * associated with this circuit. */ @@ -2666,9 +2944,36 @@ typedef struct origin_circuit_t { * cannibalized circuits. */ unsigned int has_opened : 1; - /** Kludge to help us prevent the warn in bug #6475 and eventually - * debug why we are not seeing first hops in some cases. */ - path_state_t path_state : 2; + /** + * Path bias state machine. Used to ensure integrity of our + * circuit building and usage accounting. See path_state_t + * for more details. + */ + ENUM_BF(path_state_t) path_state : 3; + + /* If this flag is set, we should not consider attaching any more + * connections to this circuit. */ + unsigned int unusable_for_new_conns : 1; + + /** + * Tristate variable to guard against pathbias miscounting + * due to circuit purpose transitions changing the decision + * of pathbias_should_count(). This variable is informational + * only. The current results of pathbias_should_count() are + * the official decision for pathbias accounting. + */ + uint8_t pathbias_shouldcount; +#define PATHBIAS_SHOULDCOUNT_UNDECIDED 0 +#define PATHBIAS_SHOULDCOUNT_IGNORED 1 +#define PATHBIAS_SHOULDCOUNT_COUNTED 2 + + /** For path probing. Store the temporary probe stream ID + * for response comparison */ + streamid_t pathbias_probe_id; + + /** For path probing. Store the temporary probe address nonce + * (in host byte order) for response comparison. */ + uint32_t pathbias_probe_nonce; /** Set iff this is a hidden-service circuit which has timed out * according to our current circuit-build timeout, but which has @@ -2686,6 +2991,10 @@ typedef struct origin_circuit_t { * service-side introduction circuits never have this flag set.) */ unsigned int hs_circ_has_timed_out : 1; + /** Set iff this circuit has been given a relaxed timeout because + * no circuits have opened. Used to prevent spamming logs. */ + unsigned int relaxed_timeout : 1; + /** Set iff this is a service-side rendezvous circuit for which a * new connection attempt has been launched. We consider launching * a new service-side rend circ to a client when the previous one @@ -2763,29 +3072,42 @@ typedef struct origin_circuit_t { * ISO_STREAM. */ uint64_t associated_isolated_stream_global_id; /**@}*/ - + /** A list of addr_policy_t for this circuit in particular. Used by + * adjust_exit_policy_from_exitpolicy_failure. + */ + smartlist_t *prepend_policy; } origin_circuit_t; +struct onion_queue_t; + /** An or_circuit_t holds information needed to implement a circuit at an * OR. */ typedef struct or_circuit_t { - circuit_t _base; + circuit_t base_; /** Next circuit in the doubly-linked ring of circuits waiting to add - * cells to p_conn. NULL if we have no cells pending, or if we're not + * cells to p_chan. NULL if we have no cells pending, or if we're not * linked to an OR connection. */ - struct circuit_t *next_active_on_p_conn; + struct circuit_t *next_active_on_p_chan; /** Previous circuit in the doubly-linked ring of circuits waiting to add - * cells to p_conn. NULL if we have no cells pending, or if we're not + * cells to p_chan. NULL if we have no cells pending, or if we're not * linked to an OR connection. */ - struct circuit_t *prev_active_on_p_conn; + struct circuit_t *prev_active_on_p_chan; + /** Pointer to an entry on the onion queue, if this circuit is waiting for a + * chance to give an onionskin to a cpuworker. Used only in onion.c */ + struct onion_queue_t *onionqueue_entry; /** The circuit_id used in the previous (backward) hop of this circuit. */ circid_t p_circ_id; /** Queue of cells waiting to be transmitted on p_conn. */ - cell_queue_t p_conn_cells; - /** The OR connection that is previous in this circuit. */ - or_connection_t *p_conn; + cell_queue_t p_chan_cells; + /** The channel that is previous in this circuit. */ + channel_t *p_chan; + /** + * Circuit mux associated with p_chan to which this circuit is attached; + * NULL if we have no p_chan. + */ + circuitmux_t *p_mux; /** Linked list of Exit streams associated with this circuit. */ edge_connection_t *n_streams; /** Linked list of Exit streams associated with this circuit that are @@ -2825,7 +3147,8 @@ typedef struct or_circuit_t { char rend_token[REND_TOKEN_LEN]; /* ???? move to a subtype or adjunct structure? Wastes 20 bytes -NM */ - char handshake_digest[DIGEST_LEN]; /**< Stores KH for the handshake. */ + /** Stores KH for the handshake. */ + char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */ /** How many more relay_early cells can we send on this circuit, according * to the specification? */ @@ -2842,14 +3165,10 @@ typedef struct or_circuit_t { * 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. */ -#define TO_CIRCUIT(x) (&((x)->_base)) +#define TO_CIRCUIT(x) (&((x)->base_)) /** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert * if the cast is impossible. */ @@ -2930,13 +3249,40 @@ typedef struct port_cfg_t { uint8_t isolation_flags; /**< Zero or more isolation flags */ int session_group; /**< A session group, or -1 if this port is not in a * session group. */ + /* Socks only: */ + /** When both no-auth and user/pass are advertised by a SOCKS client, select + * no-auth. */ + unsigned int socks_prefer_no_auth : 1; /* Server port types (or, dir) only: */ unsigned int no_advertise : 1; unsigned int no_listen : 1; unsigned int all_addrs : 1; - unsigned int ipv4_only : 1; - unsigned int ipv6_only : 1; + unsigned int bind_ipv4_only : 1; + unsigned int bind_ipv6_only : 1; + + /* Client port types only: */ + unsigned int ipv4_traffic : 1; + unsigned int ipv6_traffic : 1; + unsigned int prefer_ipv6 : 1; + + /** For a socks listener: should we cache IPv4/IPv6 DNS information that + * exit nodes tell us? + * + * @{ */ + unsigned int cache_ipv4_answers : 1; + unsigned int cache_ipv6_answers : 1; + /** @} */ + /** For a socks listeners: if we find an answer in our client-side DNS cache, + * should we use it? + * + * @{ */ + unsigned int use_cached_ipv4_answers : 1; + unsigned int use_cached_ipv6_answers : 1; + /** @} */ + /** For socks listeners: When we can automap an address to IPv4 or IPv6, + * do we prefer IPv6? */ + unsigned int prefer_ipv6_virtaddr : 1; /* Unix sockets only: */ /** Path for an AF_UNIX address */ @@ -2972,7 +3318,7 @@ typedef struct routerset_t routerset_t; /** Configuration options for a Tor process. */ typedef struct { - uint32_t _magic; + uint32_t magic_; /** What should the tor process actually do? */ enum { @@ -3014,7 +3360,7 @@ typedef struct { * ORs not to consider as exits. */ /** Union of ExcludeNodes and ExcludeExitNodes */ - routerset_t *_ExcludeExitNodesUnion; + routerset_t *ExcludeExitNodesUnion_; int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our * process for all current and future memory. */ @@ -3022,7 +3368,7 @@ typedef struct { /** List of "entry", "middle", "exit", "introduction", "rendezvous". */ smartlist_t *AllowInvalidNodes; /** Bitmask; derived from AllowInvalidNodes. */ - invalid_router_usage_t _AllowInvalid; + invalid_router_usage_t AllowInvalid_; config_line_t *ExitPolicy; /**< Lists of exit policy components. */ int ExitPolicyRejectPrivate; /**< Should we not exit to local addresses? */ config_line_t *SocksPolicy; /**< Lists of socks policy components */ @@ -3043,7 +3389,11 @@ typedef struct { /** Addresses to bind for listening for control connections. */ config_line_t *ControlListenAddress; /** Local address to bind outbound sockets */ - char *OutboundBindAddress; + config_line_t *OutboundBindAddress; + /** IPv4 address derived from OutboundBindAddress. */ + tor_addr_t OutboundBindAddressIPv4_; + /** IPv6 address derived from OutboundBindAddress. */ + tor_addr_t OutboundBindAddressIPv6_; /** Directory server only: which versions of * Tor should we tell users to run? */ config_line_t *RecommendedVersions; @@ -3116,7 +3466,7 @@ typedef struct { char *BridgePassword; /** If BridgePassword is set, this is a SHA256 digest of the basic http * authenticator for it. Used so we can do a time-independent comparison. */ - char *_BridgePassword_AuthDigest; + char *BridgePassword_AuthDigest_; int UseBridges; /**< Boolean: should we start all circuits with a bridge? */ config_line_t *Bridges; /**< List of bootstrap bridge addresses. */ @@ -3127,6 +3477,9 @@ typedef struct { config_line_t *ServerTransportPlugin; /**< List of client transport plugins. */ + /** List of TCP/IP addresses that transports should listen at. */ + config_line_t *ServerTransportListenAddr; + int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make * this explicit so we can change how we behave in the * future. */ @@ -3142,7 +3495,7 @@ typedef struct { * "v1", "v2", "v3", "bridge", or "". */ smartlist_t *PublishServerDescriptor; /** A bitfield of authority types, derived from PublishServerDescriptor. */ - dirinfo_type_t _PublishServerDescriptor; + dirinfo_type_t PublishServerDescriptor_; /** Boolean: do we publish hidden service descriptors to the HS auths? */ int PublishHidServDescriptors; int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */ @@ -3175,7 +3528,7 @@ typedef struct { int CloseHSServiceRendCircuitsImmediatelyOnTimeout; int ConnLimit; /**< Demanded minimum number of simultaneous connections. */ - int _ConnLimit; /**< Maximum allowed number of simultaneous connections. */ + int ConnLimit_; /**< Maximum allowed number of simultaneous connections. */ int RunAsDaemon; /**< If true, run in the background. (Unix only) */ int FascistFirewall; /**< Whether to prefer ORs reachable on open ports. */ smartlist_t *FirewallPorts; /**< Which ports our firewall allows @@ -3234,9 +3587,7 @@ typedef struct { * 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? */ + int MaxOnionQueueDelay; /**<DOCDOC*/ int NewCircuitPeriod; /**< How long do we use a circuit before building * a new one? */ int MaxCircuitDirtiness; /**< Never use circs that were first used more than @@ -3288,7 +3639,14 @@ typedef struct { /** List of configuration lines for replacement directory authorities. * If you just want to replace one class of authority at a time, * use the "Alternate*Authority" options below instead. */ - config_line_t *DirServers; + config_line_t *DirAuthorities; + + /** List of fallback directory servers */ + config_line_t *FallbackDir; + + /** Weight to apply to all directory authority rates if considering them + * along with fallbackdirs */ + double DirAuthorityFallbackRate; /** If set, use these main (currently v3) directory authorities and * not the default ones. */ @@ -3336,6 +3694,7 @@ typedef struct { int AuthDirMaxServersPerAuthAddr; /**< Do not permit more than this * number of servers per IP address shared * with an authority. */ + int AuthDirHasIPv6Connectivity; /**< Boolean: are we on IPv6? */ /** If non-zero, always vote the Fast flag for any relay advertising * this amount of capacity or more. */ @@ -3378,7 +3737,7 @@ typedef struct { /* Derived from SafeLogging */ enum { SAFELOG_SCRUB_ALL, SAFELOG_SCRUB_RELAY, SAFELOG_SCRUB_NONE - } _SafeLogging; + } SafeLogging_; int SafeSocks; /**< Boolean: should we outright refuse application * connections that use socks4 or socks5-with-local-dns? */ @@ -3397,6 +3756,10 @@ typedef struct { 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? */ + int UseEntryGuardsAsDirGuards; /** Boolean: Do we try to get directory info + * from a smallish number of fixed nodes? */ + int NumDirectoryGuards; /**< How many dir guards do we try to establish? + * If 0, use value from NumEntryGuards. */ int RephistTrackTime; /**< How many seconds do we keep rephist info? */ int FastFirstHopPK; /**< If Tor believes it is safe, should we save a third * of our PK time by sending CREATE_FAST cells? */ @@ -3407,8 +3770,10 @@ typedef struct { /** 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. */ + char *VirtualAddrNetworkIPv4; /**< Address and mask to hand out for virtual + * MAPADDRESS requests for IPv4 addresses */ + char *VirtualAddrNetworkIPv6; /**< Address and mask to hand out for virtual + * MAPADDRESS requests for IPv6 addresses */ int ServerDNSSearchDomains; /**< Boolean: If set, we don't force exit * addresses to be FQDNs, but rather search for them in * the local domains. */ @@ -3502,6 +3867,13 @@ typedef struct { * over randomly chosen exits. */ int ClientRejectInternalAddresses; + /** If true, clients may connect over IPv6. XXX we don't really + enforce this -- clients _may_ set up outgoing IPv6 connections + even when this option is not set. */ + int ClientUseIPv6; + /** If true, prefer an IPv6 OR port over an IPv4 one. */ + int ClientPreferIPv6ORPort; + /** The length of time that we think a consensus should be fresh. */ int V3AuthVotingInterval; /** The length of time we think it will take to distribute votes. */ @@ -3522,6 +3894,10 @@ typedef struct { * consensus vote on the 'params' line. */ char *ConsensusParams; + /** Authority only: minimum number of measured bandwidths we must see + * before we only beliee measured bandwidths to assign flags. */ + int MinMeasuredBWsForAuthToIgnoreAdvertised; + /** The length of time that we think an initial consensus should be fresh. * Only altered on testing networks. */ int TestingV3AuthInitialVotingInterval; @@ -3549,17 +3925,25 @@ typedef struct { * of certain configuration options. */ int TestingTorNetwork; - /** File to check for a consensus networkstatus, if we don't have one - * cached. */ - char *FallbackNetworkstatusFile; + /** Minimum value for the Exit flag threshold on testing networks. */ + uint64_t TestingMinExitFlagThreshold; + + /** Minimum value for the Fast flag threshold on testing networks. */ + uint64_t TestingMinFastFlagThreshold; /** If true, and we have GeoIP data, and we're a bridge, keep a per-country * count of how many client addresses have contacted us so that we can help * the bridge authority guess which countries have blocked access to us. */ int BridgeRecordUsageByCountry; - /** Optionally, a file with GeoIP data. */ + /** Optionally, IPv4 and IPv6 GeoIP data. */ char *GeoIPFile; + char *GeoIPv6File; + + /** Autobool: if auto, then any attempt to Exclude{Exit,}Nodes a particular + * country code will exclude all nodes in ?? and A1. If true, all nodes in + * ?? and A1 are excluded. Has no effect if we don't know any GeoIP data. */ + int GeoIPExcludeUnknown; /** If true, SIGHUP should reload the torrc. Sometimes controllers want * to make this false. */ @@ -3583,13 +3967,13 @@ typedef struct { /** If true, do not enable IOCP on windows with bufferevents, even if * we think we could. */ int DisableIOCP; - /** For testing only: will go away in 0.2.3.x. */ - int _UseFilteringSSLBufferevents; + /** For testing only: will go away eventually. */ + int UseFilteringSSLBufferevents; /** Set to true if the TestingTorNetwork configuration option is set. * This is used so that options_validate() has a chance to realize that * the defaults have changed. */ - int _UsingTestNetworkDefaults; + int UsingTestNetworkDefaults_; /** If 1, we try to use microdescriptors to build circuits. If 0, we don't. * If -1, Tor decides. */ @@ -3621,19 +4005,94 @@ typedef struct { /** * Parameters for path-bias detection. * @{ + * These options override the default behavior of Tor's (**currently + * experimental**) path bias detection algorithm. To try to find broken or + * misbehaving guard nodes, Tor looks for nodes where more than a certain + * fraction of circuits through that guard fail to get built. + * + * The PathBiasCircThreshold option controls how many circuits we need to + * build through a guard before we make these checks. The + * PathBiasNoticeRate, PathBiasWarnRate and PathBiasExtremeRate options + * control what fraction of circuits must succeed through a guard so we + * won't write log messages. If less than PathBiasExtremeRate circuits + * succeed *and* PathBiasDropGuards is set to 1, we disable use of that + * guard. + * + * When we have seen more than PathBiasScaleThreshold circuits through a + * guard, we scale our observations by 0.5 (governed by the consensus) so + * that new observations don't get swamped by old ones. + * + * By default, or if a negative value is provided for one of these options, + * Tor uses reasonable defaults from the networkstatus consensus document. + * If no defaults are available there, these options default to 150, .70, + * .50, .30, 0, and 300 respectively. */ int PathBiasCircThreshold; double PathBiasNoticeRate; - double PathBiasDisableRate; + double PathBiasWarnRate; + double PathBiasExtremeRate; + int PathBiasDropGuards; int PathBiasScaleThreshold; - int PathBiasScaleFactor; /** @} */ + /** + * Parameters for path-bias use detection + * @{ + * Similar to the above options, these options override the default behavior + * of Tor's (**currently experimental**) path use bias detection algorithm. + * + * Where as the path bias parameters govern thresholds for successfully + * building circuits, these four path use bias parameters govern thresholds + * only for circuit usage. Circuits which receive no stream usage are not + * counted by this detection algorithm. A used circuit is considered + * successful if it is capable of carrying streams or otherwise receiving + * well-formed responses to RELAY cells. + * + * By default, or if a negative value is provided for one of these options, + * Tor uses reasonable defaults from the networkstatus consensus document. + * If no defaults are available there, these options default to 20, .80, + * .60, and 100, respectively. + */ + int PathBiasUseThreshold; + double PathBiasNoticeUseRate; + double PathBiasExtremeUseRate; + int PathBiasScaleUseThreshold; + /** @} */ + + int IPv6Exit; /**< Do we support exiting to IPv6 addresses? */ + + char *TLSECGroup; /**< One of "P256", "P224", or nil for auto */ + + /** Autobool: should we use the ntor handshake if we can? */ + int UseNTorHandshake; + + /** Fraction: */ + double PathsNeededToBuildCircuits; + + /** Do we serve v2 directory info at all? This is a temporary option, since + * we'd like to disable v2 directory serving entirely, but we need a way to + * make it temporarily disableable, in order to do fast testing and be + * able to turn it back on if it turns out to be non-workable. + * + * XXXX025 Make this always-on, or always-off. Right now, it's only + * enableable for authorities. + */ + int DisableV2DirectoryInfo_; + + /** What expiry time shall we place on our SSL certs? "0" means we + * should guess a suitable value. */ + int SSLKeyLifetime; + + /** How long (seconds) do we keep a guard before picking a new one? */ + int GuardLifetime; + + /** Should we send the timestamps that pre-023 hidden services want? */ + int Support022HiddenServices; } or_options_t; /** Persistent state for an onion router, as saved to disk. */ typedef struct { - uint32_t _magic; + uint32_t magic_; /** The time at which we next plan to write the state to the disk. Equal to * TIME_MAX if there are no savable changes, 0 if there are changes that * should be saved right away. */ @@ -3753,6 +4212,10 @@ struct socks_request_t { * make sure we send back a socks reply for * every connection. */ unsigned int got_auth : 1; /**< Have we received any authentication data? */ + /** If this is set, we will choose "no authentication" instead of + * "username/password" authentication if both are offered. Used as input to + * parse_socks. */ + unsigned int socks_prefer_no_auth : 1; /** Number of bytes in username; 0 if username is NULL */ size_t usernamelen; @@ -4060,7 +4523,7 @@ typedef enum { typedef struct measured_bw_line_t { char node_id[DIGEST_LEN]; char node_hex[MAX_HEX_NICKNAME_LEN+1]; - long int bw; + long int bw_kb; } measured_bw_line_t; #endif @@ -4082,15 +4545,6 @@ typedef struct vote_timing_t { /********************************* geoip.c **************************/ -/** 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. @@ -4145,10 +4599,10 @@ typedef enum { /** 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 + /** Flushed last byte from buffer of the channel belonging to the * circuit that initiated a tunneled request; completes a tunneled * request. */ - DIRREQ_OR_CONN_BUFFER_FLUSHED = 4 + DIRREQ_CHANNEL_BUFFER_FLUSHED = 4 } dirreq_state_t; #define WRITE_STATS_INTERVAL (24*60*60) @@ -4239,12 +4693,12 @@ typedef struct rend_encoded_v2_service_descriptor_t { * sooner.) * * XXX023 Should this be configurable? */ -#define INTRO_POINT_LIFETIME_MIN_SECONDS 18*60*60 +#define INTRO_POINT_LIFETIME_MIN_SECONDS (18*60*60) /** The maximum number of seconds that an introduction point will last * before expiring due to old age. * * XXX023 Should this be configurable? */ -#define INTRO_POINT_LIFETIME_MAX_SECONDS 24*60*60 +#define INTRO_POINT_LIFETIME_MAX_SECONDS (24*60*60) /** Introduction point information. Used both in rend_service_t (on * the service side) and in rend_service_descriptor_t (on both the @@ -4275,12 +4729,15 @@ typedef struct rend_intro_point_t { * intro point. */ unsigned int rend_service_note_removing_intro_point_called : 1; - /** (Service side only) A digestmap recording the INTRODUCE2 cells - * this intro point's circuit has received. Each key is the digest - * of the RSA-encrypted part of a received INTRODUCE2 cell; each - * value is a pointer to the time_t at which the cell was received. - * This digestmap is used to prevent replay attacks. */ - digestmap_t *accepted_intro_rsa_parts; + /** (Service side only) A replay cache recording the RSA-encrypted parts + * of INTRODUCE2 cells this intro point's circuit has received. This is + * used to prevent replay attacks. */ + replaycache_t *accepted_intro_rsa_parts; + + /** (Service side only) Count of INTRODUCE2 cells accepted from this + * intro point. + */ + int accepted_introduce2_count; /** (Service side only) The time at which this intro point was first * published, or -1 if this intro point has not yet been @@ -4336,19 +4793,23 @@ typedef struct rend_cache_entry_t { /********************************* routerlist.c ***************************/ -/** Represents information about a single trusted directory server. */ -typedef struct trusted_dir_server_t { +/** Represents information about a single trusted or fallback directory + * server. */ +typedef struct dir_server_t { char *description; char *nickname; char *address; /**< Hostname. */ uint32_t addr; /**< IPv4 address. */ uint16_t dir_port; /**< Directory port. */ uint16_t or_port; /**< OR port: Used for tunneling connections. */ + double weight; /** Weight used when selecting this node at random */ char digest[DIGEST_LEN]; /**< Digest of identity key. */ char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only, * high-security) identity key. */ unsigned int is_running:1; /**< True iff we think this server is running. */ + unsigned int is_authority:1; /**< True iff this is a directory authority + * of some kind. */ /** True iff this server has accepted the most recent server descriptor * we tried to upload to it. */ @@ -4367,7 +4828,7 @@ typedef struct trusted_dir_server_t { * as a routerstatus_t. Not updated by the * router-status management code! **/ -} trusted_dir_server_t; +} dir_server_t; #define ROUTER_REQUIRED_MIN_BANDWIDTH (20*1024) @@ -4403,7 +4864,11 @@ typedef struct trusted_dir_server_t { #define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3) #define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4) -#define _PDS_PREFER_TUNNELED_DIR_CONNS (1<<16) +/** This node is to be chosen as a directory guard, so don't choose any + * node that's currently a guard. */ +#define PDS_FOR_GUARD (1<<5) + +#define PDS_PREFER_TUNNELED_DIR_CONNS_ (1<<16) /** Possible ways to weight routers when choosing one randomly. See * routerlist_sl_choose_by_bandwidth() for more information.*/ diff --git a/src/or/policies.c b/src/or/policies.c index 81e4809687..be4da55061 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -59,8 +59,10 @@ typedef struct policy_summary_item_t { static const char *private_nets[] = { "0.0.0.0/8", "169.254.0.0/16", "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12", - // "fc00::/7", "fe80::/10", "fec0::/10", "::/127", - NULL }; + "[::]/8", + "[fc00::]/7", "[fe80::]/10", "[fec0::]/10", "[ff00::]/8", "[::]/127", + NULL +}; /** Replace all "private" entries in *<b>policy</b> with their expanded * equivalents. */ @@ -87,7 +89,8 @@ policy_expand_private(smartlist_t **policy) memcpy(&newpolicy, p, sizeof(addr_policy_t)); newpolicy.is_private = 0; newpolicy.is_canonical = 0; - if (tor_addr_parse_mask_ports(private_nets[i], &newpolicy.addr, + if (tor_addr_parse_mask_ports(private_nets[i], 0, + &newpolicy.addr, &newpolicy.maskbits, &port_min, &port_max)<0) { tor_assert(0); } @@ -100,6 +103,49 @@ policy_expand_private(smartlist_t **policy) *policy = tmp; } +/** Expand each of the AF_UNSPEC elements in *<b>policy</b> (which indicate + * protocol-neutral wildcards) into a pair of wildcard elements: one IPv4- + * specific and one IPv6-specific. */ +void +policy_expand_unspec(smartlist_t **policy) +{ + smartlist_t *tmp; + if (!*policy) + return; + + tmp = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(*policy, addr_policy_t *, p) { + sa_family_t family = tor_addr_family(&p->addr); + if (family == AF_INET6 || family == AF_INET || p->is_private) { + smartlist_add(tmp, p); + } else if (family == AF_UNSPEC) { + addr_policy_t newpolicy_ipv4; + addr_policy_t newpolicy_ipv6; + memcpy(&newpolicy_ipv4, p, sizeof(addr_policy_t)); + memcpy(&newpolicy_ipv6, p, sizeof(addr_policy_t)); + newpolicy_ipv4.is_canonical = 0; + newpolicy_ipv6.is_canonical = 0; + if (p->maskbits != 0) { + log_warn(LD_BUG, "AF_UNSPEC policy with maskbits==%d", p->maskbits); + newpolicy_ipv4.maskbits = 0; + newpolicy_ipv6.maskbits = 0; + } + tor_addr_from_ipv4h(&newpolicy_ipv4.addr, 0); + tor_addr_from_ipv6_bytes(&newpolicy_ipv6.addr, + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); + smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy_ipv4)); + smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy_ipv6)); + addr_policy_free(p); + } else { + log_warn(LD_BUG, "Funny-looking address policy with family %d", family); + smartlist_add(tmp, p); + } + } SMARTLIST_FOREACH_END(p); + + smartlist_free(*policy); + *policy = tmp; +} + /** * Given a linked list of config lines containing "allow" and "deny" * tokens, parse them and append the result to <b>dest</b>. Return -1 @@ -144,6 +190,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest, addr_policy_list_free(result); } else { policy_expand_private(&result); + policy_expand_unspec(&result); if (*dest) { smartlist_add_all(*dest, result); @@ -319,11 +366,15 @@ addr_is_in_cc_list(uint32_t addr, const smartlist_t *cc_list) { country_t country; const char *name; + tor_addr_t tar; + if (!cc_list) return 0; - country = geoip_get_country_by_ip(addr); + /* XXXXipv6 */ + tor_addr_from_ipv4h(&tar, addr); + country = geoip_get_country_by_addr(&tar); name = geoip_get_country_name(country); - return smartlist_string_isin_case(cc_list, name); + return smartlist_contains_string_case(cc_list, name); } /** Return 1 if <b>addr</b>:<b>port</b> is permitted to publish to our @@ -386,6 +437,7 @@ validate_addr_policies(const or_options_t *options, char **msg) *msg = NULL; if (policies_parse_exit_policy(options->ExitPolicy, &addr_policy, + options->IPv6Exit, options->ExitPolicyRejectPrivate, NULL, !options->BridgeRelay)) REJECT("Error in ExitPolicy entry."); @@ -730,6 +782,10 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port, static int addr_policy_covers(addr_policy_t *a, addr_policy_t *b) { + if (tor_addr_family(&a->addr) != tor_addr_family(&b->addr)) { + /* You can't cover a different family. */ + return 0; + } /* We can ignore accept/reject, since "accept *:80, reject *:80" reduces * to "accept *:80". */ if (a->maskbits > b->maskbits) { @@ -781,24 +837,54 @@ append_exit_policy_string(smartlist_t **policy, const char *more) } } +/** Add "reject <b>addr</b>:*" to <b>dest</b>, creating the list as needed. */ +void +addr_policy_append_reject_addr(smartlist_t **dest, const tor_addr_t *addr) +{ + addr_policy_t p, *add; + memset(&p, 0, sizeof(p)); + p.policy_type = ADDR_POLICY_REJECT; + p.maskbits = tor_addr_family(addr) == AF_INET6 ? 128 : 32; + tor_addr_copy(&p.addr, addr); + p.prt_min = 1; + p.prt_max = 65535; + + add = addr_policy_get_canonical_entry(&p); + if (!*dest) + *dest = smartlist_new(); + smartlist_add(*dest, add); +} + /** Detect and excise "dead code" from the policy *<b>dest</b>. */ static void exit_policy_remove_redundancies(smartlist_t *dest) { - addr_policy_t *ap, *tmp, *victim; + addr_policy_t *ap, *tmp; int i, j; - /* Step one: find a *:* entry and cut off everything after it. */ - for (i = 0; i < smartlist_len(dest); ++i) { - ap = smartlist_get(dest, i); - if (ap->maskbits == 0 && ap->prt_min <= 1 && ap->prt_max >= 65535) { - /* This is a catch-all line -- later lines are unreachable. */ - while (i+1 < smartlist_len(dest)) { - victim = smartlist_get(dest, i+1); - smartlist_del(dest, i+1); - addr_policy_free(victim); + /* Step one: kill every ipv4 thing after *4:*, every IPv6 thing after *6:* + */ + { + int kill_v4=0, kill_v6=0; + for (i = 0; i < smartlist_len(dest); ++i) { + sa_family_t family; + ap = smartlist_get(dest, i); + family = tor_addr_family(&ap->addr); + if ((family == AF_INET && kill_v4) || + (family == AF_INET6 && kill_v6)) { + smartlist_del_keeporder(dest, i--); + addr_policy_free(ap); + continue; + } + + if (ap->maskbits == 0 && ap->prt_min <= 1 && ap->prt_max >= 65535) { + /* This is a catch-all line -- later lines are unreachable. */ + if (family == AF_INET) { + kill_v4 = 1; + } else if (family == AF_INET6) { + kill_v6 = 1; + } } - break; } } @@ -813,7 +899,7 @@ exit_policy_remove_redundancies(smartlist_t *dest) char p1[POLICY_BUF_LEN], p2[POLICY_BUF_LEN]; policy_write_item(p1, sizeof(p1), tmp, 0); policy_write_item(p2, sizeof(p2), ap, 0); - log(LOG_DEBUG, LD_CONFIG, "Removing exit policy %s (%d). It is made " + log_debug(LD_CONFIG, "Removing exit policy %s (%d). It is made " "redundant by %s (%d).", p1, j, p2, i); smartlist_del_keeporder(dest, j--); addr_policy_free(tmp); @@ -842,7 +928,7 @@ exit_policy_remove_redundancies(smartlist_t *dest) char p1[POLICY_BUF_LEN], p2[POLICY_BUF_LEN]; policy_write_item(p1, sizeof(p1), ap, 0); policy_write_item(p2, sizeof(p2), tmp, 0); - log(LOG_DEBUG, LD_CONFIG, "Removing exit policy %s. It is already " + log_debug(LD_CONFIG, "Removing exit policy %s. It is already " "covered by %s.", p1, p2); smartlist_del_keeporder(dest, i--); addr_policy_free(ap); @@ -864,12 +950,20 @@ exit_policy_remove_redundancies(smartlist_t *dest) * 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. + * + * This function is used to parse the exit policy from our torrc. For + * the functions used to parse the exit policy from a router descriptor, + * see router_add_exit_policy. */ int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, + int ipv6_exit, int rejectprivate, const char *local_address, int add_default_policy) { + if (!ipv6_exit) { + append_exit_policy_string(dest, "reject *6:*"); + } if (rejectprivate) { append_exit_policy_string(dest, "reject private:*"); if (local_address) { @@ -880,10 +974,12 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, } if (parse_addr_policy(cfg, dest, -1)) return -1; - if (add_default_policy) + if (add_default_policy) { append_exit_policy_string(dest, DEFAULT_EXIT_POLICY); - else - append_exit_policy_string(dest, "reject *:*"); + } else { + append_exit_policy_string(dest, "reject *4:*"); + append_exit_policy_string(dest, "reject *6:*"); + } exit_policy_remove_redundancies(*dest); return 0; @@ -894,7 +990,8 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, void policies_exit_policy_append_reject_star(smartlist_t **dest) { - append_exit_policy_string(dest, "reject *:*"); + append_exit_policy_string(dest, "reject *4:*"); + append_exit_policy_string(dest, "reject *6:*"); } /** Replace the exit policy of <b>node</b> with reject *:* */ @@ -970,18 +1067,23 @@ exit_policy_is_general_exit(smartlist_t *policy) /** Return false if <b>policy</b> might permit access to some addr:port; * otherwise if we are certain it rejects everything, return true. */ int -policy_is_reject_star(const smartlist_t *policy) +policy_is_reject_star(const smartlist_t *policy, sa_family_t family) { if (!policy) /*XXXX disallow NULL policies? */ return 1; - SMARTLIST_FOREACH(policy, addr_policy_t *, p, { - if (p->policy_type == ADDR_POLICY_ACCEPT) + SMARTLIST_FOREACH_BEGIN(policy, addr_policy_t *, p) { + if (p->policy_type == ADDR_POLICY_ACCEPT && + (tor_addr_family(&p->addr) == family || + tor_addr_family(&p->addr) == AF_UNSPEC)) { return 0; - else if (p->policy_type == ADDR_POLICY_REJECT && - p->prt_min <= 1 && p->prt_max == 65535 && - p->maskbits == 0) + } else if (p->policy_type == ADDR_POLICY_REJECT && + p->prt_min <= 1 && p->prt_max == 65535 && + p->maskbits == 0 && + (tor_addr_family(&p->addr) == family || + tor_addr_family(&p->addr) == AF_UNSPEC)) { return 1; - }); + } + } SMARTLIST_FOREACH_END(p); return 1; } @@ -996,20 +1098,28 @@ policy_write_item(char *buf, size_t buflen, addr_policy_t *policy, const char *addrpart; int result; const int is_accept = policy->policy_type == ADDR_POLICY_ACCEPT; - const int is_ip6 = tor_addr_family(&policy->addr) == AF_INET6; + const sa_family_t family = tor_addr_family(&policy->addr); + const int is_ip6 = (family == AF_INET6); tor_addr_to_str(addrbuf, &policy->addr, sizeof(addrbuf), 1); /* write accept/reject 1.2.3.4 */ - if (policy->is_private) + if (policy->is_private) { addrpart = "private"; - else if (policy->maskbits == 0) - addrpart = "*"; - else + } else if (policy->maskbits == 0) { + if (format_for_desc) + addrpart = "*"; + else if (family == AF_INET6) + addrpart = "*6"; + else if (family == AF_INET) + addrpart = "*4"; + else + addrpart = "*"; + } else { addrpart = addrbuf; + } - result = tor_snprintf(buf, buflen, "%s%s%s %s", - (is_ip6&&format_for_desc)?"opt ":"", + result = tor_snprintf(buf, buflen, "%s%s %s", is_accept ? "accept" : "reject", (is_ip6&&format_for_desc)?"6":"", addrpart); @@ -1189,8 +1299,8 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) for (i = 0; private_nets[i]; ++i) { tor_addr_t addr; maskbits_t maskbits; - if (tor_addr_parse_mask_ports(private_nets[i], &addr, - &maskbits, NULL, NULL)<0) { + if (tor_addr_parse_mask_ports(private_nets[i], 0, &addr, + &maskbits, NULL, NULL)<0) { tor_assert(0); } if (tor_addr_compare(&p->addr, &addr, CMP_EXACT) == 0 && @@ -1216,7 +1326,7 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) * is an exception to the shorter-representation-wins rule). */ char * -policy_summarize(smartlist_t *policy) +policy_summarize(smartlist_t *policy, sa_family_t family) { smartlist_t *summary = policy_summary_create(); smartlist_t *accepts, *rejects; @@ -1228,9 +1338,16 @@ policy_summarize(smartlist_t *policy) tor_assert(policy); /* Create the summary list */ - SMARTLIST_FOREACH(policy, addr_policy_t *, p, { + SMARTLIST_FOREACH_BEGIN(policy, addr_policy_t *, p) { + sa_family_t f = tor_addr_family(&p->addr); + if (f != AF_INET && f != AF_INET6) { + log_warn(LD_BUG, "Weird family when summarizing address policy"); + } + if (f != family) + continue; + /* XXXX-ipv6 More family work is needed */ policy_summary_add_item(summary, p); - }); + } SMARTLIST_FOREACH_END(p); /* Now create two lists of strings, one for accepted and one * for rejected ports. We take care to merge ranges so that @@ -1517,7 +1634,7 @@ short_policy_is_reject_star(const short_policy_t *policy) policy->entries[0].max_port == 65535); } -/** Decides whether addr:port is probably or definitely accepted or rejcted by +/** Decide whether addr:port is probably or definitely accepted or rejected by * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port * interpretation. */ addr_policy_result_t @@ -1527,16 +1644,29 @@ compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port, if (node->rejects_all) return ADDR_POLICY_REJECTED; - if (node->ri) + if (addr && tor_addr_family(addr) == AF_INET6) { + const short_policy_t *p = NULL; + if (node->ri) + p = node->ri->ipv6_exit_policy; + else if (node->md) + p = node->md->ipv6_exit_policy; + if (p) + return compare_tor_addr_to_short_policy(addr, port, p); + else + return ADDR_POLICY_REJECTED; + } + + if (node->ri) { return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy); - else if (node->md) { + } else if (node->md) { if (node->md->exit_policy == NULL) return ADDR_POLICY_REJECTED; else return compare_tor_addr_to_short_policy(addr, port, node->md->exit_policy); - } else + } else { return ADDR_POLICY_PROBABLY_REJECTED; + } } /** Implementation for GETINFO control command: knows the answer for questions diff --git a/src/or/policies.h b/src/or/policies.h index f00d8299b8..facbbb6b5a 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,13 +9,14 @@ * \brief Header file for policies.c. **/ -#ifndef _TOR_POLICIES_H -#define _TOR_POLICIES_H +#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.) +/* (length of + * "accept6 [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]/128:65535-65535\n" + * plus a terminating NUL, rounded up to a nice number.) */ -#define POLICY_BUF_LEN 52 +#define POLICY_BUF_LEN 72 int firewall_is_fascist_or(void); int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port); @@ -31,6 +32,7 @@ int authdir_policy_badexit_address(uint32_t addr, uint16_t port); int validate_addr_policies(const or_options_t *options, char **msg); void policy_expand_private(smartlist_t **policy); +void policy_expand_unspec(smartlist_t **policy); int policies_parse_from_options(const or_options_t *options); addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent); @@ -42,12 +44,15 @@ addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port, const node_t *node); int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, + int ipv6exit, int rejectprivate, const char *local_address, int add_default_policy); void policies_exit_policy_append_reject_star(smartlist_t **dest); +void addr_policy_append_reject_addr(smartlist_t **dest, + const tor_addr_t *addr); void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter); int exit_policy_is_general_exit(smartlist_t *policy); -int policy_is_reject_star(const smartlist_t *policy); +int policy_is_reject_star(const smartlist_t *policy, sa_family_t family); int getinfo_helper_policies(control_connection_t *conn, const char *question, char **answer, const char **errmsg); @@ -58,7 +63,7 @@ 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); +char *policy_summarize(smartlist_t *policy, sa_family_t family); short_policy_t *parse_short_policy(const char *summary); char *write_short_policy(const short_policy_t *policy); diff --git a/src/or/reasons.c b/src/or/reasons.c index c51d8ee6f5..0674474e72 100644 --- a/src/or/reasons.c +++ b/src/or/reasons.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -105,7 +105,12 @@ stream_end_reason_to_socks5_response(int reason) case END_STREAM_REASON_DESTROY: return SOCKS5_GENERAL_ERROR; case END_STREAM_REASON_DONE: - return SOCKS5_SUCCEEDED; + /* Note that 'DONE' usually indicates a successful close from the other + * side of the stream... but if we receive it before a connected cell -- + * that is, before we have sent a SOCKS reply -- that means that the + * other side of the circuit closed the connection before telling us it + * was complete. */ + return SOCKS5_CONNECTION_REFUSED; case END_STREAM_REASON_TIMEOUT: return SOCKS5_TTL_EXPIRED; case END_STREAM_REASON_NOROUTE: @@ -169,11 +174,12 @@ errno_to_stream_end_reason(int e) S_CASE(ENOTSOCK): S_CASE(EPROTONOSUPPORT): S_CASE(EAFNOSUPPORT): - E_CASE(EACCES): S_CASE(ENOTCONN): - S_CASE(ENETUNREACH): return END_STREAM_REASON_INTERNAL; + S_CASE(ENETUNREACH): S_CASE(EHOSTUNREACH): + E_CASE(EACCES): + case EPERM: return END_STREAM_REASON_NOROUTE; S_CASE(ECONNREFUSED): return END_STREAM_REASON_CONNECTREFUSED; @@ -300,8 +306,13 @@ errno_to_orconn_end_reason(int e) const char * circuit_end_reason_to_control_string(int reason) { - if (reason >= 0 && reason & END_CIRC_REASON_FLAG_REMOTE) + int is_remote = 0; + + if (reason >= 0 && reason & END_CIRC_REASON_FLAG_REMOTE) { reason &= ~END_CIRC_REASON_FLAG_REMOTE; + is_remote = 1; + } + switch (reason) { case END_CIRC_AT_ORIGIN: /* This shouldn't get passed here; it's a catch-all reason. */ @@ -323,8 +334,8 @@ circuit_end_reason_to_control_string(int reason) return "CONNECTFAILED"; case END_CIRC_REASON_OR_IDENTITY: return "OR_IDENTITY"; - case END_CIRC_REASON_OR_CONN_CLOSED: - return "OR_CONN_CLOSED"; + case END_CIRC_REASON_CHANNEL_CLOSED: + return "CHANNEL_CLOSED"; case END_CIRC_REASON_FINISHED: return "FINISHED"; case END_CIRC_REASON_TIMEOUT: @@ -338,7 +349,18 @@ circuit_end_reason_to_control_string(int reason) case END_CIRC_REASON_MEASUREMENT_EXPIRED: return "MEASUREMENT_EXPIRED"; default: - log_warn(LD_BUG, "Unrecognized reason code %d", (int)reason); + if (is_remote) { + /* + * If it's remote, it's not a bug *here*, so don't use LD_BUG, but + * do note that the someone we're talking to is speaking the Tor + * protocol with a weird accent. + */ + log_warn(LD_PROTOCOL, + "Remote server sent bogus reason code %d", reason); + } else { + log_warn(LD_BUG, + "Unrecognized reason code %d", reason); + } return NULL; } } diff --git a/src/or/reasons.h b/src/or/reasons.h index 377b61b113..fe7e67722a 100644 --- a/src/or/reasons.h +++ b/src/or/reasons.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for reasons.c. **/ -#ifndef _TOR_REASONS_H -#define _TOR_REASONS_H +#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); diff --git a/src/or/relay.c b/src/or/relay.c index a193ad8431..7f06c6e145 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,12 +10,14 @@ * receiving from circuits, plus queuing on circuits. **/ -#include <math.h> #define RELAY_PRIVATE #include "or.h" +#include "addressmap.h" #include "buffers.h" +#include "channel.h" #include "circuitbuild.h" #include "circuitlist.h" +#include "circuituse.h" #include "config.h" #include "connection.h" #include "connection_edge.h" @@ -26,6 +28,7 @@ #include "mempool.h" #include "networkstatus.h" #include "nodelist.h" +#include "onion.h" #include "policies.h" #include "reasons.h" #include "relay.h" @@ -51,6 +54,10 @@ static int circuit_resume_edge_reading_helper(edge_connection_t *conn, 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); +static void adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ, + entry_connection_t *conn, + node_t *node, + const tor_addr_t *addr); /** Stop reading on edge connections when we have this many cells * waiting on the appropriate queue. */ @@ -68,6 +75,9 @@ uint64_t stats_n_relay_cells_relayed = 0; */ uint64_t stats_n_relay_cells_delivered = 0; +/** Used to tell which stream to read from first on a circuit. */ +static tor_weak_rng_t stream_choice_rng = TOR_WEAK_RNG_INIT; + /** Update digest from the payload of cell. Assign integrity part to * cell. */ @@ -166,7 +176,7 @@ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, cell_direction_t cell_direction) { - or_connection_t *or_conn=NULL; + channel_t *chan = NULL; crypt_path_t *layer_hint=NULL; char recognized=0; int reason; @@ -184,7 +194,17 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, } if (recognized) { - edge_connection_t *conn = relay_lookup_conn(circ, cell, cell_direction, + edge_connection_t *conn = NULL; + + if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) { + pathbias_check_probe_response(circ, cell); + + /* We need to drop this cell no matter what to avoid code that expects + * a certain purpose (such as the hidserv code). */ + return 0; + } + + conn = relay_lookup_conn(circ, cell, cell_direction, layer_hint); if (cell_direction == CELL_DIRECTION_OUT) { ++stats_n_relay_cells_delivered; @@ -213,24 +233,32 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, /* not recognized. pass it on. */ if (cell_direction == CELL_DIRECTION_OUT) { cell->circ_id = circ->n_circ_id; /* switch it */ - or_conn = circ->n_conn; + chan = circ->n_chan; } else if (! CIRCUIT_IS_ORIGIN(circ)) { cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */ - or_conn = TO_OR_CIRCUIT(circ)->p_conn; + chan = TO_OR_CIRCUIT(circ)->p_chan; } else { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Dropping unrecognized inbound cell on origin circuit."); - return 0; + /* If we see unrecognized cells on path bias testing circs, + * it's bad mojo. Those circuits need to die. + * XXX: Shouldn't they always die? */ + if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) { + TO_ORIGIN_CIRCUIT(circ)->path_state = PATH_STATE_USE_FAILED; + return -END_CIRC_REASON_TORPROTOCOL; + } else { + return 0; + } } - if (!or_conn) { + if (!chan) { // XXXX Can this splice stuff be done more cleanly? if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->rend_splice && cell_direction == CELL_DIRECTION_OUT) { or_circuit_t *splice = TO_OR_CIRCUIT(circ)->rend_splice; tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED); - tor_assert(splice->_base.purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED); + tor_assert(splice->base_.purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED); cell->circ_id = splice->p_circ_id; cell->command = CELL_RELAY; /* can't be relay_early anyway */ if ((reason = circuit_receive_relay_cell(cell, TO_CIRCUIT(splice), @@ -254,7 +282,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, 0); + append_cell_to_circuit_queue(circ, chan, cell, cell_direction, 0); return 0; } @@ -351,15 +379,22 @@ 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, streamid_t on_stream) + crypt_path_t *layer_hint, streamid_t on_stream, + const char *filename, int lineno) { - or_connection_t *conn; /* where to send the cell */ + channel_t *chan; /* where to send the cell */ if (cell_direction == CELL_DIRECTION_OUT) { crypt_path_t *thishop; /* counter for repeated crypts */ - conn = circ->n_conn; - if (!CIRCUIT_IS_ORIGIN(circ) || !conn) { - log_warn(LD_BUG,"outgoing relay cell has n_conn==NULL. Dropping."); + chan = circ->n_chan; + if (!chan) { + log_warn(LD_BUG,"outgoing relay cell sent from %s:%d has n_chan==NULL." + " Dropping.", filename, lineno); + return 0; /* just drop it */ + } + if (!CIRCUIT_IS_ORIGIN(circ)) { + log_warn(LD_BUG,"outgoing relay cell sent from %s:%d on non-origin " + "circ. Dropping.", filename, lineno); return 0; /* just drop it */ } @@ -388,14 +423,14 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, return 0; /* just drop it */ } or_circ = TO_OR_CIRCUIT(circ); - conn = or_circ->p_conn; + chan = or_circ->p_chan; relay_set_digest(or_circ->p_digest, cell); if (relay_crypt_one_payload(or_circ->p_crypto, cell->payload, 1) < 0) return -1; } ++stats_n_relay_cells_relayed; - append_cell_to_circuit_queue(circ, conn, cell, cell_direction, on_stream); + append_cell_to_circuit_queue(circ, chan, cell, cell_direction, on_stream); return 0; } @@ -422,7 +457,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn; tmpconn=tmpconn->next_stream) { if (rh.stream_id == tmpconn->stream_id && - !tmpconn->_base.marked_for_close && + !tmpconn->base_.marked_for_close && tmpconn->cpath_layer == layer_hint) { log_debug(LD_APP,"found conn for stream %d.", rh.stream_id); return tmpconn; @@ -432,7 +467,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn; tmpconn=tmpconn->next_stream) { if (rh.stream_id == tmpconn->stream_id && - !tmpconn->_base.marked_for_close) { + !tmpconn->base_.marked_for_close) { log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id); if (cell_direction == CELL_DIRECTION_OUT || connection_edge_is_rendezvous_stream(tmpconn)) @@ -442,7 +477,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn; tmpconn=tmpconn->next_stream) { if (rh.stream_id == tmpconn->stream_id && - !tmpconn->_base.marked_for_close) { + !tmpconn->base_.marked_for_close) { log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id); return tmpconn; } @@ -520,9 +555,10 @@ relay_command_to_string(uint8_t command) * return 0. */ 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) +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, + const char *filename, int lineno) { cell_t cell; relay_header_t rh; @@ -561,15 +597,16 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, geoip_change_dirreq_state(circ->dirreq_id, DIRREQ_TUNNELED, DIRREQ_END_CELL_SENT); - if (cell_direction == CELL_DIRECTION_OUT && circ->n_conn) { + if (cell_direction == CELL_DIRECTION_OUT && circ->n_chan) { /* if we're using relaybandwidthrate, this conn wants priority */ - circ->n_conn->client_used = approx_time(); + channel_timestamp_client(circ->n_chan); } if (cell_direction == CELL_DIRECTION_OUT) { origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); if (origin_circ->remaining_relay_early_cells > 0 && (relay_command == RELAY_COMMAND_EXTEND || + relay_command == RELAY_COMMAND_EXTEND2 || 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 @@ -583,7 +620,8 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, * task 878. */ origin_circ->relay_early_commands[ origin_circ->relay_early_cells_sent++] = relay_command; - } else if (relay_command == RELAY_COMMAND_EXTEND) { + } else if (relay_command == RELAY_COMMAND_EXTEND || + relay_command == RELAY_COMMAND_EXTEND2) { /* If no RELAY_EARLY cells can be sent over this circuit, log which * commands have been sent as RELAY_EARLY cells before; helps debug * task 878. */ @@ -603,7 +641,7 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, } if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer, - stream_id) < 0) { + stream_id, filename, lineno) < 0) { log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing."); circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return -1; @@ -631,16 +669,16 @@ connection_edge_send_command(edge_connection_t *fromconn, tor_assert(fromconn); circ = fromconn->on_circuit; - if (fromconn->_base.marked_for_close) { + if (fromconn->base_.marked_for_close) { log_warn(LD_BUG, "called on conn that's already marked for close at %s:%d.", - fromconn->_base.marked_for_close_file, - fromconn->_base.marked_for_close); + fromconn->base_.marked_for_close_file, + fromconn->base_.marked_for_close); return 0; } if (!circ) { - if (fromconn->_base.type == CONN_TYPE_AP) { + if (fromconn->base_.type == CONN_TYPE_AP) { log_info(LD_APP,"no circ. Closing conn."); connection_mark_unattached_ap(EDGE_TO_ENTRY_CONN(fromconn), END_STREAM_REASON_INTERNAL); @@ -685,14 +723,41 @@ connection_ap_process_end_not_open( relay_header_t *rh, cell_t *cell, origin_circuit_t *circ, entry_connection_t *conn, crypt_path_t *layer_hint) { - struct in_addr in; node_t *exitrouter; int reason = *(cell->payload+RELAY_HEADER_SIZE); - int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE; + int control_reason; edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); (void) layer_hint; /* unused */ - if (rh->length > 0 && edge_reason_is_retriable(reason) && + if (rh->length > 0) { + if (reason == END_STREAM_REASON_TORPROTOCOL || + reason == END_STREAM_REASON_DESTROY) { + /* Both of these reasons could mean a failed tag + * hit the exit and it complained. Do not probe. + * Fail the circuit. */ + circ->path_state = PATH_STATE_USE_FAILED; + return -END_CIRC_REASON_TORPROTOCOL; + } else if (reason == END_STREAM_REASON_INTERNAL) { + /* We can't infer success or failure, since older Tors report + * ENETUNREACH as END_STREAM_REASON_INTERNAL. */ + } else { + /* Path bias: If we get a valid reason code from the exit, + * it wasn't due to tagging. + * + * We rely on recognized+digest being strong enough to make + * tags unlikely to allow us to get tagged, yet 'recognized' + * reason codes here. */ + pathbias_mark_use_success(circ); + } + } + + if (rh->length == 0) { + reason = END_STREAM_REASON_MISC; + } + + control_reason = reason | END_STREAM_REASON_FLAG_REMOTE; + + if (edge_reason_is_retriable(reason) && /* avoid retry if rend */ !connection_edge_is_rendezvous_stream(edge_conn)) { const char *chosen_exit_digest = @@ -702,48 +767,67 @@ connection_ap_process_end_not_open( stream_end_reason_to_string(reason)); exitrouter = node_get_mutable_by_id(chosen_exit_digest); switch (reason) { - case END_STREAM_REASON_EXITPOLICY: + case END_STREAM_REASON_EXITPOLICY: { + tor_addr_t addr; + tor_addr_make_unspec(&addr); if (rh->length >= 5) { - uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1)); - int ttl; - if (!addr) { + int ttl = -1; + tor_addr_make_unspec(&addr); + if (rh->length == 5 || rh->length == 9) { + tor_addr_from_ipv4n(&addr, + get_uint32(cell->payload+RELAY_HEADER_SIZE+1)); + if (rh->length == 9) + ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5)); + } else if (rh->length == 17 || rh->length == 21) { + tor_addr_from_ipv6_bytes(&addr, + (char*)(cell->payload+RELAY_HEADER_SIZE+1)); + if (rh->length == 21) + ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+17)); + } + if (tor_addr_is_null(&addr)) { log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,", safe_str(conn->socks_request->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return 0; } - if (rh->length >= 9) - ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5)); - else - ttl = -1; + if ((tor_addr_family(&addr) == AF_INET && !conn->ipv4_traffic_ok) || + (tor_addr_family(&addr) == AF_INET6 && !conn->ipv6_traffic_ok)) { + log_fn(LOG_PROTOCOL_WARN, LD_APP, + "Got an EXITPOLICY failure on a connection with a " + "mismatched family. Closing."); + connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + return 0; + } if (get_options()->ClientDNSRejectInternalAddresses && - is_internal_IP(addr, 0)) { + tor_addr_is_internal(&addr, 0)) { log_info(LD_APP,"Address '%s' resolved to internal. Closing,", safe_str(conn->socks_request->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return 0; } - client_dns_set_addressmap(conn->socks_request->address, addr, + + client_dns_set_addressmap(conn, + conn->socks_request->address, &addr, conn->chosen_exit_name, ttl); + + { + char new_addr[TOR_ADDR_BUF_LEN]; + tor_addr_to_str(new_addr, &addr, sizeof(new_addr), 1); + if (strcmp(conn->socks_request->address, new_addr)) { + strlcpy(conn->socks_request->address, new_addr, + sizeof(conn->socks_request->address)); + control_event_stream_status(conn, STREAM_EVENT_REMAP, 0); + } + } } /* check if he *ought* to have allowed it */ - if (exitrouter && - (rh->length < 5 || - (tor_inet_aton(conn->socks_request->address, &in) && - !conn->chosen_exit_name))) { - log_info(LD_APP, - "Exitrouter %s seems to be more restrictive than its exit " - "policy. Not using this router as exit for now.", - node_describe(exitrouter)); - policies_set_node_exitpolicy_to_reject_all(exitrouter); - } - /* rewrite it to an IP if we learned one. */ - if (addressmap_rewrite(conn->socks_request->address, - sizeof(conn->socks_request->address), - NULL, NULL)) { - control_event_stream_status(conn, STREAM_EVENT_REMAP, 0); - } + + adjust_exit_policy_from_exitpolicy_failure(circ, + conn, + exitrouter, + &addr); + if (conn->chosen_exit_optional || conn->chosen_exit_retries) { /* stop wanting a specific exit */ @@ -762,6 +846,7 @@ connection_ap_process_end_not_open( return 0; /* else, conn will get closed below */ break; + } case END_STREAM_REASON_CONNECTREFUSED: if (!conn->chosen_exit_optional) break; /* break means it'll close, below */ @@ -776,9 +861,7 @@ connection_ap_process_end_not_open( /* We haven't retried too many times; reattach the connection. */ circuit_log_path(LOG_INFO,LD_APP,circ); /* Mark this circuit "unusable for new streams". */ - /* XXXX024 this is a kludgy way to do this. */ - tor_assert(circ->_base.timestamp_dirty); - circ->_base.timestamp_dirty -= get_options()->MaxCircuitDirtiness; + mark_circuit_unusable_for_new_conns(circ); if (conn->chosen_exit_optional) { /* stop wanting a specific exit */ @@ -826,21 +909,102 @@ connection_ap_process_end_not_open( return 0; } +/** Called when we have gotten an END_REASON_EXITPOLICY failure on <b>circ</b> + * for <b>conn</b>, while attempting to connect via <b>node</b>. If the node + * told us which address it rejected, then <b>addr</b> is that address; + * otherwise it is AF_UNSPEC. + * + * If we are sure the node should have allowed this address, mark the node as + * having a reject *:* exit policy. Otherwise, mark the circuit as unusable + * for this particular address. + **/ +static void +adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ, + entry_connection_t *conn, + node_t *node, + const tor_addr_t *addr) +{ + int make_reject_all = 0; + const sa_family_t family = tor_addr_family(addr); + + if (node) { + tor_addr_t tmp; + int asked_for_family = tor_addr_parse(&tmp, conn->socks_request->address); + if (family == AF_UNSPEC) { + make_reject_all = 1; + } else if (node_exit_policy_is_exact(node, family) && + asked_for_family != -1 && !conn->chosen_exit_name) { + make_reject_all = 1; + } + + if (make_reject_all) { + log_info(LD_APP, + "Exitrouter %s seems to be more restrictive than its exit " + "policy. Not using this router as exit for now.", + node_describe(node)); + policies_set_node_exitpolicy_to_reject_all(node); + } + } + + if (family != AF_UNSPEC) + addr_policy_append_reject_addr(&circ->prepend_policy, addr); +} + /** Helper: change the socks_request->address field on conn to the - * dotted-quad representation of <b>new_addr</b> (given in host order), + * dotted-quad representation of <b>new_addr</b>, * and send an appropriate REMAP event. */ static void -remap_event_helper(entry_connection_t *conn, uint32_t new_addr) +remap_event_helper(entry_connection_t *conn, const tor_addr_t *new_addr) { - struct in_addr in; - - in.s_addr = htonl(new_addr); - tor_inet_ntoa(&in, conn->socks_request->address, - sizeof(conn->socks_request->address)); + tor_addr_to_str(conn->socks_request->address, new_addr, + sizeof(conn->socks_request->address), + 1); control_event_stream_status(conn, STREAM_EVENT_REMAP, REMAP_STREAM_SOURCE_EXIT); } +/** Extract the contents of a connected cell in <b>cell</b>, whose relay + * header has already been parsed into <b>rh</b>. On success, set + * <b>addr_out</b> to the address we're connected to, and <b>ttl_out</b> to + * the ttl of that address, in seconds, and return 0. On failure, return + * -1. */ +int +connected_cell_parse(const relay_header_t *rh, const cell_t *cell, + tor_addr_t *addr_out, int *ttl_out) +{ + uint32_t bytes; + const uint8_t *payload = cell->payload + RELAY_HEADER_SIZE; + + tor_addr_make_unspec(addr_out); + *ttl_out = -1; + if (rh->length == 0) + return 0; + if (rh->length < 4) + return -1; + bytes = ntohl(get_uint32(payload)); + + /* If bytes is 0, this is maybe a v6 address. Otherwise it's a v4 address */ + if (bytes != 0) { + /* v4 address */ + tor_addr_from_ipv4h(addr_out, bytes); + if (rh->length >= 8) { + bytes = ntohl(get_uint32(payload + 4)); + if (bytes <= INT32_MAX) + *ttl_out = bytes; + } + } else { + if (rh->length < 25) /* 4 bytes of 0s, 1 addr, 16 ipv4, 4 ttl. */ + return -1; + if (get_uint8(payload + 4) != 6) + return -1; + tor_addr_from_ipv6_bytes(addr_out, (char*)(payload + 5)); + bytes = ntohl(get_uint32(payload + 21)); + if (bytes <= INT32_MAX) + *ttl_out = (int) bytes; + } + return 0; +} + /** An incoming relay cell has arrived from circuit <b>circ</b> to * stream <b>conn</b>. * @@ -854,7 +1018,7 @@ connection_edge_process_relay_cell_not_open( edge_connection_t *conn, crypt_path_t *layer_hint) { if (rh->command == RELAY_COMMAND_END) { - if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) { + if (CIRCUIT_IS_ORIGIN(circ) && conn->base_.type == CONN_TYPE_AP) { return connection_ap_process_end_not_open(rh, cell, TO_ORIGIN_CIRCUIT(circ), EDGE_TO_ENTRY_CONN(conn), @@ -869,38 +1033,55 @@ connection_edge_process_relay_cell_not_open( } } - if (conn->_base.type == CONN_TYPE_AP && + if (conn->base_.type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) { + tor_addr_t addr; + int ttl; entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); tor_assert(CIRCUIT_IS_ORIGIN(circ)); - if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) { + if (conn->base_.state != AP_CONN_STATE_CONNECT_WAIT) { log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got 'connected' while not in state connect_wait. Dropping."); return 0; } - conn->_base.state = AP_CONN_STATE_OPEN; + conn->base_.state = AP_CONN_STATE_OPEN; log_info(LD_APP,"'connected' received after %d seconds.", - (int)(time(NULL) - conn->_base.timestamp_lastread)); - if (rh->length >= 4) { - uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE)); - int ttl; - if (!addr || (get_options()->ClientDNSRejectInternalAddresses && - is_internal_IP(addr, 0))) { + (int)(time(NULL) - conn->base_.timestamp_lastread)); + if (connected_cell_parse(rh, cell, &addr, &ttl) < 0) { + log_fn(LOG_PROTOCOL_WARN, LD_APP, + "Got a badly formatted connected cell. Closing."); + connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL); + } + if (tor_addr_family(&addr) != AF_UNSPEC) { + const sa_family_t family = tor_addr_family(&addr); + if (tor_addr_is_null(&addr) || + (get_options()->ClientDNSRejectInternalAddresses && + tor_addr_is_internal(&addr, 0))) { log_info(LD_APP, "...but it claims the IP address was %s. Closing.", - fmt_addr32(addr)); + fmt_addr(&addr)); connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL); return 0; } - if (rh->length >= 8) - ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4)); - else - ttl = -1; - client_dns_set_addressmap(entry_conn->socks_request->address, addr, + + if ((family == AF_INET && ! entry_conn->ipv4_traffic_ok) || + (family == AF_INET6 && ! entry_conn->ipv6_traffic_ok)) { + log_fn(LOG_PROTOCOL_WARN, LD_APP, + "Got a connected cell to %s with unsupported address family." + " Closing.", fmt_addr(&addr)); + connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); + connection_mark_unattached_ap(entry_conn, + END_STREAM_REASON_TORPROTOCOL); + return 0; + } + + client_dns_set_addressmap(entry_conn, + entry_conn->socks_request->address, &addr, entry_conn->chosen_exit_name, ttl); - remap_event_helper(entry_conn, addr); + remap_event_helper(entry_conn, &addr); } circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ)); /* don't send a socks reply to transparent conns */ @@ -924,6 +1105,7 @@ connection_edge_process_relay_cell_not_open( control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_STATUS, 0); break; case DIR_PURPOSE_FETCH_SERVERDESC: + case DIR_PURPOSE_FETCH_MICRODESC: control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS, count_loading_descriptors_progress()); break; @@ -944,13 +1126,13 @@ connection_edge_process_relay_cell_not_open( } return 0; } - if (conn->_base.type == CONN_TYPE_AP && + if (conn->base_.type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) { int ttl; int answer_len; uint8_t answer_type; entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); - if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) { + if (conn->base_.state != AP_CONN_STATE_RESOLVE_WAIT) { log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while " "not in state resolve_wait. Dropping."); return 0; @@ -969,12 +1151,15 @@ connection_edge_process_relay_cell_not_open( 2+answer_len)); else ttl = -1; - if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) { - uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2)); - if (get_options()->ClientDNSRejectInternalAddresses && - is_internal_IP(addr, 0)) { + if (answer_type == RESOLVED_TYPE_IPV4 || + answer_type == RESOLVED_TYPE_IPV6) { + tor_addr_t addr; + if (decode_address_from_payload(&addr, cell->payload+RELAY_HEADER_SIZE, + rh->length) && + tor_addr_is_internal(&addr, 0) && + get_options()->ClientDNSRejectInternalAddresses) { log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", - fmt_addr32(addr)); + fmt_addr(&addr)); connection_ap_handshake_socks_resolved(entry_conn, RESOLVED_TYPE_ERROR_TRANSIENT, 0, NULL, 0, TIME_MAX); @@ -990,8 +1175,15 @@ connection_edge_process_relay_cell_not_open( ttl, -1); if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) { - uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2)); - remap_event_helper(entry_conn, addr); + tor_addr_t addr; + tor_addr_from_ipv4n(&addr, + get_uint32(cell->payload+RELAY_HEADER_SIZE+2)); + remap_event_helper(entry_conn, &addr); + } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) { + tor_addr_t addr; + tor_addr_from_ipv6_bytes(&addr, + (char*)(cell->payload+RELAY_HEADER_SIZE+2)); + remap_event_helper(entry_conn, &addr); } connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DONE | @@ -1001,8 +1193,8 @@ connection_edge_process_relay_cell_not_open( log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Got an unexpected relay command %d, in state %d (%s). Dropping.", - rh->command, conn->_base.state, - conn_state_to_string(conn->_base.type, conn->_base.state)); + rh->command, conn->base_.state, + conn_state_to_string(conn->base_.type, conn->base_.state)); return 0; /* for forward compatibility, don't kill the circuit */ // connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); // connection_mark_for_close(conn); @@ -1067,9 +1259,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, * conn points to the recognized stream. */ if (conn && !connection_state_is_open(TO_CONN(conn))) { - if (conn->_base.type == CONN_TYPE_EXIT && - (conn->_base.state == EXIT_CONN_STATE_CONNECTING || - conn->_base.state == EXIT_CONN_STATE_RESOLVING) && + if (conn->base_.type == CONN_TYPE_EXIT && + (conn->base_.state == EXIT_CONN_STATE_CONNECTING || + conn->base_.state == EXIT_CONN_STATE_RESOLVING) && rh.command == RELAY_COMMAND_DATA) { /* Allow DATA cells to be delivered to an exit node in state * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING. @@ -1112,7 +1304,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, * 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; + TO_OR_CIRCUIT(circ)->p_chan->dirreq_id = circ->dirreq_id; } return connection_exit_begin_conn(cell, circ); @@ -1168,11 +1360,12 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, return 0; } /* XXX add to this log_fn the exit node's nickname? */ - log_info(domain,"%d: end cell (%s) for stream %d. Removing stream.", - conn->_base.s, + log_info(domain,TOR_SOCKET_T_FORMAT": end cell (%s) for stream %d. " + "Removing stream.", + conn->base_.s, stream_end_reason_to_string(reason), conn->stream_id); - if (conn->_base.type == CONN_TYPE_AP) { + if (conn->base_.type == CONN_TYPE_AP) { entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); if (entry_conn->socks_request && !entry_conn->socks_request->has_finished) @@ -1183,16 +1376,17 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, conn->edge_has_sent_end = 1; if (!conn->end_reason) conn->end_reason = reason | END_STREAM_REASON_FLAG_REMOTE; - if (!conn->_base.marked_for_close) { + if (!conn->base_.marked_for_close) { /* only mark it if not already marked. it's possible to * get the 'end' right around when the client hangs up on us. */ connection_mark_and_flush(TO_CONN(conn)); } return 0; - case RELAY_COMMAND_EXTEND: { + case RELAY_COMMAND_EXTEND: + case RELAY_COMMAND_EXTEND2: { static uint64_t total_n_extend=0, total_nonearly=0; total_n_extend++; - if (conn) { + if (rh.stream_id) { log_fn(LOG_PROTOCOL_WARN, domain, "'extend' cell received for non-zero stream. Dropping."); return 0; @@ -1224,17 +1418,27 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, return circuit_extend(cell, circ); } case RELAY_COMMAND_EXTENDED: + case RELAY_COMMAND_EXTENDED2: if (!layer_hint) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "'extended' unsupported at non-origin. Dropping."); return 0; } log_debug(domain,"Got an extended cell! Yay."); - if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ), - CELL_CREATED, - cell->payload+RELAY_HEADER_SIZE)) < 0) { - log_warn(domain,"circuit_finish_handshake failed."); - return reason; + { + extended_cell_t extended_cell; + if (extended_cell_parse(&extended_cell, rh.command, + (const uint8_t*)cell->payload+RELAY_HEADER_SIZE, + rh.length)<0) { + log_warn(LD_PROTOCOL, + "Can't parse EXTENDED cell; killing circuit."); + return -END_CIRC_REASON_TORPROTOCOL; + } + if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ), + &extended_cell.created_cell)) < 0) { + log_warn(domain,"circuit_finish_handshake failed."); + return reason; + } } if ((reason=circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)))<0) { log_info(domain,"circuit_send_next_onion_skin() failed."); @@ -1247,12 +1451,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, "'truncate' unsupported at origin. Dropping."); return 0; } - 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); + if (circ->n_hop) { + if (circ->n_chan) + log_warn(LD_BUG, "n_chan and n_hop set on the same circuit!"); + extend_info_free(circ->n_hop); + circ->n_hop = NULL; + tor_free(circ->n_chan_create_cell); + circuit_set_state(circ, CIRCUIT_STATE_OPEN); + } + if (circ->n_chan) { + uint8_t trunc_reason = get_uint8(cell->payload + RELAY_HEADER_SIZE); + circuit_clear_cell_queue(circ, circ->n_chan); + channel_send_destroy(circ->n_circ_id, circ->n_chan, + trunc_reason); + circuit_set_n_circid_chan(circ, 0, NULL); } log_debug(LD_EXIT, "Processed 'truncate', replying."); { @@ -1268,7 +1480,8 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, "'truncated' unsupported at non-origin. Dropping."); return 0; } - circuit_truncated(TO_ORIGIN_CIRCUIT(circ), layer_hint); + circuit_truncated(TO_ORIGIN_CIRCUIT(circ), layer_hint, + get_uint8(cell->payload + RELAY_HEADER_SIZE)); return 0; case RELAY_COMMAND_CONNECTED: if (conn) { @@ -1285,7 +1498,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (layer_hint->package_window + CIRCWINDOW_INCREMENT > CIRCWINDOW_START_MAX) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Bug/attack: unexpected sendme cell from exit relay. " + "Unexpected sendme cell from exit relay. " "Closing circ."); return -END_CIRC_REASON_TORPROTOCOL; } @@ -1297,8 +1510,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (circ->package_window + CIRCWINDOW_INCREMENT > CIRCWINDOW_START_MAX) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Bug/attack: unexpected sendme cell from client. " - "Closing circ."); + "Unexpected sendme cell from client. " + "Closing circ (window %d).", + circ->package_window); return -END_CIRC_REASON_TORPROTOCOL; } circ->package_window += CIRCWINDOW_INCREMENT; @@ -1406,21 +1620,22 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, size_t bytes_to_process, length; char payload[CELL_PAYLOAD_SIZE]; circuit_t *circ; - const unsigned domain = conn->_base.type == CONN_TYPE_AP ? LD_APP : LD_EXIT; + const unsigned domain = conn->base_.type == CONN_TYPE_AP ? LD_APP : LD_EXIT; int sending_from_optimistic = 0; - const int sending_optimistically = - conn->_base.type == CONN_TYPE_AP && - conn->_base.state != AP_CONN_STATE_OPEN; entry_connection_t *entry_conn = - conn->_base.type == CONN_TYPE_AP ? EDGE_TO_ENTRY_CONN(conn) : NULL; + conn->base_.type == CONN_TYPE_AP ? EDGE_TO_ENTRY_CONN(conn) : NULL; + const int sending_optimistically = + entry_conn && + conn->base_.type == CONN_TYPE_AP && + conn->base_.state != AP_CONN_STATE_OPEN; crypt_path_t *cpath_layer = conn->cpath_layer; tor_assert(conn); - if (conn->_base.marked_for_close) { + if (conn->base_.marked_for_close) { log_warn(LD_BUG, "called on conn that's already marked for close at %s:%d.", - conn->_base.marked_for_close_file, conn->_base.marked_for_close); + conn->base_.marked_for_close_file, conn->base_.marked_for_close); return 0; } @@ -1487,7 +1702,8 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, connection_fetch_from_buf(payload, length, TO_CONN(conn)); } - log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s, + log_debug(domain,TOR_SOCKET_T_FORMAT": Packaging %d bytes (%d waiting).", + conn->base_.s, (int)length, (int)connection_get_inbuf_len(TO_CONN(conn))); if (sending_optimistically && !sending_from_optimistic) { @@ -1553,9 +1769,9 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn) } while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) { - log_debug(conn->_base.type == CONN_TYPE_AP ?LD_APP:LD_EXIT, + log_debug(conn->base_.type == CONN_TYPE_AP ?LD_APP:LD_EXIT, "Outbuf %d, Queuing stream sendme.", - (int)conn->_base.outbuf_flushlen); + (int)conn->base_.outbuf_flushlen); conn->deliver_window += STREAMWINDOW_INCREMENT; if (connection_edge_send_command(conn, RELAY_COMMAND_SENDME, NULL, 0) < 0) { @@ -1587,6 +1803,12 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) circ, layer_hint); } +void +stream_choice_seed_weak_rng(void) +{ + crypto_seed_weak_rng(&stream_choice_rng); +} + /** A helper function for circuit_resume_edge_reading() above. * The arguments are the same, except that <b>conn</b> is the head * of a linked list of edge streams that should each be considered. @@ -1602,16 +1824,23 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, int cells_on_queue; int cells_per_conn; edge_connection_t *chosen_stream = NULL; + int max_to_package; + + if (first_conn == NULL) { + /* Don't bother to try to do the rest of this if there are no connections + * to resume. */ + return 0; + } /* 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; + max_to_package = circ->package_window; if (CIRCUIT_IS_ORIGIN(circ)) { - cells_on_queue = circ->n_conn_cells.n; + cells_on_queue = circ->n_chan_cells.n; } else { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); - cells_on_queue = or_circ->p_conn_cells.n; + cells_on_queue = or_circ->p_chan_cells.n; } if (CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue < max_to_package) max_to_package = CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue; @@ -1631,10 +1860,19 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, int num_streams = 0; for (conn = first_conn; conn; conn = conn->next_stream) { num_streams++; - if ((tor_weak_random() % num_streams)==0) + if (tor_weak_random_one_in_n(&stream_choice_rng, num_streams)) { chosen_stream = conn; + } /* Invariant: chosen_stream has been chosen uniformly at random from - * among the first num_streams streams on first_conn. */ + * among the first num_streams streams on first_conn. + * + * (Note that we iterate over every stream on the circuit, so that after + * we've considered the first stream, we've chosen it with P=1; and + * after we consider the second stream, we've switched to it with P=1/2 + * and stayed with the first stream with P=1/2; and after we've + * considered the third stream, we've switched to it with P=1/3 and + * remained with one of the first two streams with P=(2/3), giving each + * one P=(1/2)(2/3) )=(1/3).) */ } } @@ -1644,7 +1882,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, /* 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) + 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)); @@ -1655,7 +1893,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, } /* 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) + 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)); @@ -1681,7 +1919,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, * package. */ for (conn=first_conn; conn; conn=conn->next_stream) { - if (conn->_base.marked_for_close || conn->package_window <= 0) + 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; @@ -1792,10 +2030,10 @@ circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint) } #ifdef ACTIVE_CIRCUITS_PARANOIA -#define assert_active_circuits_ok_paranoid(conn) \ - assert_active_circuits_ok(conn) +#define assert_cmux_ok_paranoid(chan) \ + assert_circuit_mux_okay(chan) #else -#define assert_active_circuits_ok_paranoid(conn) +#define assert_cmux_ok_paranoid(chan) #endif /** The total number of cells we have allocated from the memory pool. */ @@ -1804,10 +2042,6 @@ static size_t 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) @@ -1826,10 +2060,6 @@ 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. */ @@ -1850,12 +2080,19 @@ packed_cell_free_unchecked(packed_cell_t *cell) /** Allocate and return a new packed_cell_t. */ static INLINE packed_cell_t * -packed_cell_alloc(void) +packed_cell_new(void) { ++total_cells_allocated; return mp_pool_get(cell_pool); } +/** Return a packed cell used outside by channel_t lower layer */ +void +packed_cell_free(packed_cell_t *cell) +{ + packed_cell_free_unchecked(cell); +} + /** Log current statistics for cell pool allocation at log level * <b>severity</b>. */ void @@ -1864,23 +2101,24 @@ dump_cell_pool_usage(int severity) circuit_t *c; int n_circs = 0; int n_cells = 0; - for (c = _circuit_get_global_list(); c; c = c->next) { - n_cells += c->n_conn_cells.n; + for (c = circuit_get_global_list_(); c; c = c->next) { + n_cells += c->n_chan_cells.n; if (!CIRCUIT_IS_ORIGIN(c)) - n_cells += TO_OR_CIRCUIT(c)->p_conn_cells.n; + n_cells += TO_OR_CIRCUIT(c)->p_chan_cells.n; ++n_circs; } - log(severity, LD_MM, "%d cells allocated on %d circuits. %d cells leaked.", - n_cells, n_circs, (int)total_cells_allocated - n_cells); + tor_log(severity, LD_MM, + "%d cells allocated on %d circuits. %d cells leaked.", + n_cells, n_circs, (int)total_cells_allocated - n_cells); mp_pool_log_status(cell_pool, severity); } /** Allocate a new copy of packed <b>cell</b>. */ static INLINE packed_cell_t * -packed_cell_copy(const cell_t *cell) +packed_cell_copy(const cell_t *cell, int wide_circ_ids) { - packed_cell_t *c = packed_cell_alloc(); - cell_pack(c, cell); + packed_cell_t *c = packed_cell_new(); + cell_pack(c, cell, wide_circ_ids); c->next = NULL; return c; } @@ -1902,43 +2140,14 @@ cell_queue_append(cell_queue_t *queue, packed_cell_t *cell) /** Append a newly allocated copy of <b>cell</b> to the end of <b>queue</b> */ void -cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell) +cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell, + int wide_circ_ids) { struct timeval now; - packed_cell_t *copy = packed_cell_copy(cell); + packed_cell_t *copy = packed_cell_copy(cell, wide_circ_ids); tor_gettimeofday_cached(&now); copy->inserted_time = (uint32_t)tv_to_msec(&now); - /* Remember the time when this cell was put in the queue. */ - /*XXXX This may be obsoleted by inserted_time */ - if (get_options()->CellStatistics) { - 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); - -#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); } @@ -1955,14 +2164,6 @@ cell_queue_clear(cell_queue_t *queue) } 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 @@ -1987,9 +2188,7 @@ cell_queue_pop(cell_queue_t *queue) size_t packed_cell_mem_cost(void) { - return sizeof(packed_cell_t) + MP_POOL_ITEM_OVERHEAD + - get_options()->CellStatistics ? - (sizeof(insertion_time_elem_t)+MP_POOL_ITEM_OVERHEAD) : 0; + return sizeof(packed_cell_t) + MP_POOL_ITEM_OVERHEAD; } /** Check whether we've got too much space used for cells. If so, @@ -2005,363 +2204,68 @@ cell_queues_check_size(void) return 0; } -/** Return a pointer to the "next_active_on_{n,p}_conn" pointer of <b>circ</b>, - * depending on whether <b>conn</b> matches n_conn or p_conn. */ -static INLINE circuit_t ** -next_circ_on_conn_p(circuit_t *circ, or_connection_t *conn) -{ - tor_assert(circ); - tor_assert(conn); - if (conn == circ->n_conn) { - return &circ->next_active_on_n_conn; - } else { - or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); - tor_assert(conn == orcirc->p_conn); - return &orcirc->next_active_on_p_conn; - } -} - -/** Return a pointer to the "prev_active_on_{n,p}_conn" pointer of <b>circ</b>, - * depending on whether <b>conn</b> matches n_conn or p_conn. */ -static INLINE circuit_t ** -prev_circ_on_conn_p(circuit_t *circ, or_connection_t *conn) -{ - tor_assert(circ); - tor_assert(conn); - if (conn == circ->n_conn) { - return &circ->prev_active_on_n_conn; - } else { - or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); - tor_assert(conn == orcirc->p_conn); - return &orcirc->prev_active_on_p_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.) +/** + * Update the number of cells available on the circuit's n_chan or p_chan's + * circuit mux. */ -static double ewma_scale_factor = 0.1; -/* DOCDOC ewma_enabled */ -static int ewma_enabled = 0; - -/*DOCDOC*/ -#define EPSILON 0.00001 -/*DOCDOC*/ -#define LOG_ONEHALF -0.69314718055994529 - -/** Adjust the global cell scale factor based on <b>options</b> */ void -cell_ewma_set_scale_factor(const or_options_t *options, - const 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, -1, INT32_MAX)) >= 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 %f 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) +update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction, + const char *file, int lineno) { + channel_t *chan = NULL; + or_circuit_t *or_circ = NULL; + circuitmux_t *cmux = NULL; - 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 linked. */ -void -make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn) -{ - circuit_t **nextp = next_circ_on_conn_p(circ, conn); - circuit_t **prevp = prev_circ_on_conn_p(circ, conn); - - if (*nextp && *prevp) { - /* Already active. */ - return; - } - - assert_active_circuits_ok_paranoid(conn); - - if (! conn->active_circuits) { - conn->active_circuits = circ; - *prevp = *nextp = circ; - } else { - circuit_t *head = conn->active_circuits; - circuit_t *old_tail = *prev_circ_on_conn_p(head, conn); - *next_circ_on_conn_p(old_tail, conn) = circ; - *nextp = head; - *prev_circ_on_conn_p(head, conn) = circ; - *prevp = old_tail; - } + tor_assert(circ); - if (circ->n_conn == conn) { - add_cell_ewma_to_conn(conn, &circ->n_cell_ewma); + /* Okay, get the channel */ + if (direction == CELL_DIRECTION_OUT) { + chan = circ->n_chan; } 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); + or_circ = TO_OR_CIRCUIT(circ); + chan = or_circ->p_chan; } - assert_active_circuits_ok_paranoid(conn); -} + tor_assert(chan); + tor_assert(chan->cmux); -/** 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) -{ - circuit_t **nextp = next_circ_on_conn_p(circ, conn); - circuit_t **prevp = prev_circ_on_conn_p(circ, conn); - circuit_t *next = *nextp, *prev = *prevp; + /* Now get the cmux */ + cmux = chan->cmux; - if (!next && !prev) { - /* Already inactive. */ + /* Cmux sanity check */ + if (! circuitmux_is_circuit_attached(cmux, circ)) { + log_warn(LD_BUG, "called on non-attachd circuit from %s:%d", + file, lineno); return; } + tor_assert(circuitmux_attached_circuit_direction(cmux, circ) == direction); - assert_active_circuits_ok_paranoid(conn); + assert_cmux_ok_paranoid(chan); - tor_assert(next && prev); - tor_assert(*prev_circ_on_conn_p(next, conn) == circ); - tor_assert(*next_circ_on_conn_p(prev, conn) == circ); - - if (next == circ) { - conn->active_circuits = NULL; - } else { - *prev_circ_on_conn_p(next, conn) = prev; - *next_circ_on_conn_p(prev, conn) = next; - if (conn->active_circuits == circ) - conn->active_circuits = next; - } - *prevp = *nextp = NULL; - - if (circ->n_conn == conn) { - remove_cell_ewma_from_conn(conn, &circ->n_cell_ewma); + /* Update the number of cells we have for the circuit mux */ + if (direction == CELL_DIRECTION_OUT) { + circuitmux_set_num_cells(cmux, circ, circ->n_chan_cells.n); } 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); + circuitmux_set_num_cells(cmux, circ, or_circ->p_chan_cells.n); } - assert_active_circuits_ok_paranoid(conn); + assert_cmux_ok_paranoid(chan); } -/** Remove all circuits from the list of circuits with pending cells on - * <b>conn</b>. */ +/** Remove all circuits from the cmux on <b>chan</b>. */ void -connection_or_unlink_all_active_circs(or_connection_t *orconn) +channel_unlink_all_circuits(channel_t *chan) { - circuit_t *head = orconn->active_circuits; - circuit_t *cur = head; - if (! head) - return; - do { - circuit_t *next = *next_circ_on_conn_p(cur, orconn); - *prev_circ_on_conn_p(cur, orconn) = NULL; - *next_circ_on_conn_p(cur, orconn) = NULL; - 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); + tor_assert(chan); + tor_assert(chan->cmux); + + circuitmux_detach_all_circuits(chan->cmux); + chan->num_n_circuits = 0; + chan->num_p_circuits = 0; } /** 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>, + * every edge connection that is using <b>circ</b> to write to <b>chan</b>, * and start or stop reading as appropriate. * * If <b>stream_id</b> is nonzero, block only the edge connection whose @@ -2370,17 +2274,17 @@ connection_or_unlink_all_active_circs(or_connection_t *orconn) * Returns the number of streams whose status we changed. */ static int -set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn, +set_streams_blocked_on_circ(circuit_t *circ, channel_t *chan, 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 (circ->n_chan == chan) { + circ->streams_blocked_on_n_chan = block; if (CIRCUIT_IS_ORIGIN(circ)) edge = TO_ORIGIN_CIRCUIT(circ)->p_streams; } else { - circ->streams_blocked_on_p_conn = block; + circ->streams_blocked_on_p_chan = block; tor_assert(!CIRCUIT_IS_ORIGIN(circ)); edge = TO_OR_CIRCUIT(circ)->n_streams; } @@ -2415,147 +2319,111 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn, } /** 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 them to - * <b>conn</b>->outbuf. Return the number of cells written. Advance + * queue of the first active circuit on <b>chan</b>, and write them to + * <b>chan</b>->outbuf. Return the number of cells written. Advance * the active circuit pointer to the next active circuit in the ring. */ int -connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max, - time_t now) +channel_flush_from_first_active_circuit(channel_t *chan, int max) { - int n_flushed; + circuitmux_t *cmux = NULL; + int n_flushed = 0; cell_queue_t *queue; circuit_t *circ; + or_circuit_t *or_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); + packed_cell_t *cell; + + /* Get the cmux */ + tor_assert(chan); + tor_assert(chan->cmux); + cmux = chan->cmux; + + /* Main loop: pick a circuit, send a cell, update the cmux */ + while (n_flushed < max) { + circ = circuitmux_get_first_active_circuit(cmux); + /* If it returns NULL, no cells left to send */ + if (!circ) break; + assert_cmux_ok_paranoid(chan); + + if (circ->n_chan == chan) { + queue = &circ->n_chan_cells; + streams_blocked = circ->streams_blocked_on_n_chan; + } else { + or_circ = TO_OR_CIRCUIT(circ); + tor_assert(or_circ->p_chan == chan); + queue = &TO_OR_CIRCUIT(circ)->p_chan_cells; + streams_blocked = circ->streams_blocked_on_p_chan; } - ewma_increment = pow(ewma_scale_factor, -fractional_tick); + /* Circuitmux told us this was active, so it should have cells */ + tor_assert(queue->n > 0); - 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; - } else { - queue = &TO_OR_CIRCUIT(circ)->p_conn_cells; - streams_blocked = circ->streams_blocked_on_p_conn; - } - tor_assert(*next_circ_on_conn_p(circ,conn)); - - for (n_flushed = 0; n_flushed < max && queue->head; ) { - packed_cell_t *cell = cell_queue_pop(queue); - tor_assert(*next_circ_on_conn_p(circ,conn)); + /* + * Get just one cell here; once we've sent it, that can change the circuit + * selection, so we have to loop around for another even if this circuit + * has more than one. + */ + cell = cell_queue_pop(queue); /* Calculate the exact time that this cell has spent in the queue. */ if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) { + uint32_t msec_waiting; struct timeval tvnow; - uint32_t flushed; - uint32_t cell_waiting_time; - insertion_time_queue_t *it_queue = queue->insertion_times; + or_circ = TO_OR_CIRCUIT(circ); tor_gettimeofday_cached(&tvnow); - flushed = (uint32_t)((tvnow.tv_sec % SECONDS_IN_A_DAY) * 100L + - (uint32_t)tvnow.tv_usec / (uint32_t)10000L); - if (!it_queue || !it_queue->first) { - log_info(LD_GENERAL, "Cannot determine insertion time of cell. " - "Looks like the CellStatistics option was " - "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++; - } + msec_waiting = ((uint32_t)tv_to_msec(&tvnow)) - cell->inserted_time; + + or_circ->total_cell_waiting_time += msec_waiting; + or_circ->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, + if (queue->n == 0 && chan->dirreq_id) + geoip_change_dirreq_state(chan->dirreq_id, DIRREQ_TUNNELED, DIRREQ_CIRC_QUEUE_FLUSHED); - connection_write_to_buf(cell->body, CELL_NETWORK_SIZE, TO_CONN(conn)); + /* Now send the cell */ + channel_write_packed_cell(chan, cell); + cell = NULL; - packed_cell_free_unchecked(cell); + /* + * Don't packed_cell_free_unchecked(cell) here because the channel will + * do so when it gets out of the channel queue (probably already did, in + * which case that was an immediate double-free bug). + */ + + /* Update the counter */ ++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 (!ewma_enabled && 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: - * circuit_make_inactive_on_conn() already advanced conn->active_circuits - * for us. - */ - assert_active_circuits_ok_paranoid(conn); - goto done; - } - } - tor_assert(*next_circ_on_conn_p(circ,conn)); - assert_active_circuits_ok_paranoid(conn); - conn->active_circuits = *next_circ_on_conn_p(circ, conn); - /* 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, 0); /* unblock streams */ + /* + * Now update the cmux; tell it we've just sent a cell, and how many + * we have left. + */ + circuitmux_notify_xmit_cells(cmux, circ, 1); + circuitmux_set_num_cells(cmux, circ, queue->n); + if (queue->n == 0) + log_debug(LD_GENERAL, "Made a circuit inactive."); + + /* 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, chan, 0, 0); /* unblock streams */ - /* 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); + /* If n_flushed < max still, loop around and pick another circuit */ } - done: - if (n_flushed) - conn->timestamp_last_added_nonpadding = now; + + /* Okay, we're done sending now */ + assert_cmux_ok_paranoid(chan); + return n_flushed; } -/** Add <b>cell</b> to the queue of <b>circ</b> writing to <b>orconn</b> +/** Add <b>cell</b> to the queue of <b>circ</b> writing to <b>chan</b> * transmitting in <b>direction</b>. */ void -append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, +append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan, cell_t *cell, cell_direction_t direction, streamid_t fromstream) { @@ -2567,12 +2435,12 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, return; if (direction == CELL_DIRECTION_OUT) { - queue = &circ->n_conn_cells; - streams_blocked = circ->streams_blocked_on_n_conn; + queue = &circ->n_chan_cells; + streams_blocked = circ->streams_blocked_on_n_chan; } else { orcirc = TO_OR_CIRCUIT(circ); - queue = &orcirc->p_conn_cells; - streams_blocked = circ->streams_blocked_on_p_conn; + queue = &orcirc->p_chan_cells; + streams_blocked = circ->streams_blocked_on_p_chan; } /* @@ -2580,18 +2448,23 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, */ #if 0 /* Are we a middle circuit about to exceed ORCIRC_MAX_MIDDLE_CELLS? */ - if ((circ->n_conn != NULL) && CIRCUIT_IS_ORCIRC(circ)) { + if ((circ->n_chan != NULL) && CIRCUIT_IS_ORCIRC(circ)) { orcirc = TO_OR_CIRCUIT(circ); - if (orcirc->p_conn) { + if (orcirc->p_chan) { if (queue->n + 1 >= ORCIRC_MAX_MIDDLE_CELLS) { /* Queueing this cell would put queue over the cap */ log_warn(LD_CIRC, "Got a cell exceeding the cap of %u in the %s direction " - "on middle circ ID %u; killing the circuit.", + "on middle circ ID %u on chan ID " U64_FORMAT + "; killing the circuit.", ORCIRC_MAX_MIDDLE_CELLS, (direction == CELL_DIRECTION_OUT) ? "n" : "p", (direction == CELL_DIRECTION_OUT) ? - circ->n_circ_id : orcirc->p_circ_id); + circ->n_circ_id : orcirc->p_circ_id, + U64_PRINTF_ARG( + (direction == CELL_DIRECTION_OUT) ? + circ->n_chan->global_identifier : + orcirc->p_chan->global_identifier)); circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); return; } @@ -2599,7 +2472,7 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, } #endif - cell_queue_append_packed_copy(queue, cell); + cell_queue_append_packed_copy(queue, cell, chan->wide_circ_ids); if (PREDICT_UNLIKELY(cell_queues_check_size())) { /* We ran the OOM handler */ @@ -2610,27 +2483,27 @@ 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, 0); /* block streams */ + set_streams_blocked_on_circ(circ, chan, 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); + set_streams_blocked_on_circ(circ, chan, 1, fromstream); } + update_circuit_on_cmux(circ, direction); if (queue->n == 1) { - /* This was the first cell added to the queue. We need to make this + /* This was the first cell added to the queue. We just made this * circuit active. */ log_debug(LD_GENERAL, "Made a circuit active."); - make_circuit_active_on_conn(circ, orconn); } - if (! connection_get_outbuf_len(TO_CONN(orconn))) { + if (!channel_has_queued_writes(chan)) { /* There is no data at all waiting to be sent on the outbuf. Add a * cell, so that we can notice when it gets flushed, flushed_some can * get called, and we can start putting more data onto the buffer then. */ log_debug(LD_GENERAL, "Primed a buffer."); - connection_or_flush_from_first_active_circuit(orconn, 1, approx_time()); + channel_flush_from_first_active_circuit(chan, 1); } } @@ -2694,58 +2567,40 @@ 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>. */ +/** Remove all the cells queued on <b>circ</b> for <b>chan</b>. */ void -circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn) +circuit_clear_cell_queue(circuit_t *circ, channel_t *chan) { cell_queue_t *queue; - if (circ->n_conn == orconn) { - queue = &circ->n_conn_cells; + cell_direction_t direction; + + if (circ->n_chan == chan) { + queue = &circ->n_chan_cells; + direction = CELL_DIRECTION_OUT; } else { or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); - tor_assert(orcirc->p_conn == orconn); - queue = &orcirc->p_conn_cells; + tor_assert(orcirc->p_chan == chan); + queue = &orcirc->p_chan_cells; + direction = CELL_DIRECTION_IN; } - if (queue->n) - make_circuit_inactive_on_conn(circ,orconn); - + /* Clear the queue */ cell_queue_clear(queue); + + /* Update the cell counter in the cmux */ + if (chan->cmux && circuitmux_is_circuit_attached(chan->cmux, circ)) + update_circuit_on_cmux(circ, direction); } -/** Fail with an assert if the active circuits ring on <b>orconn</b> is - * corrupt. */ +/** Fail with an assert if the circuit mux on chan is corrupt + */ void -assert_active_circuits_ok(or_connection_t *orconn) +assert_circuit_mux_okay(channel_t *chan) { - 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)); + tor_assert(chan); + tor_assert(chan->cmux); + + circuitmux_assert_okay(chan->cmux); } /** Return 1 if we shouldn't restart reading on this circuit, even if @@ -2755,9 +2610,9 @@ static int circuit_queue_streams_are_blocked(circuit_t *circ) { if (CIRCUIT_IS_ORIGIN(circ)) { - return circ->streams_blocked_on_n_conn; + return circ->streams_blocked_on_n_chan; } else { - return circ->streams_blocked_on_p_conn; + return circ->streams_blocked_on_p_chan; } } diff --git a/src/or/relay.h b/src/or/relay.h index c55813b33c..1fef10a7da 100644 --- a/src/or/relay.h +++ b/src/or/relay.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for relay.c. **/ -#ifndef _TOR_RELAY_H -#define _TOR_RELAY_H +#ifndef TOR_RELAY_H +#define TOR_RELAY_H extern uint64_t stats_n_relay_cells_relayed; extern uint64_t stats_n_relay_cells_delivered; @@ -20,9 +20,15 @@ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, 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, +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); + size_t payload_len, crypt_path_t *cpath_layer, + const char *filename, int lineno); +#define relay_send_command_from_edge(stream_id, circ, relay_command, payload, \ + payload_len, cpath_layer) \ + relay_send_command_from_edge_((stream_id), (circ), (relay_command), \ + (payload), (payload_len), (cpath_layer), \ + __FILE__, __LINE__) int connection_edge_send_command(edge_connection_t *fromconn, uint8_t relay_command, const char *payload, size_t payload_len); @@ -42,32 +48,38 @@ void clean_cell_pool(void); void dump_cell_pool_usage(int severity); size_t packed_cell_mem_cost(void); +/* For channeltls.c */ +void packed_cell_free(packed_cell_t *cell); + 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 cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell, + int wide_circ_ids); -void append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, +void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan, 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); +void channel_unlink_all_circuits(channel_t *chan); +int channel_flush_from_first_active_circuit(channel_t *chan, int max); +void assert_circuit_mux_okay(channel_t *chan); +void update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction, + const char *file, int lineno); +#define update_circuit_on_cmux(circ, direction) \ + update_circuit_on_cmux_((circ), (direction), SHORT_FILE__, __LINE__) 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(const or_options_t *options, - const networkstatus_t *consensus); -void circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn); +void circuit_clear_cell_queue(circuit_t *circ, channel_t *chan); + +void stream_choice_seed_weak_rng(void); #ifdef RELAY_PRIVATE int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, crypt_path_t **layer_hint, char *recognized); +int connected_cell_parse(const relay_header_t *rh, const cell_t *cell, + tor_addr_t *addr_out, int *ttl_out); #endif #endif diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 3a0cd1a666..bb4bd9bfd4 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -16,6 +16,7 @@ #include "connection_edge.h" #include "directory.h" #include "main.h" +#include "networkstatus.h" #include "nodelist.h" #include "relay.h" #include "rendclient.h" @@ -23,6 +24,7 @@ #include "rephist.h" #include "router.h" #include "routerlist.h" +#include "routerset.h" static extend_info_t *rend_client_get_random_intro_impl( const rend_cache_entry_t *rend_query, @@ -43,7 +45,7 @@ rend_client_purge_state(void) void rend_client_introcirc_has_opened(origin_circuit_t *circ) { - tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); + tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); tor_assert(circ->cpath); log_info(LD_REND,"introcirc is open"); @@ -56,7 +58,7 @@ rend_client_introcirc_has_opened(origin_circuit_t *circ) static int rend_client_send_establish_rendezvous(origin_circuit_t *circ) { - tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); + tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); tor_assert(circ->rend_data); log_info(LD_REND, "Sending an ESTABLISH_RENDEZVOUS cell"); @@ -65,6 +67,14 @@ rend_client_send_establish_rendezvous(origin_circuit_t *circ) circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return -1; } + + /* Set timestamp_dirty, because circuit_expire_building expects it, + * and the rend cookie also means we've used the circ. */ + circ->base_.timestamp_dirty = time(NULL); + + /* We've attempted to use this circuit. Probe it if we fail */ + pathbias_count_use_attempt(circ); + if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), RELAY_COMMAND_ESTABLISH_RENDEZVOUS, circ->rend_data->rend_cookie, @@ -99,16 +109,17 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ) circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return -1; } + // XXX: should we not re-extend if hs_circ_has_timed_out? if (circ->remaining_relay_early_cells) { log_info(LD_REND, - "Re-extending circ %d, this time to %s.", - circ->_base.n_circ_id, + "Re-extending circ %u, this time to %s.", + (unsigned)circ->base_.n_circ_id, safe_str_client(extend_info_describe(extend_info))); result = circuit_extend_to_new_exit(circ, extend_info); } else { log_info(LD_REND, - "Closing intro circ %d (out of RELAY_EARLY cells).", - circ->_base.n_circ_id); + "Closing intro circ %u (out of RELAY_EARLY cells).", + (unsigned)circ->base_.n_circ_id); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); /* connection_ap_handshake_attach_circuit will launch a new intro circ. */ result = 0; @@ -117,6 +128,16 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ) return result; } +/** Return true iff we should send timestamps in our INTRODUCE1 cells */ +static int +rend_client_should_send_timestamp(void) +{ + if (get_options()->Support022HiddenServices >= 0) + return get_options()->Support022HiddenServices; + + return networkstatus_get_param(NULL, "Support022HiddenServices", 1, 0, 1); +} + /** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell * down introcirc if possible. */ @@ -132,9 +153,10 @@ rend_client_send_introduction(origin_circuit_t *introcirc, crypt_path_t *cpath; off_t dh_offset; crypto_pk_t *intro_key = NULL; + int status = 0; - tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); - tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY); + tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); + tor_assert(rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY); tor_assert(introcirc->rend_data); tor_assert(rendcirc->rend_data); tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address, @@ -161,7 +183,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc, } } - return -1; + status = -1; + goto cleanup; } /* first 20 bytes of payload are the hash of Bob's pk */ @@ -184,13 +207,16 @@ rend_client_send_introduction(origin_circuit_t *introcirc, smartlist_len(entry->parsed->intro_nodes)); if (rend_client_reextend_intro_circuit(introcirc)) { + status = -2; goto perm_err; } else { - return -1; + status = -1; + goto cleanup; } } if (crypto_pk_get_digest(intro_key, payload)<0) { log_warn(LD_BUG, "Internal error: couldn't hash public key."); + status = -2; goto perm_err; } @@ -200,12 +226,14 @@ rend_client_send_introduction(origin_circuit_t *introcirc, cpath = rendcirc->build_state->pending_final_cpath = tor_malloc_zero(sizeof(crypt_path_t)); cpath->magic = CRYPT_PATH_MAGIC; - if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) { + if (!(cpath->rend_dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) { log_warn(LD_BUG, "Internal error: couldn't allocate DH."); + status = -2; goto perm_err; } - if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) { + if (crypto_dh_generate_public(cpath->rend_dh_handshake_state)<0) { log_warn(LD_BUG, "Internal error: couldn't generate g^x."); + status = -2; goto perm_err; } } @@ -221,7 +249,14 @@ rend_client_send_introduction(origin_circuit_t *introcirc, REND_DESC_COOKIE_LEN); v3_shift += 2+REND_DESC_COOKIE_LEN; } - set_uint32(tmp+v3_shift+1, htonl((uint32_t)time(NULL))); + if (rend_client_should_send_timestamp()) { + uint32_t now = (uint32_t)time(NULL); + now += 300; + now -= now % 600; + set_uint32(tmp+v3_shift+1, htonl(now)); + } else { + set_uint32(tmp+v3_shift+1, 0); + } v3_shift += 4; } /* if version 2 only write version number */ else if (entry->parsed->protocols & (1<<2)) { @@ -253,9 +288,10 @@ rend_client_send_introduction(origin_circuit_t *introcirc, dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN; } - if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset, + if (crypto_dh_get_public(cpath->rend_dh_handshake_state, tmp+dh_offset, DH_KEY_LEN)<0) { log_warn(LD_BUG, "Internal error: couldn't extract g^x."); + status = -2; goto perm_err; } @@ -269,6 +305,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, PK_PKCS1_OAEP_PADDING, 0); if (r<0) { log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed."); + status = -2; goto perm_err; } @@ -288,7 +325,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc, introcirc->cpath->prev)<0) { /* introcirc is already marked for close. leave rendcirc alone. */ log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell"); - return -2; + status = -2; + goto cleanup; } /* Now, we wait for an ACK or NAK on this circuit. */ @@ -297,14 +335,21 @@ rend_client_send_introduction(origin_circuit_t *introcirc, /* Set timestamp_dirty, because circuit_expire_building expects it * to specify when a circuit entered the _C_INTRODUCE_ACK_WAIT * state. */ - introcirc->_base.timestamp_dirty = time(NULL); + introcirc->base_.timestamp_dirty = time(NULL); + + pathbias_count_use_attempt(introcirc); + + goto cleanup; - return 0; perm_err: - if (!introcirc->_base.marked_for_close) + if (!introcirc->base_.marked_for_close) circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL); circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL); - return -2; + cleanup: + memwipe(payload, 0, sizeof(payload)); + memwipe(tmp, 0, sizeof(tmp)); + + return status; } /** Called when a rendezvous circuit is open; sends a establish @@ -312,7 +357,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, void rend_client_rendcirc_has_opened(origin_circuit_t *circ) { - tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); + tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); log_info(LD_REND,"rendcirc is open"); @@ -322,6 +367,32 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ) } } +/** + * Called to close other intro circuits we launched in parallel + * due to timeout. + */ +static void +rend_client_close_other_intros(const char *onion_address) +{ + circuit_t *c; + /* abort parallel intro circs, if any */ + for (c = circuit_get_global_list_(); c; c = c->next) { + if ((c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING || + c->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) && + !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { + origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c); + if (oc->rend_data && + !rend_cmp_service_ids(onion_address, + oc->rend_data->onion_address)) { + log_info(LD_REND|LD_CIRC, "Closing introduction circuit %d that we " + "built in parallel (Purpose %d).", oc->global_identifier, + c->purpose); + circuit_mark_for_close(c, END_CIRC_REASON_TIMEOUT); + } + } + } +} + /** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell. */ int @@ -331,10 +402,10 @@ rend_client_introduction_acked(origin_circuit_t *circ, origin_circuit_t *rendcirc; (void) request; // XXXX Use this. - if (circ->_base.purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { log_warn(LD_PROTOCOL, - "Received REND_INTRODUCE_ACK on unexpected circuit %d.", - circ->_base.n_circ_id); + "Received REND_INTRODUCE_ACK on unexpected circuit %u.", + (unsigned)circ->base_.n_circ_id); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); return -1; } @@ -345,6 +416,10 @@ rend_client_introduction_acked(origin_circuit_t *circ, #endif tor_assert(circ->rend_data); + /* For path bias: This circuit was used successfully. Valid + * nacks and acks count. */ + pathbias_mark_use_success(circ); + if (request_len == 0) { /* It's an ACK; the introduction point relayed our introduction request. */ /* Locate the rend circ which is waiting to hear about this ack, @@ -361,7 +436,7 @@ rend_client_introduction_acked(origin_circuit_t *circ, /* Set timestamp_dirty, because circuit_expire_building expects * it to specify when a circuit entered the * _C_REND_READY_INTRO_ACKED state. */ - rendcirc->_base.timestamp_dirty = time(NULL); + rendcirc->base_.timestamp_dirty = time(NULL); } else { log_info(LD_REND,"...Found no rend circ. Dropping on the floor."); } @@ -369,6 +444,9 @@ rend_client_introduction_acked(origin_circuit_t *circ, circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_INTRODUCE_ACKED); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); + + /* close any other intros launched in parallel */ + rend_client_close_other_intros(circ->rend_data->onion_address); } else { /* It's a NAK; the introduction point didn't relay our request. */ circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_INTRODUCING); @@ -525,7 +603,7 @@ rend_client_purge_last_hid_serv_requests(void) if (old_last_hid_serv_requests != NULL) { log_info(LD_REND, "Purging client last-HS-desc-request-time table"); - strmap_free(old_last_hid_serv_requests, _tor_free); + strmap_free(old_last_hid_serv_requests, tor_free_); } } @@ -602,7 +680,8 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) directory_initiate_command_routerstatus_rend(hs_dir, DIR_PURPOSE_FETCH_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, - !tor2web_mode, desc_id_base32, + tor2web_mode?DIRIND_ONEHOP:DIRIND_ANONYMOUS, + desc_id_base32, NULL, 0, 0, rend_query); log_info(LD_REND, "Sending fetch request for v2 descriptor for " @@ -659,10 +738,17 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query) time(NULL), chosen_replica) < 0) { log_warn(LD_REND, "Internal error: Computing v2 rendezvous " "descriptor ID did not succeed."); - return; + /* + * Hmm, can this write anything to descriptor_id and still fail? + * Let's clear it just to be safe. + * + * From here on, any returns should goto done which clears + * descriptor_id so we don't leave key-derived material on the stack. + */ + goto done; } if (directory_get_from_hs_dir(descriptor_id, rend_query) != 0) - return; /* either success or failure, but we're done */ + goto done; /* either success or failure, but we're done */ } /* If we come here, there are no hidden service directories left. */ log_info(LD_REND, "Could not pick one of the responsible hidden " @@ -670,6 +756,10 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query) "we already tried them all unsuccessfully."); /* Close pending connections. */ rend_client_desc_trynow(rend_query->onion_address); + + done: + memwipe(descriptor_id, 0, sizeof(descriptor_id)); + return; } @@ -818,7 +908,7 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, (void) request; (void) request_len; /* we just got an ack for our establish-rendezvous. switch purposes. */ - if (circ->_base.purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) { log_warn(LD_PROTOCOL,"Got a rendezvous ack when we weren't expecting one. " "Closing circ."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); @@ -829,7 +919,14 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_REND_READY); /* Set timestamp_dirty, because circuit_expire_building expects it * to specify when a circuit entered the _C_REND_READY state. */ - circ->_base.timestamp_dirty = time(NULL); + circ->base_.timestamp_dirty = time(NULL); + + /* From a path bias point of view, this circuit is now successfully used. + * Waiting any longer opens us up to attacks from Bob. He could induce + * Alice to attempt to connect to his hidden service and never reply + * to her rend requests */ + pathbias_mark_use_success(circ); + /* XXXX This is a pretty brute-force approach. It'd be better to * attach only the connections that are waiting on this circuit, rather * than trying to attach them all. See comments bug 743. */ @@ -847,8 +944,8 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, crypt_path_t *hop; char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; - if ((circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY && - circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) + if ((circ->base_.purpose != CIRCUIT_PURPOSE_C_REND_READY && + circ->base_.purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) || !circ->build_state->pending_final_cpath) { log_warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not " "expecting it. Closing."); @@ -868,9 +965,9 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, tor_assert(circ->build_state); tor_assert(circ->build_state->pending_final_cpath); hop = circ->build_state->pending_final_cpath; - tor_assert(hop->dh_handshake_state); + tor_assert(hop->rend_dh_handshake_state); if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, - hop->dh_handshake_state, (char*)request, + hop->rend_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."); @@ -886,8 +983,8 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, goto err; } - crypto_dh_free(hop->dh_handshake_state); - hop->dh_handshake_state = NULL; + crypto_dh_free(hop->rend_dh_handshake_state); + hop->rend_dh_handshake_state = NULL; /* All is well. Extend the circuit. */ circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_REND_JOINED); @@ -1172,11 +1269,11 @@ rend_parse_service_authorization(const or_options_t *options, strmap_t *parsed = strmap_new(); smartlist_t *sl = smartlist_new(); rend_service_authorization_t *auth = NULL; + char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2]; + char descriptor_cookie_base64ext[REND_DESC_COOKIE_LEN_BASE64+2+1]; for (line = options->HidServAuth; line; line = line->next) { char *onion_address, *descriptor_cookie; - char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2]; - char descriptor_cookie_base64ext[REND_DESC_COOKIE_LEN_BASE64+2+1]; int auth_type_val = 0; auth = NULL; SMARTLIST_FOREACH(sl, char *, c, tor_free(c);); @@ -1222,7 +1319,7 @@ rend_parse_service_authorization(const or_options_t *options, descriptor_cookie); goto err; } - auth_type_val = (descriptor_cookie_tmp[16] >> 4) + 1; + auth_type_val = (((uint8_t)descriptor_cookie_tmp[16]) >> 4) + 1; if (auth_type_val < 1 || auth_type_val > 2) { log_warn(LD_CONFIG, "Authorization cookie has unknown authorization " "type encoded."); @@ -1253,6 +1350,8 @@ rend_parse_service_authorization(const or_options_t *options, } else { strmap_free(parsed, rend_service_authorization_strmap_item_free); } + memwipe(descriptor_cookie_tmp, 0, sizeof(descriptor_cookie_tmp)); + memwipe(descriptor_cookie_base64ext, 0, sizeof(descriptor_cookie_base64ext)); return res; } diff --git a/src/or/rendclient.h b/src/or/rendclient.h index 393b556e32..1f731d0ae5 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for rendclient.c. **/ -#ifndef _TOR_RENDCLIENT_H -#define _TOR_RENDCLIENT_H +#ifndef TOR_RENDCLIENT_H +#define TOR_RENDCLIENT_H void rend_client_purge_state(void); diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 76786e0fd1..d1b49411cd 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -439,7 +439,7 @@ rend_intro_point_free(rend_intro_point_t *intro) crypto_pk_free(intro->intro_key); if (intro->accepted_intro_rsa_parts != NULL) { - digestmap_free(intro->accepted_intro_rsa_parts, _tor_free); + replaycache_free(intro->accepted_intro_rsa_parts); } tor_free(intro); @@ -800,7 +800,7 @@ rend_cache_entry_free(rend_cache_entry_t *e) /** Helper: deallocate a rend_cache_entry_t. (Used with strmap_free(), which * requires a function pointer whose argument is void*). */ static void -_rend_cache_entry_free(void *p) +rend_cache_entry_free_(void *p) { rend_cache_entry_free(p); } @@ -809,8 +809,8 @@ _rend_cache_entry_free(void *p) void rend_cache_free_all(void) { - strmap_free(rend_cache, _rend_cache_entry_free); - 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; } @@ -844,7 +844,7 @@ rend_cache_purge(void) { if (rend_cache) { log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache"); - strmap_free(rend_cache, _rend_cache_entry_free); + strmap_free(rend_cache, rend_cache_entry_free_); } rend_cache = strmap_new(); } @@ -954,7 +954,7 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e) return 1; } -/** <b>query</b> is a base-32'ed service id. If it's malformed, return -1. +/** <b>query</b> is a base32'ed service id. If it's malformed, return -1. * Else look it up. * - If it is found, point *desc to it, and write its length into * *desc_len, and return 1. @@ -1476,13 +1476,6 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, command); } -/** Return the number of entries in our rendezvous descriptor cache. */ -int -rend_cache_size(void) -{ - return strmap_size(rend_cache); -} - /** Allocate and return a new rend_data_t with the same * contents as <b>query</b>. */ rend_data_t * diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h index be6bd13d2c..f476593d2b 100644 --- a/src/or/rendcommon.h +++ b/src/or/rendcommon.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for rendcommon.c. **/ -#ifndef _TOR_RENDCOMMON_H -#define _TOR_RENDCOMMON_H +#ifndef TOR_RENDCOMMON_H +#define TOR_RENDCOMMON_H /** Free all storage associated with <b>data</b> */ static INLINE void @@ -49,7 +49,6 @@ 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, diff --git a/src/or/rendmid.c b/src/or/rendmid.c index bacd0ef93e..1bd11f6dc0 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -32,10 +32,10 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, int reason = END_CIRC_REASON_INTERNAL; log_info(LD_REND, - "Received an ESTABLISH_INTRO request on circuit %d", - circ->p_circ_id); + "Received an ESTABLISH_INTRO request on circuit %u", + (unsigned) circ->p_circ_id); - if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit."); reason = END_CIRC_REASON_TORPROTOCOL; @@ -56,8 +56,8 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, goto err; } - /* Next 20 bytes: Hash of handshake_digest | "INTRODUCE" */ - memcpy(buf, circ->handshake_digest, DIGEST_LEN); + /* Next 20 bytes: Hash of rend_circ_nonce | "INTRODUCE" */ + memcpy(buf, circ->rend_circ_nonce, DIGEST_LEN); memcpy(buf+DIGEST_LEN, "INTRODUCE", 9); if (crypto_digest(expected_digest, buf, DIGEST_LEN+9) < 0) { log_warn(LD_BUG, "Internal error computing digest."); @@ -114,8 +114,8 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, memcpy(circ->rend_token, pk_digest, DIGEST_LEN); log_info(LD_REND, - "Established introduction point on circuit %d for service %s", - circ->p_circ_id, safe_str(serviceid)); + "Established introduction point on circuit %u for service %s", + (unsigned) circ->p_circ_id, safe_str(serviceid)); return 0; truncated: @@ -139,13 +139,13 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, char serviceid[REND_SERVICE_ID_LEN_BASE32+1]; char nak_body[1]; - log_info(LD_REND, "Received an INTRODUCE1 request on circuit %d", - circ->p_circ_id); + log_info(LD_REND, "Received an INTRODUCE1 request on circuit %u", + (unsigned)circ->p_circ_id); - if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_warn(LD_PROTOCOL, - "Rejecting INTRODUCE1 on non-OR or non-edge circuit %d.", - circ->p_circ_id); + "Rejecting INTRODUCE1 on non-OR or non-edge circuit %u.", + (unsigned)circ->p_circ_id); goto err; } @@ -155,9 +155,9 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, */ if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+ DH_KEY_LEN+CIPHER_KEY_LEN+PKCS1_OAEP_PADDING_OVERHEAD)) { - log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %d; " + log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %u; " "responding with nack.", - circ->p_circ_id); + (unsigned)circ->p_circ_id); goto err; } @@ -168,17 +168,17 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, intro_circ = circuit_get_intro_point((char*)request); if (!intro_circ) { log_info(LD_REND, - "No intro circ found for INTRODUCE1 cell (%s) from circuit %d; " + "No intro circ found for INTRODUCE1 cell (%s) from circuit %u; " "responding with nack.", - safe_str(serviceid), circ->p_circ_id); + safe_str(serviceid), (unsigned)circ->p_circ_id); goto err; } log_info(LD_REND, "Sending introduction request for service %s " - "from circ %d to circ %d", - safe_str(serviceid), circ->p_circ_id, - intro_circ->p_circ_id); + "from circ %u to circ %u", + safe_str(serviceid), (unsigned)circ->p_circ_id, + (unsigned)intro_circ->p_circ_id); /* Great. Now we just relay the cell down the circuit. */ if (relay_send_command_from_edge(0, TO_CIRCUIT(intro_circ), @@ -221,10 +221,10 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, char hexid[9]; int reason = END_CIRC_REASON_TORPROTOCOL; - log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %d", - circ->p_circ_id); + log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %u", + (unsigned)circ->p_circ_id); - if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_warn(LD_PROTOCOL, "Tried to establish rendezvous on non-OR or non-edge circuit."); goto err; @@ -256,8 +256,8 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, base16_encode(hexid,9,(char*)request,4); log_info(LD_REND, - "Established rendezvous point on circuit %d for cookie %s", - circ->p_circ_id, hexid); + "Established rendezvous point on circuit %u for cookie %s", + (unsigned)circ->p_circ_id, hexid); return 0; err: @@ -277,18 +277,18 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, char hexid[9]; int reason = END_CIRC_REASON_INTERNAL; - if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) { + if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_info(LD_REND, - "Tried to complete rendezvous on non-OR or non-edge circuit %d.", - circ->p_circ_id); + "Tried to complete rendezvous on non-OR or non-edge circuit %u.", + (unsigned)circ->p_circ_id); reason = END_CIRC_REASON_TORPROTOCOL; goto err; } if (request_len != REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %d.", - (int)request_len, circ->p_circ_id); + "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %u.", + (int)request_len, (unsigned)circ->p_circ_id); reason = END_CIRC_REASON_TORPROTOCOL; goto err; } @@ -296,8 +296,8 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, base16_encode(hexid, sizeof(hexid), (const char*)request, 4); log_info(LD_REND, - "Got request for rendezvous from circuit %d to cookie %s.", - circ->p_circ_id, hexid); + "Got request for rendezvous from circuit %u to cookie %s.", + (unsigned)circ->p_circ_id, hexid); rend_circ = circuit_get_rendezvous((char*)request); if (!rend_circ) { @@ -314,15 +314,15 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, (char*)(request+REND_COOKIE_LEN), request_len-REND_COOKIE_LEN, NULL)) { log_warn(LD_GENERAL, - "Unable to send RENDEZVOUS2 cell to client on circuit %d.", - rend_circ->p_circ_id); + "Unable to send RENDEZVOUS2 cell to client on circuit %u.", + (unsigned)rend_circ->p_circ_id); goto err; } /* Join the circuits. */ log_info(LD_REND, - "Completing rendezvous: circuit %d joins circuit %d (cookie %s)", - circ->p_circ_id, rend_circ->p_circ_id, hexid); + "Completing rendezvous: circuit %u joins circuit %u (cookie %s)", + (unsigned)circ->p_circ_id, (unsigned)rend_circ->p_circ_id, hexid); circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_ESTABLISHED); circuit_change_purpose(TO_CIRCUIT(rend_circ), diff --git a/src/or/rendmid.h b/src/or/rendmid.h index 0af6436dea..310276ac96 100644 --- a/src/or/rendmid.h +++ b/src/or/rendmid.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for rendmid.c. **/ -#ifndef _TOR_RENDMID_H -#define _TOR_RENDMID_H +#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); diff --git a/src/or/rendservice.c b/src/or/rendservice.c index d235f089fc..8a4a11e475 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -7,6 +7,8 @@ * \brief The hidden-service side of rendezvous functionality. **/ +#define RENDSERVICE_PRIVATE + #include "or.h" #include "circuitbuild.h" #include "circuitlist.h" @@ -21,16 +23,42 @@ #include "router.h" #include "relay.h" #include "rephist.h" +#include "replaycache.h" #include "routerlist.h" #include "routerparse.h" +#include "routerset.h" static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest); static rend_intro_point_t *find_intro_point(origin_circuit_t *circ); +static extend_info_t *find_rp_for_intro( + const rend_intro_cell_t *intro, + uint8_t *need_free_out, char **err_msg_out); + static int intro_point_accepted_intro_count(rend_intro_point_t *intro); static int intro_point_should_expire_now(rend_intro_point_t *intro, time_t now); +struct rend_service_t; +static int rend_service_load_keys(struct rend_service_t *s); +static int rend_service_load_auth_keys(struct rend_service_t *s, + const char *hfname); + +static ssize_t rend_service_parse_intro_for_v0_or_v1( + rend_intro_cell_t *intro, + const uint8_t *buf, + size_t plaintext_len, + char **err_msg_out); +static ssize_t rend_service_parse_intro_for_v2( + rend_intro_cell_t *intro, + const uint8_t *buf, + size_t plaintext_len, + char **err_msg_out); +static ssize_t rend_service_parse_intro_for_v3( + rend_intro_cell_t *intro, + const uint8_t *buf, + size_t plaintext_len, + char **err_msg_out); /** Represents the mapping from a virtual port of a rendezvous service to * a real port on some IP. @@ -60,7 +88,7 @@ typedef struct rend_service_port_config_t { /** How many seconds should we wait for new HS descriptors to reach * our clients before we close an expiring intro point? */ -#define INTRO_POINT_EXPIRATION_GRACE_PERIOD 5*60 +#define INTRO_POINT_EXPIRATION_GRACE_PERIOD (5*60) /** Represents a single hidden service running at this OP. */ typedef struct rend_service_t { @@ -91,16 +119,12 @@ typedef struct rend_service_t { * up-to-date. */ time_t next_upload_time; /**< Scheduled next hidden service descriptor * upload time. */ - /** Map from digests of Diffie-Hellman values INTRODUCE2 to time_t - * of when they were received. Clients may send INTRODUCE1 cells - * for the same rendezvous point through two or more different - * introduction points; when they do, this digestmap keeps us from - * launching multiple simultaneous attempts to connect to the same - * rend point. */ - digestmap_t *accepted_intro_dh_parts; - /** Time at which we last removed expired values from - * accepted_intro_dh_parts. */ - time_t last_cleaned_accepted_intro_dh_parts; + /** Replay cache for Diffie-Hellman values of INTRODUCE2 cells, to + * detect repeats. Clients may send INTRODUCE1 cells for the same + * rendezvous point through two or more different introduction points; + * when they do, this keeps us from launching multiple simultaneous attempts + * to connect to the same rend point. */ + replaycache_t *accepted_intro_dh_parts; } rend_service_t; /** A list of rend_service_t's for services run on this OP. @@ -135,7 +159,9 @@ rend_authorized_client_free(rend_authorized_client_t *client) return; if (client->client_key) crypto_pk_free(client->client_key); + tor_strclear(client->client_name); tor_free(client->client_name); + memwipe(client->descriptor_cookie, 0, sizeof(client->descriptor_cookie)); tor_free(client); } @@ -171,7 +197,9 @@ rend_service_free(rend_service_t *service) rend_authorized_client_free(c);); smartlist_free(service->clients); } - digestmap_free(service->accepted_intro_dh_parts, _tor_free); + if (service->accepted_intro_dh_parts) { + replaycache_free(service->accepted_intro_dh_parts); + } tor_free(service); } @@ -244,8 +272,8 @@ rend_add_service(rend_service_t *service) service->directory); for (i = 0; i < smartlist_len(service->ports); ++i) { p = smartlist_get(service->ports, i); - log_debug(LD_REND,"Service maps port %d to %s:%d", - p->virtual_port, fmt_addr(&p->real_addr), p->real_port); + log_debug(LD_REND,"Service maps port %d to %s", + p->virtual_port, fmt_addrport(&p->real_addr, p->real_port)); } } } @@ -515,7 +543,7 @@ rend_config_services(const or_options_t *options, int validate_only) /* XXXX it would be nicer if we had a nicer abstraction to use here, * so we could just iterate over the list of services to close, but * once again, this isn't critical-path code. */ - for (circ = _circuit_get_global_list(); circ; circ = circ->next) { + for (circ = circuit_get_global_list_(); circ; circ = circ->next) { if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN && (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -565,6 +593,7 @@ rend_service_update_descriptor(rend_service_t *service) 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->timestamp -= d->timestamp % 3600; /* Round down to nearest hour */ d->intro_nodes = smartlist_new(); /* Support intro protocols 2 and 3. */ d->protocols = (1 << 2) + (1 << 3); @@ -582,7 +611,7 @@ rend_service_update_descriptor(rend_service_t *service) } circ = find_intro_circuit(intro_svc, service->pk_digest); - if (!circ || circ->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) { + if (!circ || circ->base_.purpose != CIRCUIT_PURPOSE_S_INTRO) { /* This intro point's circuit isn't finished yet. Don't list it. */ continue; } @@ -609,231 +638,274 @@ rend_service_update_descriptor(rend_service_t *service) /** Load and/or generate private keys for all hidden services, possibly * including keys for client authorization. Return 0 on success, -1 on - * failure. - */ + * failure. */ int -rend_service_load_keys(void) +rend_service_load_all_keys(void) { - int r = 0; - char fname[512]; - char buf[1500]; - SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) { if (s->private_key) continue; log_info(LD_REND, "Loading hidden-service keys from \"%s\"", s->directory); - /* Check/create directory */ - if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0) + if (rend_service_load_keys(s) < 0) return -1; + } SMARTLIST_FOREACH_END(s); + + return 0; +} + +/** Load and/or generate private keys for the hidden service <b>s</b>, + * possibly including keys for client authorization. Return 0 on success, -1 + * on failure. */ +static int +rend_service_load_keys(rend_service_t *s) +{ + char fname[512]; + char buf[128]; + + /* Check/create directory */ + if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0) + return -1; + + /* Load key */ + if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) || + strlcat(fname,PATH_SEPARATOR"private_key",sizeof(fname)) + >= sizeof(fname)) { + log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\".", + s->directory); + return -1; + } + s->private_key = init_key_from_file(fname, 1, LOG_ERR); + if (!s->private_key) + return -1; + + /* Create service file */ + if (rend_get_service_id(s->private_key, s->service_id)<0) { + log_warn(LD_BUG, "Internal error: couldn't encode service ID."); + return -1; + } + if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) { + log_warn(LD_BUG, "Couldn't compute hash of public key."); + return -1; + } + if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) || + strlcat(fname,PATH_SEPARATOR"hostname",sizeof(fname)) + >= sizeof(fname)) { + log_warn(LD_CONFIG, "Directory name too long to store hostname file:" + " \"%s\".", s->directory); + return -1; + } + + tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id); + if (write_str_to_file(fname,buf,0)<0) { + log_warn(LD_CONFIG, "Could not write onion address to hostname file."); + memwipe(buf, 0, sizeof(buf)); + return -1; + } + memwipe(buf, 0, sizeof(buf)); - /* Load key */ - if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) || - strlcat(fname,PATH_SEPARATOR"private_key",sizeof(fname)) - >= sizeof(fname)) { - log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\".", - s->directory); + /* If client authorization is configured, load or generate keys. */ + if (s->auth_type != REND_NO_AUTH) { + if (rend_service_load_auth_keys(s, fname) < 0) return -1; + } + + return 0; +} + +/** Load and/or generate client authorization keys for the hidden service + * <b>s</b>, which stores its hostname in <b>hfname</b>. Return 0 on success, + * -1 on failure. */ +static int +rend_service_load_auth_keys(rend_service_t *s, const char *hfname) +{ + int r = 0; + char cfname[512]; + char *client_keys_str = NULL; + strmap_t *parsed_clients = strmap_new(); + FILE *cfile, *hfile; + open_file_t *open_cfile = NULL, *open_hfile = NULL; + char extended_desc_cookie[REND_DESC_COOKIE_LEN+1]; + char desc_cook_out[3*REND_DESC_COOKIE_LEN_BASE64+1]; + char service_id[16+1]; + char buf[1500]; + + /* Load client keys and descriptor cookies, if available. */ + if (tor_snprintf(cfname, sizeof(cfname), "%s"PATH_SEPARATOR"client_keys", + s->directory)<0) { + log_warn(LD_CONFIG, "Directory name too long to store client keys " + "file: \"%s\".", s->directory); + goto err; + } + client_keys_str = read_file_to_str(cfname, RFTS_IGNORE_MISSING, NULL); + if (client_keys_str) { + if (rend_parse_client_keys(parsed_clients, client_keys_str) < 0) { + log_warn(LD_CONFIG, "Previously stored client_keys file could not " + "be parsed."); + goto err; + } else { + log_info(LD_CONFIG, "Parsed %d previously stored client entries.", + strmap_size(parsed_clients)); } - s->private_key = init_key_from_file(fname, 1, LOG_ERR); - if (!s->private_key) - return -1; + } - /* Create service file */ - if (rend_get_service_id(s->private_key, s->service_id)<0) { - log_warn(LD_BUG, "Internal error: couldn't encode service ID."); - return -1; + /* Prepare client_keys and hostname files. */ + if (!(cfile = start_writing_to_stdio_file(cfname, + OPEN_FLAGS_REPLACE | O_TEXT, + 0600, &open_cfile))) { + log_warn(LD_CONFIG, "Could not open client_keys file %s", + escaped(cfname)); + goto err; + } + + if (!(hfile = start_writing_to_stdio_file(hfname, + OPEN_FLAGS_REPLACE | O_TEXT, + 0600, &open_hfile))) { + log_warn(LD_CONFIG, "Could not open hostname file %s", escaped(hfname)); + goto err; + } + + /* Either use loaded keys for configured clients or generate new + * ones if a client is new. */ + SMARTLIST_FOREACH_BEGIN(s->clients, rend_authorized_client_t *, client) { + rend_authorized_client_t *parsed = + strmap_get(parsed_clients, client->client_name); + int written; + size_t len; + /* Copy descriptor cookie from parsed entry or create new one. */ + if (parsed) { + memcpy(client->descriptor_cookie, parsed->descriptor_cookie, + REND_DESC_COOKIE_LEN); + } else { + crypto_rand(client->descriptor_cookie, REND_DESC_COOKIE_LEN); } - if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) { - log_warn(LD_BUG, "Couldn't compute hash of public key."); - return -1; + if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1, + client->descriptor_cookie, + REND_DESC_COOKIE_LEN) < 0) { + log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); + goto err; } - if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) || - strlcat(fname,PATH_SEPARATOR"hostname",sizeof(fname)) - >= sizeof(fname)) { - log_warn(LD_CONFIG, "Directory name too long to store hostname file:" - " \"%s\".", s->directory); - return -1; + /* Copy client key from parsed entry or create new one if required. */ + if (parsed && parsed->client_key) { + client->client_key = crypto_pk_dup_key(parsed->client_key); + } else if (s->auth_type == REND_STEALTH_AUTH) { + /* Create private key for client. */ + crypto_pk_t *prkey = NULL; + if (!(prkey = crypto_pk_new())) { + log_warn(LD_BUG,"Error constructing client key"); + goto err; + } + if (crypto_pk_generate_key(prkey)) { + log_warn(LD_BUG,"Error generating client key"); + crypto_pk_free(prkey); + goto err; + } + if (crypto_pk_check_key(prkey) <= 0) { + log_warn(LD_BUG,"Generated client key seems invalid"); + crypto_pk_free(prkey); + goto err; + } + client->client_key = prkey; } - tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id); - if (write_str_to_file(fname,buf,0)<0) { - log_warn(LD_CONFIG, "Could not write onion address to hostname file."); - return -1; + /* Add entry to client_keys file. */ + desc_cook_out[strlen(desc_cook_out)-1] = '\0'; /* Remove newline. */ + written = tor_snprintf(buf, sizeof(buf), + "client-name %s\ndescriptor-cookie %s\n", + client->client_name, desc_cook_out); + if (written < 0) { + log_warn(LD_BUG, "Could not write client entry."); + goto err; } - - /* If client authorization is configured, load or generate keys. */ - if (s->auth_type != REND_NO_AUTH) { - char *client_keys_str = NULL; - strmap_t *parsed_clients = strmap_new(); - char cfname[512]; - FILE *cfile, *hfile; - open_file_t *open_cfile = NULL, *open_hfile = NULL; - - /* Load client keys and descriptor cookies, if available. */ - if (tor_snprintf(cfname, sizeof(cfname), "%s"PATH_SEPARATOR"client_keys", - s->directory)<0) { - log_warn(LD_CONFIG, "Directory name too long to store client keys " - "file: \"%s\".", s->directory); + if (client->client_key) { + char *client_key_out = NULL; + if (crypto_pk_write_private_key_to_string(client->client_key, + &client_key_out, &len) != 0) { + log_warn(LD_BUG, "Internal error: " + "crypto_pk_write_private_key_to_string() failed."); goto err; } - client_keys_str = read_file_to_str(cfname, RFTS_IGNORE_MISSING, NULL); - if (client_keys_str) { - if (rend_parse_client_keys(parsed_clients, client_keys_str) < 0) { - log_warn(LD_CONFIG, "Previously stored client_keys file could not " - "be parsed."); - goto err; - } else { - log_info(LD_CONFIG, "Parsed %d previously stored client entries.", - strmap_size(parsed_clients)); - tor_free(client_keys_str); - } - } - - /* Prepare client_keys and hostname files. */ - if (!(cfile = start_writing_to_stdio_file(cfname, - OPEN_FLAGS_REPLACE | O_TEXT, - 0600, &open_cfile))) { - log_warn(LD_CONFIG, "Could not open client_keys file %s", - escaped(cfname)); + if (rend_get_service_id(client->client_key, service_id)<0) { + log_warn(LD_BUG, "Internal error: couldn't encode service ID."); + /* + * len is string length, not buffer length, but last byte is NUL + * anyway. + */ + memwipe(client_key_out, 0, len); + tor_free(client_key_out); goto err; } - if (!(hfile = start_writing_to_stdio_file(fname, - OPEN_FLAGS_REPLACE | O_TEXT, - 0600, &open_hfile))) { - log_warn(LD_CONFIG, "Could not open hostname file %s", escaped(fname)); + written = tor_snprintf(buf + written, sizeof(buf) - written, + "client-key\n%s", client_key_out); + memwipe(client_key_out, 0, len); + tor_free(client_key_out); + if (written < 0) { + log_warn(LD_BUG, "Could not write client entry."); goto err; } + } - /* Either use loaded keys for configured clients or generate new - * ones if a client is new. */ - SMARTLIST_FOREACH_BEGIN(s->clients, rend_authorized_client_t *, client) - { - char desc_cook_out[3*REND_DESC_COOKIE_LEN_BASE64+1]; - char service_id[16+1]; - rend_authorized_client_t *parsed = - strmap_get(parsed_clients, client->client_name); - int written; - size_t len; - /* Copy descriptor cookie from parsed entry or create new one. */ - if (parsed) { - memcpy(client->descriptor_cookie, parsed->descriptor_cookie, - REND_DESC_COOKIE_LEN); - } else { - crypto_rand(client->descriptor_cookie, REND_DESC_COOKIE_LEN); - } - if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1, - client->descriptor_cookie, - REND_DESC_COOKIE_LEN) < 0) { - log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); - strmap_free(parsed_clients, rend_authorized_client_strmap_item_free); - return -1; - } - /* Copy client key from parsed entry or create new one if required. */ - if (parsed && parsed->client_key) { - client->client_key = crypto_pk_dup_key(parsed->client_key); - } else if (s->auth_type == REND_STEALTH_AUTH) { - /* Create private key for client. */ - crypto_pk_t *prkey = NULL; - if (!(prkey = crypto_pk_new())) { - log_warn(LD_BUG,"Error constructing client key"); - goto err; - } - if (crypto_pk_generate_key(prkey)) { - log_warn(LD_BUG,"Error generating client key"); - crypto_pk_free(prkey); - goto err; - } - if (crypto_pk_check_key(prkey) <= 0) { - log_warn(LD_BUG,"Generated client key seems invalid"); - crypto_pk_free(prkey); - goto err; - } - client->client_key = prkey; - } - /* Add entry to client_keys file. */ - desc_cook_out[strlen(desc_cook_out)-1] = '\0'; /* Remove newline. */ - written = tor_snprintf(buf, sizeof(buf), - "client-name %s\ndescriptor-cookie %s\n", - client->client_name, desc_cook_out); - if (written < 0) { - log_warn(LD_BUG, "Could not write client entry."); - goto err; - } - if (client->client_key) { - char *client_key_out = NULL; - crypto_pk_write_private_key_to_string(client->client_key, - &client_key_out, &len); - if (rend_get_service_id(client->client_key, service_id)<0) { - log_warn(LD_BUG, "Internal error: couldn't encode service ID."); - tor_free(client_key_out); - goto err; - } - written = tor_snprintf(buf + written, sizeof(buf) - written, - "client-key\n%s", client_key_out); - tor_free(client_key_out); - if (written < 0) { - log_warn(LD_BUG, "Could not write client entry."); - goto err; - } - } - - if (fputs(buf, cfile) < 0) { - log_warn(LD_FS, "Could not append client entry to file: %s", - strerror(errno)); - goto err; - } - - /* Add line to hostname file. */ - if (s->auth_type == REND_BASIC_AUTH) { - /* Remove == signs (newline has been removed above). */ - desc_cook_out[strlen(desc_cook_out)-2] = '\0'; - tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n", - s->service_id, desc_cook_out, client->client_name); - } else { - char extended_desc_cookie[REND_DESC_COOKIE_LEN+1]; - memcpy(extended_desc_cookie, client->descriptor_cookie, - REND_DESC_COOKIE_LEN); - extended_desc_cookie[REND_DESC_COOKIE_LEN] = - ((int)s->auth_type - 1) << 4; - if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1, - extended_desc_cookie, - REND_DESC_COOKIE_LEN+1) < 0) { - log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); - goto err; - } - desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and - newline. */ - tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n", - service_id, desc_cook_out, client->client_name); - } + if (fputs(buf, cfile) < 0) { + log_warn(LD_FS, "Could not append client entry to file: %s", + strerror(errno)); + goto err; + } - if (fputs(buf, hfile)<0) { - log_warn(LD_FS, "Could not append host entry to file: %s", - strerror(errno)); - goto err; - } + /* Add line to hostname file. */ + if (s->auth_type == REND_BASIC_AUTH) { + /* Remove == signs (newline has been removed above). */ + desc_cook_out[strlen(desc_cook_out)-2] = '\0'; + tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n", + s->service_id, desc_cook_out, client->client_name); + } else { + memcpy(extended_desc_cookie, client->descriptor_cookie, + REND_DESC_COOKIE_LEN); + extended_desc_cookie[REND_DESC_COOKIE_LEN] = + ((int)s->auth_type - 1) << 4; + if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1, + extended_desc_cookie, + REND_DESC_COOKIE_LEN+1) < 0) { + log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); + goto err; } - SMARTLIST_FOREACH_END(client); + desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and + newline. */ + tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n", + service_id, desc_cook_out, client->client_name); + } - goto done; - err: - r = -1; - done: - tor_free(client_keys_str); - strmap_free(parsed_clients, rend_authorized_client_strmap_item_free); - if (r<0) { - if (open_cfile) - abort_writing_to_file(open_cfile); - if (open_hfile) - abort_writing_to_file(open_hfile); - return r; - } else { - finish_writing_to_file(open_cfile); - finish_writing_to_file(open_hfile); - } + if (fputs(buf, hfile)<0) { + log_warn(LD_FS, "Could not append host entry to file: %s", + strerror(errno)); + goto err; } - } SMARTLIST_FOREACH_END(s); + } SMARTLIST_FOREACH_END(client); + + finish_writing_to_file(open_cfile); + finish_writing_to_file(open_hfile); + + goto done; + err: + r = -1; + if (open_cfile) + abort_writing_to_file(open_cfile); + if (open_hfile) + abort_writing_to_file(open_hfile); + done: + if (client_keys_str) { + tor_strclear(client_keys_str); + tor_free(client_keys_str); + } + strmap_free(parsed_clients, rend_authorized_client_strmap_item_free); + + memwipe(cfname, 0, sizeof(cfname)); + + /* Clear stack buffers that held key-derived material. */ + memwipe(buf, 0, sizeof(buf)); + memwipe(desc_cook_out, 0, sizeof(desc_cook_out)); + memwipe(service_id, 0, sizeof(service_id)); + memwipe(extended_desc_cookie, 0, sizeof(extended_desc_cookie)); + return r; } @@ -860,7 +932,7 @@ rend_service_requires_uptime(rend_service_t *service) for (i=0; i < smartlist_len(service->ports); ++i) { p = smartlist_get(service->ports, i); - if (smartlist_string_num_isin(get_options()->LongLivedPorts, + if (smartlist_contains_int_as_string(get_options()->LongLivedPorts, p->virtual_port)) return 1; } @@ -906,26 +978,6 @@ rend_check_authorization(rend_service_t *service, return 1; } -/** Remove elements from <b>service</b>'s replay cache that are old enough to - * be noticed by timestamp checking. */ -static void -clean_accepted_intro_dh_parts(rend_service_t *service, time_t now) -{ - const time_t cutoff = now - REND_REPLAY_TIME_INTERVAL; - - service->last_cleaned_accepted_intro_dh_parts = now; - if (!service->accepted_intro_dh_parts) - return; - - DIGESTMAP_FOREACH_MODIFY(service->accepted_intro_dh_parts, digest, - time_t *, t) { - if (*t < cutoff) { - tor_free(t); - MAP_DEL_CURRENT(digest); - } - } DIGESTMAP_FOREACH_END; -} - /** Called when <b>intro</b> will soon be removed from * <b>service</b>'s list of intro points. */ static void @@ -1033,42 +1085,51 @@ rend_service_note_removing_intro_point(rend_service_t *service, /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen * rendezvous point. */ - /* XXXX024 this function sure could use some organizing. -RD */ int rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, size_t request_len) { - char *ptr, *r_cookie; - extend_info_t *extend_info = NULL; + /* Global status stuff */ + int status = 0, result; + const or_options_t *options = get_options(); + char *err_msg = NULL; + const char *stage_descr = NULL; + int reason = END_CIRC_REASON_TORPROTOCOL; + /* Service/circuit/key stuff we can learn before parsing */ + char serviceid[REND_SERVICE_ID_LEN_BASE32+1]; + rend_service_t *service = NULL; + rend_intro_point_t *intro_point = NULL; + crypto_pk_t *intro_key = NULL; + /* Parsed cell */ + rend_intro_cell_t *parsed_req = NULL; + /* Rendezvous point */ + extend_info_t *rp = NULL; + /* + * We need to look up and construct the extend_info_t for v0 and v1, + * but all the info is in the cell and it's constructed by the parser + * for v2 and v3, so freeing it would be a double-free. Use this to + * keep track of whether we should free it. + */ + uint8_t need_rp_free = 0; + /* XXX not handled yet */ char buf[RELAY_PAYLOAD_SIZE]; char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */ - rend_service_t *service; - rend_intro_point_t *intro_point; - int r, i, v3_shift = 0; - size_t len, keylen; + int i; crypto_dh_t *dh = NULL; origin_circuit_t *launched = NULL; crypt_path_t *cpath = NULL; - char serviceid[REND_SERVICE_ID_LEN_BASE32+1]; char hexcookie[9]; int circ_needs_uptime; - int reason = END_CIRC_REASON_TORPROTOCOL; - crypto_pk_t *intro_key; - char intro_key_digest[DIGEST_LEN]; - int auth_type; - size_t auth_len = 0; - char auth_data[REND_DESC_COOKIE_LEN]; - crypto_digest_t *digest = NULL; time_t now = time(NULL); - char diffie_hellman_hash[DIGEST_LEN]; - time_t *access_time; - const or_options_t *options = get_options(); + time_t elapsed; + int replay; - if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) { + /* Do some initial validation and logging before we parse the cell */ + if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_INTRO) { log_warn(LD_PROTOCOL, - "Got an INTRODUCE2 over a non-introduction circuit %d.", - circuit->_base.n_circ_id); - return -1; + "Got an INTRODUCE2 over a non-introduction circuit %u.", + (unsigned) circuit->base_.n_circ_id); + goto err; } #ifndef NON_ANONYMOUS_MODE_ENABLED @@ -1076,218 +1137,150 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, #endif tor_assert(circuit->rend_data); + /* We'll use this in a bazillion log messages */ base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN); - log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.", - escaped(serviceid), circuit->_base.n_circ_id); - - /* min key length plus digest length plus nickname length */ - if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+ - DH_KEY_LEN+42) { - log_warn(LD_PROTOCOL, "Got a truncated INTRODUCE2 cell on circ %d.", - circuit->_base.n_circ_id); - return -1; - } /* look up service depending on circuit. */ - service = rend_service_get_by_pk_digest( - circuit->rend_data->rend_pk_digest); + service = + rend_service_get_by_pk_digest(circuit->rend_data->rend_pk_digest); if (!service) { - log_warn(LD_BUG, "Internal error: Got an INTRODUCE2 cell on an intro " + log_warn(LD_BUG, + "Internal error: Got an INTRODUCE2 cell on an intro " "circ for an unrecognized service %s.", escaped(serviceid)); - return -1; - } - - /* 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); - if (tor_memneq(intro_key_digest, request, DIGEST_LEN)) { - base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, - (char*)request, REND_SERVICE_ID_LEN); - log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).", - escaped(serviceid)); - return -1; - } - - keylen = crypto_pk_keysize(intro_key); - if (request_len < keylen+DIGEST_LEN) { - log_warn(LD_PROTOCOL, - "PK-encrypted portion of INTRODUCE2 cell was truncated."); - return -1; + goto err; } intro_point = find_intro_point(circuit); if (intro_point == NULL) { - log_warn(LD_BUG, "Internal error: Got an INTRODUCE2 cell on an intro circ " - "(for service %s) with no corresponding rend_intro_point_t.", + log_warn(LD_BUG, + "Internal error: Got an INTRODUCE2 cell on an " + "intro circ (for service %s) with no corresponding " + "rend_intro_point_t.", escaped(serviceid)); - return -1; - } - - if (!service->accepted_intro_dh_parts) - service->accepted_intro_dh_parts = digestmap_new(); - - if (!intro_point->accepted_intro_rsa_parts) - intro_point->accepted_intro_rsa_parts = digestmap_new(); - - { - char pkpart_digest[DIGEST_LEN]; - /* Check for replay of PK-encrypted portion. */ - crypto_digest(pkpart_digest, (char*)request+DIGEST_LEN, keylen); - access_time = digestmap_get(intro_point->accepted_intro_rsa_parts, - pkpart_digest); - if (access_time != NULL) { - log_warn(LD_REND, "Possible replay detected! We received an " - "INTRODUCE2 cell with same PK-encrypted part %d seconds ago. " - "Dropping cell.", (int)(now-*access_time)); - return -1; - } - access_time = tor_malloc(sizeof(time_t)); - *access_time = now; - digestmap_set(intro_point->accepted_intro_rsa_parts, - pkpart_digest, access_time); - } - - /* Next N bytes is encrypted with service key */ - note_crypto_pk_op(REND_SERVER); - r = crypto_pk_private_hybrid_decrypt( - intro_key,buf,sizeof(buf), - (char*)(request+DIGEST_LEN),request_len-DIGEST_LEN, - PK_PKCS1_OAEP_PADDING,1); - if (r<0) { - log_warn(LD_PROTOCOL, "Couldn't decrypt INTRODUCE2 cell."); - return -1; + goto err; } - len = r; - if (*buf == 3) { - /* Version 3 INTRODUCE2 cell. */ - v3_shift = 1; - auth_type = buf[1]; - switch (auth_type) { - case REND_BASIC_AUTH: - /* fall through */ - case REND_STEALTH_AUTH: - auth_len = ntohs(get_uint16(buf+2)); - if (auth_len != REND_DESC_COOKIE_LEN) { - log_info(LD_REND, "Wrong auth data size %d, should be %d.", - (int)auth_len, REND_DESC_COOKIE_LEN); - return -1; - } - memcpy(auth_data, buf+4, sizeof(auth_data)); - v3_shift += 2+REND_DESC_COOKIE_LEN; - break; - case REND_NO_AUTH: - break; - default: - log_info(LD_REND, "Unknown authorization type '%d'", auth_type); - } - /* Skip the timestamp field. We no longer use it. */ - v3_shift += 4; - } - if (*buf == 2 || *buf == 3) { - /* Version 2 INTRODUCE2 cell. */ - int klen; - extend_info = tor_malloc_zero(sizeof(extend_info_t)); - tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf+v3_shift+1)); - extend_info->port = ntohs(get_uint16(buf+v3_shift+5)); - memcpy(extend_info->identity_digest, buf+v3_shift+7, - DIGEST_LEN); - extend_info->nickname[0] = '$'; - base16_encode(extend_info->nickname+1, sizeof(extend_info->nickname)-1, - extend_info->identity_digest, DIGEST_LEN); - - klen = ntohs(get_uint16(buf+v3_shift+7+DIGEST_LEN)); - if ((int)len != v3_shift+7+DIGEST_LEN+2+klen+20+128) { - log_warn(LD_PROTOCOL, "Bad length %u for version %d INTRODUCE2 cell.", - (int)len, *buf); - reason = END_CIRC_REASON_TORPROTOCOL; - goto err; - } - extend_info->onion_key = - crypto_pk_asn1_decode(buf+v3_shift+7+DIGEST_LEN+2, klen); - if (!extend_info->onion_key) { - log_warn(LD_PROTOCOL, "Error decoding onion key in version %d " - "INTRODUCE2 cell.", *buf); - reason = END_CIRC_REASON_TORPROTOCOL; - goto err; - } - ptr = buf+v3_shift+7+DIGEST_LEN+2+klen; - len -= v3_shift+7+DIGEST_LEN+2+klen; - } else { - char *rp_nickname; - size_t nickname_field_len; - const node_t *node; - int version; - if (*buf == 1) { - rp_nickname = buf+1; - nickname_field_len = MAX_HEX_NICKNAME_LEN+1; - version = 1; - } else { - nickname_field_len = MAX_NICKNAME_LEN+1; - rp_nickname = buf; - version = 0; - } - ptr=memchr(rp_nickname,0,nickname_field_len); - if (!ptr || ptr == rp_nickname) { - log_warn(LD_PROTOCOL, - "Couldn't find a nul-padded nickname in INTRODUCE2 cell."); - return -1; - } - if ((version == 0 && !is_legal_nickname(rp_nickname)) || - (version == 1 && !is_legal_nickname_or_hexdigest(rp_nickname))) { - log_warn(LD_PROTOCOL, "Bad nickname in INTRODUCE2 cell."); - return -1; - } - /* Okay, now we know that a nickname is at the start of the buffer. */ - ptr = rp_nickname+nickname_field_len; - len -= nickname_field_len; - len -= rp_nickname - buf; /* also remove header space used by version, if - * any */ - node = node_get_by_nickname(rp_nickname, 0); - if (!node) { - log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.", - escaped_safe_str_client(rp_nickname)); - /* XXXX Add a no-such-router reason? */ - reason = END_CIRC_REASON_TORPROTOCOL; - goto err; - } + log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %u.", + escaped(serviceid), (unsigned)circuit->base_.n_circ_id); - extend_info = extend_info_from_node(node, 0); - } + /* use intro key instead of service key. */ + intro_key = circuit->intro_key; - if (len != REND_COOKIE_LEN+DH_KEY_LEN) { - log_warn(LD_PROTOCOL, "Bad length %u for INTRODUCE2 cell.", (int)len); - reason = END_CIRC_REASON_TORPROTOCOL; + tor_free(err_msg); + stage_descr = NULL; + + stage_descr = "early parsing"; + /* Early parsing pass (get pk, ciphertext); type 2 is INTRODUCE2 */ + parsed_req = + rend_service_begin_parse_intro(request, request_len, 2, &err_msg); + if (!parsed_req) { + goto log_error; + } else if (err_msg) { + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); + tor_free(err_msg); + } + + stage_descr = "early validation"; + /* Early validation of pk/ciphertext part */ + result = rend_service_validate_intro_early(parsed_req, &err_msg); + if (result < 0) { + goto log_error; + } else if (err_msg) { + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); + tor_free(err_msg); + } + + /* make sure service replay caches are present */ + if (!service->accepted_intro_dh_parts) { + service->accepted_intro_dh_parts = + replaycache_new(REND_REPLAY_TIME_INTERVAL, + REND_REPLAY_TIME_INTERVAL); + } + + if (!intro_point->accepted_intro_rsa_parts) { + intro_point->accepted_intro_rsa_parts = replaycache_new(0, 0); + } + + /* check for replay of PK-encrypted portion. */ + replay = replaycache_add_test_and_elapsed( + intro_point->accepted_intro_rsa_parts, + parsed_req->ciphertext, (int)parsed_req->ciphertext_len, + &elapsed); + + if (replay) { + log_warn(LD_REND, + "Possible replay detected! We received an " + "INTRODUCE2 cell with same PK-encrypted part %d " + "seconds ago. Dropping cell.", + (int)elapsed); goto err; } + stage_descr = "decryption"; + /* Now try to decrypt it */ + result = rend_service_decrypt_intro(parsed_req, intro_key, &err_msg); + if (result < 0) { + goto log_error; + } else if (err_msg) { + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); + tor_free(err_msg); + } + + stage_descr = "late parsing"; + /* Parse the plaintext */ + result = rend_service_parse_intro_plaintext(parsed_req, &err_msg); + if (result < 0) { + goto log_error; + } else if (err_msg) { + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); + tor_free(err_msg); + } + + stage_descr = "late validation"; + /* Validate the parsed plaintext parts */ + result = rend_service_validate_intro_late(parsed_req, &err_msg); + if (result < 0) { + goto log_error; + } else if (err_msg) { + log_info(LD_REND, "%s on circ %u.", err_msg, + (unsigned)circuit->base_.n_circ_id); + tor_free(err_msg); + } + stage_descr = NULL; + + /* Increment INTRODUCE2 counter */ + ++(intro_point->accepted_introduce2_count); + + /* Find the rendezvous point */ + rp = find_rp_for_intro(parsed_req, &need_rp_free, &err_msg); + if (!rp) + goto log_error; + /* Check if we'd refuse to talk to this router */ if (options->StrictNodes && - routerset_contains_extendinfo(options->ExcludeNodes, extend_info)) { + routerset_contains_extendinfo(options->ExcludeNodes, rp)) { log_warn(LD_REND, "Client asked to rendezvous at a relay that we " "exclude, and StrictNodes is set. Refusing service."); reason = END_CIRC_REASON_INTERNAL; /* XXX might leak why we refused */ goto err; } - r_cookie = ptr; - base16_encode(hexcookie,9,r_cookie,4); - - /* Determine hash of Diffie-Hellman, part 1 to detect replays. */ - digest = crypto_digest_new(); - crypto_digest_add_bytes(digest, ptr+REND_COOKIE_LEN, DH_KEY_LEN); - crypto_digest_get_digest(digest, diffie_hellman_hash, DIGEST_LEN); - crypto_digest_free(digest); + base16_encode(hexcookie, 9, (const char *)(parsed_req->rc), 4); /* Check whether there is a past request with the same Diffie-Hellman, * part 1. */ - access_time = digestmap_get(service->accepted_intro_dh_parts, - diffie_hellman_hash); - if (access_time != NULL) { + replay = replaycache_add_test_and_elapsed( + service->accepted_intro_dh_parts, + parsed_req->dh, DH_KEY_LEN, + &elapsed); + + if (replay) { /* A Tor client will send a new INTRODUCE1 cell with the same rend * cookie and DH public key as its previous one if its intro circ * times out while in state CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT . @@ -1299,25 +1292,15 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, "INTRODUCE2 cell with same first part of " "Diffie-Hellman handshake %d seconds ago. Dropping " "cell.", - (int) (now - *access_time)); + (int) elapsed); goto err; } - /* Add request to access history, including time and hash of Diffie-Hellman, - * part 1, and possibly remove requests from the history that are older than - * one hour. */ - access_time = tor_malloc(sizeof(time_t)); - *access_time = now; - digestmap_set(service->accepted_intro_dh_parts, - diffie_hellman_hash, access_time); - if (service->last_cleaned_accepted_intro_dh_parts + REND_REPLAY_TIME_INTERVAL - < now) - clean_accepted_intro_dh_parts(service, now); - /* If the service performs client authorization, check included auth data. */ if (service->clients) { - if (auth_len > 0) { - if (rend_check_authorization(service, auth_data)) { + if (parsed_req->version == 3 && parsed_req->u.v3.auth_len > 0) { + if (rend_check_authorization(service, + (const char*)parsed_req->u.v3.auth_data)) { log_info(LD_REND, "Authorization data in INTRODUCE2 cell are valid."); } else { log_info(LD_REND, "The authorization data that are contained in " @@ -1341,7 +1324,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, reason = END_CIRC_REASON_INTERNAL; goto err; } - if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, ptr+REND_COOKIE_LEN, + if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, + (char *)(parsed_req->dh), DH_KEY_LEN, keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) { log_warn(LD_BUG, "Internal error: couldn't complete DH handshake"); @@ -1360,7 +1344,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL; if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME; launched = circuit_launch_by_extend_info( - CIRCUIT_PURPOSE_S_CONNECT_REND, extend_info, flags); + CIRCUIT_PURPOSE_S_CONNECT_REND, rp, flags); if (launched) break; @@ -1368,7 +1352,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (!launched) { /* give up */ log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous " "point %s for service %s.", - safe_str_client(extend_info_describe(extend_info)), + safe_str_client(extend_info_describe(rp)), serviceid); reason = END_CIRC_REASON_CONNECTFAILED; goto err; @@ -1376,7 +1360,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, log_info(LD_REND, "Accepted intro; launching circuit to %s " "(cookie %s) for service %s.", - safe_str_client(extend_info_describe(extend_info)), + safe_str_client(extend_info_describe(rp)), hexcookie, serviceid); tor_assert(launched->build_state); /* Fill in the circuit's state. */ @@ -1384,7 +1368,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, memcpy(launched->rend_data->rend_pk_digest, circuit->rend_data->rend_pk_digest, DIGEST_LEN); - memcpy(launched->rend_data->rend_cookie, r_cookie, REND_COOKIE_LEN); + memcpy(launched->rend_data->rend_cookie, parsed_req->rc, REND_COOKIE_LEN); strlcpy(launched->rend_data->onion_address, service->service_id, sizeof(launched->rend_data->onion_address)); @@ -1397,24 +1381,875 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, cpath->magic = CRYPT_PATH_MAGIC; launched->build_state->expiry_time = now + MAX_REND_TIMEOUT; - cpath->dh_handshake_state = dh; + cpath->rend_dh_handshake_state = dh; dh = NULL; if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0) goto err; - memcpy(cpath->handshake_digest, keys, DIGEST_LEN); - if (extend_info) extend_info_free(extend_info); + memcpy(cpath->rend_circ_nonce, keys, DIGEST_LEN); - memwipe(keys, 0, sizeof(keys)); - return 0; + goto done; + + log_error: + if (!err_msg) { + if (stage_descr) { + tor_asprintf(&err_msg, + "unknown %s error for INTRODUCE2", stage_descr); + } else { + err_msg = tor_strdup("unknown error for INTRODUCE2"); + } + } + + log_warn(LD_REND, "%s on circ %u", err_msg, + (unsigned)circuit->base_.n_circ_id); err: - memwipe(keys, 0, sizeof(keys)); + status = -1; if (dh) crypto_dh_free(dh); - if (launched) + if (launched) { circuit_mark_for_close(TO_CIRCUIT(launched), reason); - if (extend_info) extend_info_free(extend_info); + } + tor_free(err_msg); + + done: + memwipe(keys, 0, sizeof(keys)); + memwipe(buf, 0, sizeof(buf)); + memwipe(serviceid, 0, sizeof(serviceid)); + memwipe(hexcookie, 0, sizeof(hexcookie)); + + /* Free the parsed cell */ + if (parsed_req) { + rend_service_free_intro(parsed_req); + parsed_req = NULL; + } + + /* Free rp if we must */ + if (need_rp_free) extend_info_free(rp); + + return status; +} + +/** Given a parsed and decrypted INTRODUCE2, find the rendezvous point or + * return NULL and an error string if we can't. + */ + +static extend_info_t * +find_rp_for_intro(const rend_intro_cell_t *intro, + uint8_t *need_free_out, char **err_msg_out) +{ + extend_info_t *rp = NULL; + char *err_msg = NULL; + const char *rp_nickname = NULL; + const node_t *node = NULL; + uint8_t need_free = 0; + + if (!intro || !need_free_out) { + if (err_msg_out) + err_msg = tor_strdup("Bad parameters to find_rp_for_intro()"); + + goto err; + } + + if (intro->version == 0 || intro->version == 1) { + if (intro->version == 1) rp_nickname = (const char *)(intro->u.v1.rp); + else rp_nickname = (const char *)(intro->u.v0.rp); + + node = node_get_by_nickname(rp_nickname, 0); + if (!node) { + if (err_msg_out) { + tor_asprintf(&err_msg, + "Couldn't find router %s named in INTRODUCE2 cell", + escaped_safe_str_client(rp_nickname)); + } + + goto err; + } + + rp = extend_info_from_node(node, 0); + if (!rp) { + if (err_msg_out) { + tor_asprintf(&err_msg, + "Could build extend_info_t for router %s named " + "in INTRODUCE2 cell", + escaped_safe_str_client(rp_nickname)); + } + + goto err; + } else { + need_free = 1; + } + } else if (intro->version == 2) { + rp = intro->u.v2.extend_info; + } else if (intro->version == 3) { + rp = intro->u.v3.extend_info; + } else { + if (err_msg_out) { + tor_asprintf(&err_msg, + "Unknown version %d in INTRODUCE2 cell", + (int)(intro->version)); + } + + goto err; + } + + goto done; + + err: + if (err_msg_out) *err_msg_out = err_msg; + else tor_free(err_msg); + + done: + if (rp && need_free_out) *need_free_out = need_free; + + return rp; +} + +/** Remove unnecessary parts from a rend_intro_cell_t - the ciphertext if + * already decrypted, the plaintext too if already parsed + */ + +void +rend_service_compact_intro(rend_intro_cell_t *request) +{ + if (!request) return; + + if ((request->plaintext && request->plaintext_len > 0) || + request->parsed) { + tor_free(request->ciphertext); + request->ciphertext_len = 0; + } + + if (request->parsed) { + tor_free(request->plaintext); + request->plaintext_len = 0; + } +} + +/** Free a parsed INTRODUCE1 or INTRODUCE2 cell that was allocated by + * rend_service_parse_intro(). + */ +void +rend_service_free_intro(rend_intro_cell_t *request) +{ + if (!request) { + log_info(LD_BUG, "rend_service_free_intro() called with NULL request!"); + return; + } + + /* Free ciphertext */ + tor_free(request->ciphertext); + request->ciphertext_len = 0; + + /* Have plaintext? */ + if (request->plaintext) { + /* Zero it out just to be safe */ + memwipe(request->plaintext, 0, request->plaintext_len); + tor_free(request->plaintext); + request->plaintext_len = 0; + } + + /* Have parsed plaintext? */ + if (request->parsed) { + switch (request->version) { + case 0: + case 1: + /* + * Nothing more to do; these formats have no further pointers + * in them. + */ + break; + case 2: + extend_info_free(request->u.v2.extend_info); + request->u.v2.extend_info = NULL; + break; + case 3: + if (request->u.v3.auth_data) { + memwipe(request->u.v3.auth_data, 0, request->u.v3.auth_len); + tor_free(request->u.v3.auth_data); + } + + extend_info_free(request->u.v3.extend_info); + request->u.v3.extend_info = NULL; + break; + default: + log_info(LD_BUG, + "rend_service_free_intro() saw unknown protocol " + "version %d.", + request->version); + } + } + + /* Zero it out to make sure sensitive stuff doesn't hang around in memory */ + memwipe(request, 0, sizeof(*request)); + + tor_free(request); +} + +/** Parse an INTRODUCE1 or INTRODUCE2 cell into a newly allocated + * rend_intro_cell_t structure. Free it with rend_service_free_intro() + * when finished. The type parameter should be 1 or 2 to indicate whether + * this is INTRODUCE1 or INTRODUCE2. This parses only the non-encrypted + * parts; after this, call rend_service_decrypt_intro() with a key, then + * rend_service_parse_intro_plaintext() to finish parsing. The optional + * err_msg_out parameter is set to a string suitable for log output + * if parsing fails. This function does some validation, but only + * that which depends solely on the contents of the cell and the + * key; it can be unit-tested. Further validation is done in + * rend_service_validate_intro(). + */ + +rend_intro_cell_t * +rend_service_begin_parse_intro(const uint8_t *request, + size_t request_len, + uint8_t type, + char **err_msg_out) +{ + rend_intro_cell_t *rv = NULL; + char *err_msg = NULL; + + if (!request || request_len <= 0) goto err; + if (!(type == 1 || type == 2)) goto err; + + /* First, check that the cell is long enough to be a sensible INTRODUCE */ + + /* min key length plus digest length plus nickname length */ + if (request_len < + (DIGEST_LEN + REND_COOKIE_LEN + (MAX_NICKNAME_LEN + 1) + + DH_KEY_LEN + 42)) { + if (err_msg_out) { + tor_asprintf(&err_msg, + "got a truncated INTRODUCE%d cell", + (int)type); + } + goto err; + } + + /* Allocate a new parsed cell structure */ + rv = tor_malloc_zero(sizeof(*rv)); + + /* Set the type */ + rv->type = type; + + /* Copy in the ID */ + memcpy(rv->pk, request, DIGEST_LEN); + + /* Copy in the ciphertext */ + rv->ciphertext = tor_malloc(request_len - DIGEST_LEN); + memcpy(rv->ciphertext, request + DIGEST_LEN, request_len - DIGEST_LEN); + rv->ciphertext_len = request_len - DIGEST_LEN; + + goto done; + + err: + if (rv) rend_service_free_intro(rv); + rv = NULL; + if (err_msg_out && !err_msg) { + tor_asprintf(&err_msg, + "unknown INTRODUCE%d error", + (int)type); + } + + done: + if (err_msg_out) *err_msg_out = err_msg; + else tor_free(err_msg); + + return rv; +} + +/** Parse the version-specific parts of a v0 or v1 INTRODUCE1 or INTRODUCE2 + * cell + */ + +static ssize_t +rend_service_parse_intro_for_v0_or_v1( + rend_intro_cell_t *intro, + const uint8_t *buf, + size_t plaintext_len, + char **err_msg_out) +{ + const char *rp_nickname, *endptr; + size_t nickname_field_len, ver_specific_len; + + if (intro->version == 1) { + ver_specific_len = MAX_HEX_NICKNAME_LEN + 2; + rp_nickname = ((const char *)buf) + 1; + nickname_field_len = MAX_HEX_NICKNAME_LEN + 1; + } else if (intro->version == 0) { + ver_specific_len = MAX_NICKNAME_LEN + 1; + rp_nickname = (const char *)buf; + nickname_field_len = MAX_NICKNAME_LEN + 1; + } else { + if (err_msg_out) + tor_asprintf(err_msg_out, + "rend_service_parse_intro_for_v0_or_v1() called with " + "bad version %d on INTRODUCE%d cell (this is a bug)", + intro->version, + (int)(intro->type)); + goto err; + } + + if (plaintext_len < ver_specific_len) { + if (err_msg_out) + tor_asprintf(err_msg_out, + "short plaintext of encrypted part in v1 INTRODUCE%d " + "cell (%lu bytes, needed %lu)", + (int)(intro->type), + (unsigned long)plaintext_len, + (unsigned long)ver_specific_len); + goto err; + } + + endptr = memchr(rp_nickname, 0, nickname_field_len); + if (!endptr || endptr == rp_nickname) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "couldn't find a nul-padded nickname in " + "INTRODUCE%d cell", + (int)(intro->type)); + } + goto err; + } + + if ((intro->version == 0 && + !is_legal_nickname(rp_nickname)) || + (intro->version == 1 && + !is_legal_nickname_or_hexdigest(rp_nickname))) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "bad nickname in INTRODUCE%d cell", + (int)(intro->type)); + } + goto err; + } + + if (intro->version == 1) { + memcpy(intro->u.v1.rp, rp_nickname, endptr - rp_nickname + 1); + } else { + memcpy(intro->u.v0.rp, rp_nickname, endptr - rp_nickname + 1); + } + + return ver_specific_len; + + err: + return -1; +} + +/** Parse the version-specific parts of a v2 INTRODUCE1 or INTRODUCE2 cell + */ + +static ssize_t +rend_service_parse_intro_for_v2( + rend_intro_cell_t *intro, + const uint8_t *buf, + size_t plaintext_len, + char **err_msg_out) +{ + unsigned int klen; + extend_info_t *extend_info = NULL; + ssize_t ver_specific_len; + + /* + * We accept version 3 too so that the v3 parser can call this with + * and adjusted buffer for the latter part of a v3 cell, which is + * identical to a v2 cell. + */ + if (!(intro->version == 2 || + intro->version == 3)) { + if (err_msg_out) + tor_asprintf(err_msg_out, + "rend_service_parse_intro_for_v2() called with " + "bad version %d on INTRODUCE%d cell (this is a bug)", + intro->version, + (int)(intro->type)); + goto err; + } + + /* 7 == version, IP and port, DIGEST_LEN == id, 2 == key length */ + if (plaintext_len < 7 + DIGEST_LEN + 2) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "truncated plaintext of encrypted parted of " + "version %d INTRODUCE%d cell", + intro->version, + (int)(intro->type)); + } + + goto err; + } + + extend_info = tor_malloc_zero(sizeof(extend_info_t)); + tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf + 1)); + extend_info->port = ntohs(get_uint16(buf + 5)); + memcpy(extend_info->identity_digest, buf + 7, DIGEST_LEN); + extend_info->nickname[0] = '$'; + base16_encode(extend_info->nickname + 1, sizeof(extend_info->nickname) - 1, + extend_info->identity_digest, DIGEST_LEN); + klen = ntohs(get_uint16(buf + 7 + DIGEST_LEN)); + + /* 7 == version, IP and port, DIGEST_LEN == id, 2 == key length */ + if (plaintext_len < 7 + DIGEST_LEN + 2 + klen) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "truncated plaintext of encrypted parted of " + "version %d INTRODUCE%d cell", + intro->version, + (int)(intro->type)); + } + + goto err; + } + + extend_info->onion_key = + crypto_pk_asn1_decode((const char *)(buf + 7 + DIGEST_LEN + 2), klen); + if (!extend_info->onion_key) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "error decoding onion key in version %d " + "INTRODUCE%d cell", + intro->version, + (intro->type)); + } + + goto err; + } + + ver_specific_len = 7+DIGEST_LEN+2+klen; + + if (intro->version == 2) intro->u.v2.extend_info = extend_info; + else intro->u.v3.extend_info = extend_info; + + return ver_specific_len; + + err: + extend_info_free(extend_info); + + return -1; +} + +/** Parse the version-specific parts of a v3 INTRODUCE1 or INTRODUCE2 cell + */ + +static ssize_t +rend_service_parse_intro_for_v3( + rend_intro_cell_t *intro, + const uint8_t *buf, + size_t plaintext_len, + char **err_msg_out) +{ + ssize_t adjust, v2_ver_specific_len, ts_offset; + + /* This should only be called on v3 cells */ + if (intro->version != 3) { + if (err_msg_out) + tor_asprintf(err_msg_out, + "rend_service_parse_intro_for_v3() called with " + "bad version %d on INTRODUCE%d cell (this is a bug)", + intro->version, + (int)(intro->type)); + goto err; + } + + /* + * Check that we have at least enough to get auth_len: + * + * 1 octet for version, 1 for auth_type, 2 for auth_len + */ + if (plaintext_len < 4) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "truncated plaintext of encrypted parted of " + "version %d INTRODUCE%d cell", + intro->version, + (int)(intro->type)); + } + + goto err; + } + + /* + * The rend_client_send_introduction() function over in rendclient.c is + * broken (i.e., fails to match the spec) in such a way that we can't + * change it without breaking the protocol. Specifically, it doesn't + * emit auth_len when auth-type is REND_NO_AUTH, so everything is off + * by two bytes after that. Calculate ts_offset and do everything from + * the timestamp on relative to that to handle this dain bramage. + */ + + intro->u.v3.auth_type = buf[1]; + if (intro->u.v3.auth_type != REND_NO_AUTH) { + intro->u.v3.auth_len = ntohs(get_uint16(buf + 2)); + ts_offset = 4 + intro->u.v3.auth_len; + } else { + intro->u.v3.auth_len = 0; + ts_offset = 2; + } + + /* Check that auth len makes sense for this auth type */ + if (intro->u.v3.auth_type == REND_BASIC_AUTH || + intro->u.v3.auth_type == REND_STEALTH_AUTH) { + if (intro->u.v3.auth_len != REND_DESC_COOKIE_LEN) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "wrong auth data size %d for INTRODUCE%d cell, " + "should be %d", + (int)(intro->u.v3.auth_len), + (int)(intro->type), + REND_DESC_COOKIE_LEN); + } + + goto err; + } + } + + /* Check that we actually have everything up through the timestamp */ + if (plaintext_len < (size_t)(ts_offset)+4) { + if (err_msg_out) { + tor_asprintf(err_msg_out, + "truncated plaintext of encrypted parted of " + "version %d INTRODUCE%d cell", + intro->version, + (int)(intro->type)); + } + + goto err; + } + + if (intro->u.v3.auth_type != REND_NO_AUTH && + intro->u.v3.auth_len > 0) { + /* Okay, we can go ahead and copy auth_data */ + intro->u.v3.auth_data = tor_malloc(intro->u.v3.auth_len); + /* + * We know we had an auth_len field in this case, so 4 is + * always right. + */ + memcpy(intro->u.v3.auth_data, buf + 4, intro->u.v3.auth_len); + } + + /* + * From here on, the format is as in v2, so we call the v2 parser with + * adjusted buffer and length. We are 4 + ts_offset octets in, but the + * v2 parser expects to skip over a version byte at the start, so we + * adjust by 3 + ts_offset. + */ + adjust = 3 + ts_offset; + + v2_ver_specific_len = + rend_service_parse_intro_for_v2(intro, + buf + adjust, plaintext_len - adjust, + err_msg_out); + + /* Success in v2 parser */ + if (v2_ver_specific_len >= 0) return v2_ver_specific_len + adjust; + /* Failure in v2 parser; it will have provided an err_msg */ + else return v2_ver_specific_len; + + err: return -1; } +/** Table of parser functions for version-specific parts of an INTRODUCE2 + * cell. + */ + +static ssize_t + (*intro_version_handlers[])( + rend_intro_cell_t *, + const uint8_t *, + size_t, + char **) = +{ rend_service_parse_intro_for_v0_or_v1, + rend_service_parse_intro_for_v0_or_v1, + rend_service_parse_intro_for_v2, + rend_service_parse_intro_for_v3 }; + +/** Decrypt the encrypted part of an INTRODUCE1 or INTRODUCE2 cell, + * return 0 if successful, or < 0 and write an error message to + * *err_msg_out if provided. + */ + +int +rend_service_decrypt_intro( + rend_intro_cell_t *intro, + crypto_pk_t *key, + char **err_msg_out) +{ + char *err_msg = NULL; + uint8_t key_digest[DIGEST_LEN]; + char service_id[REND_SERVICE_ID_LEN_BASE32+1]; + ssize_t key_len; + uint8_t buf[RELAY_PAYLOAD_SIZE]; + int result, status = 0; + + if (!intro || !key) { + if (err_msg_out) { + err_msg = + tor_strdup("rend_service_decrypt_intro() called with bad " + "parameters"); + } + + status = -2; + goto err; + } + + /* Make sure we have ciphertext */ + if (!(intro->ciphertext) || intro->ciphertext_len <= 0) { + if (err_msg_out) { + tor_asprintf(&err_msg, + "rend_intro_cell_t was missing ciphertext for " + "INTRODUCE%d cell", + (int)(intro->type)); + } + status = -3; + goto err; + } + + /* Check that this cell actually matches this service key */ + + /* first DIGEST_LEN bytes of request is intro or service pk digest */ + crypto_pk_get_digest(key, (char *)key_digest); + if (tor_memneq(key_digest, intro->pk, DIGEST_LEN)) { + if (err_msg_out) { + base32_encode(service_id, REND_SERVICE_ID_LEN_BASE32 + 1, + (char*)(intro->pk), REND_SERVICE_ID_LEN); + tor_asprintf(&err_msg, + "got an INTRODUCE%d cell for the wrong service (%s)", + (int)(intro->type), + escaped(service_id)); + } + + status = -4; + goto err; + } + + /* Make sure the encrypted part is long enough to decrypt */ + + key_len = crypto_pk_keysize(key); + if (intro->ciphertext_len < key_len) { + if (err_msg_out) { + tor_asprintf(&err_msg, + "got an INTRODUCE%d cell with a truncated PK-encrypted " + "part", + (int)(intro->type)); + } + + status = -5; + goto err; + } + + /* Decrypt the encrypted part */ + + note_crypto_pk_op(REND_SERVER); + result = + crypto_pk_private_hybrid_decrypt( + key, (char *)buf, sizeof(buf), + (const char *)(intro->ciphertext), intro->ciphertext_len, + PK_PKCS1_OAEP_PADDING, 1); + if (result < 0) { + if (err_msg_out) { + tor_asprintf(&err_msg, + "couldn't decrypt INTRODUCE%d cell", + (int)(intro->type)); + } + status = -6; + goto err; + } + intro->plaintext_len = result; + intro->plaintext = tor_malloc(intro->plaintext_len); + memcpy(intro->plaintext, buf, intro->plaintext_len); + + goto done; + + err: + if (err_msg_out && !err_msg) { + tor_asprintf(&err_msg, + "unknown INTRODUCE%d error decrypting encrypted part", + (int)(intro->type)); + } + if (status >= 0) status = -1; + + done: + if (err_msg_out) *err_msg_out = err_msg; + else tor_free(err_msg); + + /* clean up potentially sensitive material */ + memwipe(buf, 0, sizeof(buf)); + memwipe(key_digest, 0, sizeof(key_digest)); + memwipe(service_id, 0, sizeof(service_id)); + + return status; +} + +/** Parse the plaintext of the encrypted part of an INTRODUCE1 or + * INTRODUCE2 cell, return 0 if successful, or < 0 and write an error + * message to *err_msg_out if provided. + */ + +int +rend_service_parse_intro_plaintext( + rend_intro_cell_t *intro, + char **err_msg_out) +{ + char *err_msg = NULL; + ssize_t ver_specific_len, ver_invariant_len; + uint8_t version; + int status = 0; + + if (!intro) { + if (err_msg_out) { + err_msg = + tor_strdup("rend_service_parse_intro_plaintext() called with NULL " + "rend_intro_cell_t"); + } + + status = -2; + goto err; + } + + /* Check that we have plaintext */ + if (!(intro->plaintext) || intro->plaintext_len <= 0) { + if (err_msg_out) { + err_msg = tor_strdup("rend_intro_cell_t was missing plaintext"); + } + status = -3; + goto err; + } + + /* In all formats except v0, the first byte is a version number */ + version = intro->plaintext[0]; + + /* v0 has no version byte (stupid...), so handle it as a fallback */ + if (version > 3) version = 0; + + /* Copy the version into the parsed cell structure */ + intro->version = version; + + /* Call the version-specific parser from the table */ + ver_specific_len = + intro_version_handlers[version](intro, + intro->plaintext, intro->plaintext_len, + &err_msg); + if (ver_specific_len < 0) { + status = -4; + goto err; + } + + /** The rendezvous cookie and Diffie-Hellman stuff are version-invariant + * and at the end of the plaintext of the encrypted part of the cell. + */ + + ver_invariant_len = intro->plaintext_len - ver_specific_len; + if (ver_invariant_len < REND_COOKIE_LEN + DH_KEY_LEN) { + tor_asprintf(&err_msg, + "decrypted plaintext of INTRODUCE%d cell was truncated (%ld bytes)", + (int)(intro->type), + (long)(intro->plaintext_len)); + status = -5; + goto err; + } else if (ver_invariant_len > REND_COOKIE_LEN + DH_KEY_LEN) { + tor_asprintf(&err_msg, + "decrypted plaintext of INTRODUCE%d cell was too long (%ld bytes)", + (int)(intro->type), + (long)(intro->plaintext_len)); + status = -6; + } else { + memcpy(intro->rc, + intro->plaintext + ver_specific_len, + REND_COOKIE_LEN); + memcpy(intro->dh, + intro->plaintext + ver_specific_len + REND_COOKIE_LEN, + DH_KEY_LEN); + } + + /* Flag it as being fully parsed */ + intro->parsed = 1; + + goto done; + + err: + if (err_msg_out && !err_msg) { + tor_asprintf(&err_msg, + "unknown INTRODUCE%d error parsing encrypted part", + (int)(intro->type)); + } + if (status >= 0) status = -1; + + done: + if (err_msg_out) *err_msg_out = err_msg; + else tor_free(err_msg); + + return status; +} + +/** Do validity checks on a parsed intro cell before decryption; some of + * these are not done in rend_service_begin_parse_intro() itself because + * they depend on a lot of other state and would make it hard to unit test. + * Returns >= 0 if successful or < 0 if the intro cell is invalid, and + * optionally writes out an error message for logging. If an err_msg + * pointer is provided, it is the caller's responsibility to free any + * provided message. + */ + +int +rend_service_validate_intro_early(const rend_intro_cell_t *intro, + char **err_msg_out) +{ + int status = 0; + + if (!intro) { + if (err_msg_out) + *err_msg_out = + tor_strdup("NULL intro cell passed to " + "rend_service_validate_intro_early()"); + + status = -1; + goto err; + } + + /* TODO */ + + err: + return status; +} + +/** Do validity checks on a parsed intro cell after decryption; some of + * these are not done in rend_service_parse_intro_plaintext() itself because + * they depend on a lot of other state and would make it hard to unit test. + * Returns >= 0 if successful or < 0 if the intro cell is invalid, and + * optionally writes out an error message for logging. If an err_msg + * pointer is provided, it is the caller's responsibility to free any + * provided message. + */ + +int +rend_service_validate_intro_late(const rend_intro_cell_t *intro, + char **err_msg_out) +{ + int status = 0; + + if (!intro) { + if (err_msg_out) + *err_msg_out = + tor_strdup("NULL intro cell passed to " + "rend_service_validate_intro_late()"); + + status = -1; + goto err; + } + + if (intro->version == 3 && intro->parsed) { + if (!(intro->u.v3.auth_type == REND_NO_AUTH || + intro->u.v3.auth_type == REND_BASIC_AUTH || + intro->u.v3.auth_type == REND_STEALTH_AUTH)) { + /* This is an informative message, not an error, as in the old code */ + if (err_msg_out) + tor_asprintf(err_msg_out, + "unknown authorization type %d", + intro->u.v3.auth_type); + } + } + + err: + return status; +} + /** Called when we fail building a rendezvous circuit at some point other * than the last hop: launches a new circuit to the same rendezvous point. */ @@ -1424,7 +2259,7 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc) origin_circuit_t *newcirc; cpath_build_state_t *newstate, *oldstate; - tor_assert(oldcirc->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND); + tor_assert(oldcirc->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND); /* Don't relaunch the same rend circ twice. */ if (oldcirc->hs_service_side_rend_circ_has_been_relaunched) { @@ -1529,7 +2364,7 @@ rend_service_launch_establish_intro(rend_service_t *service, sizeof(launched->rend_data->onion_address)); memcpy(launched->rend_data->rend_pk_digest, service->pk_digest, DIGEST_LEN); launched->intro_key = crypto_pk_dup_key(intro->intro_key); - if (launched->_base.state == CIRCUIT_STATE_OPEN) + if (launched->base_.state == CIRCUIT_STATE_OPEN) rend_service_intro_has_opened(launched); return 0; } @@ -1541,7 +2376,7 @@ count_established_intro_points(const char *query) { int num_ipos = 0; circuit_t *circ; - for (circ = _circuit_get_global_list(); circ; circ = circ->next) { + for (circ = circuit_get_global_list_(); circ; circ = circ->next) { if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN && (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -1570,7 +2405,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) int reason = END_CIRC_REASON_TORPROTOCOL; crypto_pk_t *intro_key; - tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO); + tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO); #ifndef NON_ANONYMOUS_MODE_ENABLED tor_assert(!(circuit->build_state->onehop_tunnel)); #endif @@ -1583,8 +2418,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) 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); + log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %u.", + serviceid, (unsigned)circuit->base_.n_circ_id); reason = END_CIRC_REASON_NOSUCHSERVICE; goto err; } @@ -1600,8 +2435,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) this case, we might as well close the thing. */ log_info(LD_CIRC|LD_REND, "We have just finished an introduction " "circuit, but we already have enough. Closing it."); - circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_NONE); - return; + reason = END_CIRC_REASON_NONE; + goto err; } else { tor_assert(circuit->build_state->is_internal); log_info(LD_CIRC|LD_REND, "We have just finished an introduction " @@ -1622,13 +2457,13 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) } circuit_has_opened(circuit); - return; + goto done; } } log_info(LD_REND, - "Established circuit %d as introduction point for service %s", - circuit->_base.n_circ_id, serviceid); + "Established circuit %u as introduction point for service %s", + (unsigned)circuit->base_.n_circ_id, serviceid); /* Use the intro key instead of the service key in ESTABLISH_INTRO. */ intro_key = circuit->intro_key; @@ -1643,7 +2478,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) len = r; set_uint16(buf, htons((uint16_t)len)); len += 2; - memcpy(auth, circuit->cpath->prev->handshake_digest, DIGEST_LEN); + memcpy(auth, circuit->cpath->prev->rend_circ_nonce, DIGEST_LEN); memcpy(auth+DIGEST_LEN, "INTRODUCE", 9); if (crypto_digest(buf+len, auth, DIGEST_LEN+9)) goto err; @@ -1662,15 +2497,25 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) RELAY_COMMAND_ESTABLISH_INTRO, buf, len, circuit->cpath->prev)<0) { log_info(LD_GENERAL, - "Couldn't send introduction request for service %s on circuit %d", - serviceid, circuit->_base.n_circ_id); + "Couldn't send introduction request for service %s on circuit %u", + serviceid, (unsigned)circuit->base_.n_circ_id); reason = END_CIRC_REASON_INTERNAL; goto err; } - return; + /* We've attempted to use this circuit */ + pathbias_count_use_attempt(circuit); + + goto done; + err: circuit_mark_for_close(TO_CIRCUIT(circuit), reason); + done: + memwipe(buf, 0, sizeof(buf)); + memwipe(auth, 0, sizeof(auth)); + memwipe(serviceid, 0, sizeof(serviceid)); + + return; } /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a @@ -1686,7 +2531,7 @@ rend_service_intro_established(origin_circuit_t *circuit, (void) request; (void) request_len; - if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) { + if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) { log_warn(LD_PROTOCOL, "received INTRO_ESTABLISHED cell on non-intro circuit."); goto err; @@ -1695,8 +2540,8 @@ rend_service_intro_established(origin_circuit_t *circuit, 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); + log_warn(LD_REND, "Unknown service on introduction circuit %u.", + (unsigned)circuit->base_.n_circ_id); goto err; } service->desc_is_dirty = time(NULL); @@ -1705,8 +2550,12 @@ rend_service_intro_established(origin_circuit_t *circuit, base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32 + 1, circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN); log_info(LD_REND, - "Received INTRO_ESTABLISHED cell on circuit %d for service %s", - circuit->_base.n_circ_id, serviceid); + "Received INTRO_ESTABLISHED cell on circuit %u for service %s", + (unsigned)circuit->base_.n_circ_id, serviceid); + + /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully + * used the circ */ + pathbias_mark_use_success(circuit); return 0; err: @@ -1727,13 +2576,21 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) char hexcookie[9]; int reason; - tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND); + tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND); tor_assert(circuit->cpath); tor_assert(circuit->build_state); #ifndef NON_ANONYMOUS_MODE_ENABLED tor_assert(!(circuit->build_state->onehop_tunnel)); #endif tor_assert(circuit->rend_data); + + /* Declare the circuit dirty to avoid reuse, and for path-bias */ + if (!circuit->base_.timestamp_dirty) + circuit->base_.timestamp_dirty = time(NULL); + + /* This may be redundant */ + pathbias_count_use_attempt(circuit); + hop = circuit->build_state->service_pending_final_cpath_ref->cpath; base16_encode(hexcookie,9,circuit->rend_data->rend_cookie,4); @@ -1741,9 +2598,9 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN); log_info(LD_REND, - "Done building circuit %d to rendezvous with " + "Done building circuit %u to rendezvous with " "cookie %s for service %s", - circuit->_base.n_circ_id, hexcookie, serviceid); + (unsigned)circuit->base_.n_circ_id, hexcookie, serviceid); /* Clear the 'in-progress HS circ has timed out' flag for * consistency with what happens on the client side; this line has @@ -1777,13 +2634,13 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */ memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN); - if (crypto_dh_get_public(hop->dh_handshake_state, + if (crypto_dh_get_public(hop->rend_dh_handshake_state, buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) { log_warn(LD_GENERAL,"Couldn't get DH public key."); reason = END_CIRC_REASON_INTERNAL; goto err; } - memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->handshake_digest, + memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->rend_circ_nonce, DIGEST_LEN); /* Send the cell */ @@ -1796,8 +2653,8 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) goto err; } - crypto_dh_free(hop->dh_handshake_state); - hop->dh_handshake_state = NULL; + crypto_dh_free(hop->rend_dh_handshake_state); + hop->rend_dh_handshake_state = NULL; /* Append the cpath entry. */ hop->state = CPATH_STATE_OPEN; @@ -1813,9 +2670,16 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) /* Change the circuit purpose. */ circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_REND_JOINED); - return; + goto done; + err: circuit_mark_for_close(TO_CIRCUIT(circuit), reason); + done: + memwipe(buf, 0, sizeof(buf)); + memwipe(serviceid, 0, sizeof(serviceid)); + memwipe(hexcookie, 0, sizeof(hexcookie)); + + return; } /* @@ -1876,7 +2740,7 @@ find_intro_point(origin_circuit_t *circ) if (service == NULL) return NULL; SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point, - if (crypto_pk_cmp_keys(intro_point->intro_key, circ->intro_key) == 0) { + if (crypto_pk_eq_keys(intro_point->intro_key, circ->intro_key)) { return intro_point; }); @@ -1912,7 +2776,7 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, char *hs_dir_ip; const node_t *node; hs_dir = smartlist_get(responsible_dirs, j); - if (smartlist_digest_isin(renddesc->successful_uploads, + if (smartlist_contains_digest(renddesc->successful_uploads, hs_dir->identity_digest)) /* Don't upload descriptor if we succeeded in doing so last time. */ continue; @@ -1929,7 +2793,8 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, directory_initiate_command_routerstatus(hs_dir, DIR_PURPOSE_UPLOAD_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, - 1, NULL, desc->desc_str, + DIRIND_ANONYMOUS, NULL, + desc->desc_str, strlen(desc->desc_str), 0); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc->desc_id, DIGEST_LEN); @@ -1946,7 +2811,8 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, 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)) + if (!smartlist_contains_digest(successful_uploads, + hs_dir->identity_digest)) smartlist_add(successful_uploads, hs_dir->identity_digest); } smartlist_clear(responsible_dirs); @@ -1964,7 +2830,7 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, if (!renddesc->successful_uploads) renddesc->successful_uploads = smartlist_new(); SMARTLIST_FOREACH(successful_uploads, const char *, c, { - if (!smartlist_digest_isin(renddesc->successful_uploads, c)) { + if (!smartlist_contains_digest(renddesc->successful_uploads, c)) { char *hsdir_id = tor_memdup(c, DIGEST_LEN); smartlist_add(renddesc->successful_uploads, hsdir_id); } @@ -2091,11 +2957,7 @@ upload_service_descriptor(rend_service_t *service) static int intro_point_accepted_intro_count(rend_intro_point_t *intro) { - if (intro->accepted_intro_rsa_parts == NULL) { - return 0; - } else { - return digestmap_size(intro->accepted_intro_rsa_parts); - } + return intro->accepted_introduce2_count; } /** Return non-zero iff <b>intro</b> should 'expire' now (i.e. we @@ -2201,7 +3063,8 @@ rend_services_introduce(void) if (intro->time_expiring + INTRO_POINT_EXPIRATION_GRACE_PERIOD > now) { /* This intro point has completely expired. Remove it, and * mark the circuit for close if it's still alive. */ - if (intro_circ != NULL) { + if (intro_circ != NULL && + intro_circ->base_.purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) { circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_FINISHED); } @@ -2299,7 +3162,7 @@ rend_services_introduce(void) j < (int)n_intro_points_to_open; ++j) { /* XXXX remove casts */ router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC; - if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION) + if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION) flags |= CRN_ALLOW_INVALID; node = router_choose_random_node(intro_nodes, options->ExcludeNodes, flags); @@ -2436,7 +3299,7 @@ rend_service_dump_stats(int severity) for (i=0; i < smartlist_len(rend_service_list); ++i) { service = smartlist_get(rend_service_list, i); - log(severity, LD_GENERAL, "Service configured in \"%s\":", + tor_log(severity, LD_GENERAL, "Service configured in \"%s\":", service->directory); for (j=0; j < smartlist_len(service->intro_nodes); ++j) { intro = smartlist_get(service->intro_nodes, j); @@ -2444,12 +3307,12 @@ rend_service_dump_stats(int severity) circ = find_intro_circuit(intro, service->pk_digest); if (!circ) { - log(severity, LD_GENERAL, " Intro point %d at %s: no circuit", + tor_log(severity, LD_GENERAL, " Intro point %d at %s: no circuit", j, safe_name); continue; } - log(severity, LD_GENERAL, " Intro point %d at %s: circuit is %s", - j, safe_name, circuit_state_to_string(circ->_base.state)); + tor_log(severity, LD_GENERAL, " Intro point %d at %s: circuit is %s", + j, safe_name, circuit_state_to_string(circ->base_.state)); } } } @@ -2468,7 +3331,7 @@ rend_service_set_connection_addr_port(edge_connection_t *conn, smartlist_t *matching_ports; rend_service_port_config_t *chosen_port; - tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_S_REND_JOINED); + tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED); tor_assert(circ->rend_data); log_debug(LD_REND,"beginning to hunt for addr/port"); base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, @@ -2477,26 +3340,26 @@ rend_service_set_connection_addr_port(edge_connection_t *conn, 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.", - serviceid, circ->_base.n_circ_id); + "rendezvous circuit %u; closing.", + serviceid, (unsigned)circ->base_.n_circ_id); return -1; } matching_ports = smartlist_new(); SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p, { - if (conn->_base.port == p->virtual_port) { + if (conn->base_.port == p->virtual_port) { smartlist_add(matching_ports, p); } }); chosen_port = smartlist_choose(matching_ports); smartlist_free(matching_ports); if (chosen_port) { - tor_addr_copy(&conn->_base.addr, &chosen_port->real_addr); - conn->_base.port = chosen_port->real_port; + tor_addr_copy(&conn->base_.addr, &chosen_port->real_addr); + conn->base_.port = chosen_port->real_port; return 0; } log_info(LD_REND, "No virtual port mapping exists for port %d on service %s", - conn->_base.port,serviceid); + conn->base_.port,serviceid); return -1; } diff --git a/src/or/rendservice.h b/src/or/rendservice.h index e5848785a8..caf88a3d64 100644 --- a/src/or/rendservice.h +++ b/src/or/rendservice.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,12 +9,68 @@ * \brief Header file for rendservice.c. **/ -#ifndef _TOR_RENDSERVICE_H -#define _TOR_RENDSERVICE_H +#ifndef TOR_RENDSERVICE_H +#define TOR_RENDSERVICE_H + +#include "or.h" + +typedef struct rend_intro_cell_s rend_intro_cell_t; + +#ifdef RENDSERVICE_PRIVATE + +/* This can be used for both INTRODUCE1 and INTRODUCE2 */ + +struct rend_intro_cell_s { + /* Is this an INTRODUCE1 or INTRODUCE2? (set to 1 or 2) */ + uint8_t type; + /* Public key digest */ + uint8_t pk[DIGEST_LEN]; + /* Optionally, store ciphertext here */ + uint8_t *ciphertext; + ssize_t ciphertext_len; + /* Optionally, store plaintext */ + uint8_t *plaintext; + ssize_t plaintext_len; + /* Have we parsed the plaintext? */ + uint8_t parsed; + /* intro protocol version (0, 1, 2 or 3) */ + uint8_t version; + /* Version-specific parts */ + union { + struct { + /* Rendezvous point nickname */ + uint8_t rp[20]; + } v0; + struct { + /* Rendezvous point nickname or hex-encoded key digest */ + uint8_t rp[42]; + } v1; + struct { + /* The extend_info_t struct has everything v2 uses */ + extend_info_t *extend_info; + } v2; + struct { + /* Auth type used */ + uint8_t auth_type; + /* Length of auth data */ + uint16_t auth_len; + /* Auth data */ + uint8_t *auth_data; + /* Rendezvous point's IP address/port, identity digest and onion key */ + extend_info_t *extend_info; + } v3; + } u; + /* Rendezvous cookie */ + uint8_t rc[REND_COOKIE_LEN]; + /* Diffie-Hellman data */ + uint8_t dh[DH_KEY_LEN]; +}; + +#endif int num_rend_services(void); int rend_config_services(const or_options_t *options, int validate_only); -int rend_service_load_keys(void); +int rend_service_load_all_keys(void); void rend_services_introduce(void); void rend_consider_services_upload(time_t now); void rend_hsdir_routers_changed(void); @@ -27,6 +83,21 @@ int rend_service_intro_established(origin_circuit_t *circuit, 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_compact_intro(rend_intro_cell_t *request); +int rend_service_decrypt_intro(rend_intro_cell_t *request, + crypto_pk_t *key, + char **err_msg_out); +void rend_service_free_intro(rend_intro_cell_t *request); +rend_intro_cell_t * rend_service_begin_parse_intro(const uint8_t *request, + size_t request_len, + uint8_t type, + char **err_msg_out); +int rend_service_parse_intro_plaintext(rend_intro_cell_t *intro, + char **err_msg_out); +int rend_service_validate_intro_early(const rend_intro_cell_t *intro, + char **err_msg_out); +int rend_service_validate_intro_late(const rend_intro_cell_t *intro, + char **err_msg_out); void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc); int rend_service_set_connection_addr_port(edge_connection_t *conn, origin_circuit_t *circ); diff --git a/src/or/rephist.c b/src/or/rephist.c index 3b0d9dd35f..2948bf8f00 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -160,7 +160,7 @@ get_link_history(const char *from_id, const char *to_id) /** Helper: free storage held by a single link history entry. */ static void -_free_link_history(void *val) +free_link_history_(void *val) { rephist_total_alloc -= sizeof(link_history_t); tor_free(val); @@ -171,7 +171,7 @@ static void free_or_history(void *_hist) { or_history_t *hist = _hist; - digestmap_free(hist->link_history_map, _free_link_history); + digestmap_free(hist->link_history_map, free_link_history_); rephist_total_alloc -= sizeof(or_history_t); rephist_total_num--; tor_free(hist); @@ -310,9 +310,10 @@ rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr, tor_assert(hist); tor_assert((!at_addr && !at_port) || (at_addr && at_port)); - addr_changed = at_addr && + addr_changed = at_addr && !tor_addr_is_null(&hist->last_reached_addr) && tor_addr_compare(at_addr, &hist->last_reached_addr, CMP_EXACT) != 0; - port_changed = at_port && at_port != hist->last_reached_port; + port_changed = at_port && hist->last_reached_port && + at_port != hist->last_reached_port; if (!started_tracking_stability) started_tracking_stability = time(NULL); @@ -422,6 +423,21 @@ rep_hist_note_router_unreachable(const char *id, time_t when) } } +/** Mark a router with ID <b>id</b> as non-Running, and retroactively declare + * that it has never been running: give it no stability and no WFU. */ +void +rep_hist_make_router_pessimal(const char *id, time_t when) +{ + or_history_t *hist = get_or_history(id); + tor_assert(hist); + + rep_hist_note_router_unreachable(id, when); + mark_or_down(hist, when, 1); + + hist->weighted_run_length = 0; + hist->weighted_uptime = 0; +} + /** Helper: Discount all old MTBF data, if it is time to do so. Return * the time at which we should next discount MTBF data. */ time_t @@ -648,7 +664,7 @@ rep_hist_dump_stats(time_t now, int severity) rep_history_clean(now - get_options()->RephistTrackTime); - log(severity, LD_HIST, "--------------- Dumping history information:"); + tor_log(severity, LD_HIST, "--------------- Dumping history information:"); for (orhist_it = digestmap_iter_init(history_map); !digestmap_iter_done(orhist_it); @@ -673,7 +689,7 @@ rep_hist_dump_stats(time_t now, int severity) } else { uptime=1.0; } - log(severity, LD_HIST, + tor_log(severity, LD_HIST, "OR %s [%s]: %ld/%ld good connections; uptime %ld/%ld sec (%.2f%%); " "wmtbf %lu:%02lu:%02lu", name1, hexdigest1, @@ -707,7 +723,7 @@ rep_hist_dump_stats(time_t now, int severity) else len += ret; } - log(severity, LD_HIST, "%s", buffer); + tor_log(severity, LD_HIST, "%s", buffer); } } } @@ -1136,7 +1152,7 @@ rep_hist_load_mtbf_data(time_t now) wfu_timebuf[0] = '\0'; if (format == 1) { - n = sscanf(line, "%40s %ld %lf S=%10s %8s", + n = tor_sscanf(line, "%40s %ld %lf S=%10s %8s", hexbuf, &wrl, &trw, mtbf_timebuf, mtbf_timebuf+11); if (n != 3 && n != 5) { log_warn(LD_HIST, "Couldn't scan line %s", escaped(line)); @@ -1153,7 +1169,7 @@ rep_hist_load_mtbf_data(time_t now) wfu_idx = find_next_with(lines, i+1, "+WFU "); if (mtbf_idx >= 0) { const char *mtbfline = smartlist_get(lines, mtbf_idx); - n = sscanf(mtbfline, "+MTBF %lu %lf S=%10s %8s", + n = tor_sscanf(mtbfline, "+MTBF %lu %lf S=%10s %8s", &wrl, &trw, mtbf_timebuf, mtbf_timebuf+11); if (n == 2 || n == 4) { have_mtbf = 1; @@ -1164,7 +1180,7 @@ rep_hist_load_mtbf_data(time_t now) } if (wfu_idx >= 0) { const char *wfuline = smartlist_get(lines, wfu_idx); - n = sscanf(wfuline, "+WFU %lu %lu S=%10s %8s", + n = tor_sscanf(wfuline, "+WFU %lu %lu S=%10s %8s", &wt_uptime, &total_wt_time, wfu_timebuf, wfu_timebuf+11); if (n == 2 || n == 4) { @@ -1531,10 +1547,10 @@ rep_hist_get_bandwidth_lines(void) const char *desc = NULL; size_t len; - /* opt [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */ + /* [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */ /* The n,n,n part above. Largest representation of a uint64_t is 20 chars * long, plus the comma. */ -#define MAX_HIST_VALUE_LEN 21*NUM_TOTALS +#define MAX_HIST_VALUE_LEN (21*NUM_TOTALS) len = (67+MAX_HIST_VALUE_LEN)*4; buf = tor_malloc_zero(len); cp = buf; @@ -2042,7 +2058,7 @@ note_crypto_pk_op(pk_op_t operation) void dump_pk_ops(int severity) { - log(severity, LD_HIST, + tor_log(severity, LD_HIST, "PK operations: %lu directory objects signed, " "%lu directory objects verified, " "%lu routerdescs signed, " @@ -2131,7 +2147,7 @@ rep_hist_exit_stats_term(void) * but works fine for sorting an array of port numbers, which is what we use * it for. */ static int -_compare_int(const void *x, const void *y) +compare_int_(const void *x, const void *y) { return (*(int*)x - *(int*)y); } @@ -2218,7 +2234,7 @@ rep_hist_format_exit_stats(time_t now) 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); + 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) { @@ -2440,7 +2456,7 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) /** 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) +buffer_stats_compare_entries_(const void **_a, const void **_b) { const circ_buffer_stats_t *a = *_a, *b = *_b; if (a->processed_cells < b->processed_cells) @@ -2505,7 +2521,7 @@ rep_hist_format_buffer_stats(time_t now) number_of_circuits = smartlist_len(circuits_for_buffer_stats); if (number_of_circuits > 0) { smartlist_sort(circuits_for_buffer_stats, - _buffer_stats_compare_entries); + buffer_stats_compare_entries_); i = 0; SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats, circ_buffer_stats_t *, stat) @@ -2590,7 +2606,7 @@ rep_hist_buffer_stats_write(time_t now) goto done; /* Not ready to write */ /* Add open circuits to the history. */ - for (circ = _circuit_get_global_list(); circ; circ = circ->next) { + for (circ = circuit_get_global_list_(); circ; circ = circ->next) { rep_hist_buffer_stats_add_circ(circ, now); } @@ -2995,6 +3011,46 @@ rep_hist_conn_stats_write(time_t now) return start_of_conn_stats_interval + WRITE_STATS_INTERVAL; } +/** Internal statistics to track how many requests of each type of + * handshake we've received, and how many we've completed. Useful for + * seeing trends in cpu load. + * @{ */ +static int onion_handshakes_requested[MAX_ONION_HANDSHAKE_TYPE+1] = {0}; +static int onion_handshakes_completed[MAX_ONION_HANDSHAKE_TYPE+1] = {0}; +/**@}*/ + +/** A new onionskin (using the <b>type</b> handshake) has arrived. */ +void +rep_hist_note_circuit_handshake_requested(uint16_t type) +{ + if (type <= MAX_ONION_HANDSHAKE_TYPE) + onion_handshakes_requested[type]++; +} + +/** We've sent an onionskin (using the <b>type</b> handshake) to a + * cpuworker. */ +void +rep_hist_note_circuit_handshake_completed(uint16_t type) +{ + if (type <= MAX_ONION_HANDSHAKE_TYPE) + onion_handshakes_completed[type]++; +} + +/** Log our onionskin statistics since the last time we were called. */ +void +rep_hist_log_circuit_handshake_stats(time_t now) +{ + (void)now; + log_notice(LD_HIST, "Circuit handshake stats since last time: " + "%d/%d TAP, %d/%d NTor.", + onion_handshakes_completed[ONION_HANDSHAKE_TYPE_TAP], + onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP], + onion_handshakes_completed[ONION_HANDSHAKE_TYPE_NTOR], + onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR]); + memset(onion_handshakes_completed, 0, sizeof(onion_handshakes_completed)); + memset(onion_handshakes_requested, 0, sizeof(onion_handshakes_requested)); +} + /** Free all storage held by the OR/link history caches, by the * bandwidth history arrays, by the port history, or by statistics . */ void @@ -3003,6 +3059,8 @@ rep_hist_free_all(void) digestmap_free(history_map, free_or_history); tor_free(read_array); tor_free(write_array); + tor_free(dir_read_array); + tor_free(dir_write_array); tor_free(last_stability_doc); tor_free(exit_bytes_read); tor_free(exit_bytes_written); diff --git a/src/or/rephist.h b/src/or/rephist.h index d47724edb5..de824749b4 100644 --- a/src/or/rephist.h +++ b/src/or/rephist.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for rephist.c. **/ -#ifndef _TOR_REPHIST_H -#define _TOR_REPHIST_H +#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); @@ -24,6 +24,8 @@ 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_make_router_pessimal(const char *id, 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); @@ -62,8 +64,6 @@ 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); @@ -96,5 +96,11 @@ char *rep_hist_format_conn_stats(time_t now); time_t rep_hist_conn_stats_write(time_t now); void rep_hist_conn_stats_term(void); +void rep_hist_note_circuit_handshake_requested(uint16_t type); +void rep_hist_note_circuit_handshake_completed(uint16_t type); +void rep_hist_log_circuit_handshake_stats(time_t now); + +void rep_hist_free_all(void); + #endif diff --git a/src/or/replaycache.c b/src/or/replaycache.c new file mode 100644 index 0000000000..59b98489b7 --- /dev/null +++ b/src/or/replaycache.c @@ -0,0 +1,215 @@ + /* Copyright (c) 2012-2013, The Tor Project, Inc. */ + /* See LICENSE for licensing information */ + +/* + * \file replaycache.c + * + * \brief Self-scrubbing replay cache for rendservice.c + */ + +#define REPLAYCACHE_PRIVATE + +#include "or.h" +#include "replaycache.h" + +/** Free the replaycache r and all of its entries. + */ + +void +replaycache_free(replaycache_t *r) +{ + if (!r) { + log_info(LD_BUG, "replaycache_free() called on NULL"); + return; + } + + if (r->digests_seen) digestmap_free(r->digests_seen, tor_free_); + + tor_free(r); +} + +/** Allocate a new, empty replay detection cache, where horizon is the time + * for entries to age out and interval is the time after which the cache + * should be scrubbed for old entries. + */ + +replaycache_t * +replaycache_new(time_t horizon, time_t interval) +{ + replaycache_t *r = NULL; + + if (horizon < 0) { + log_info(LD_BUG, "replaycache_new() called with negative" + " horizon parameter"); + goto err; + } + + if (interval < 0) { + log_info(LD_BUG, "replaycache_new() called with negative interval" + " parameter"); + interval = 0; + } + + r = tor_malloc(sizeof(*r)); + r->scrub_interval = interval; + r->scrubbed = 0; + r->horizon = horizon; + r->digests_seen = digestmap_new(); + + err: + return r; +} + +/** See documentation for replaycache_add_and_test() + */ + +int +replaycache_add_and_test_internal( + time_t present, replaycache_t *r, const void *data, int len, + time_t *elapsed) +{ + int rv = 0; + char digest[DIGEST_LEN]; + time_t *access_time; + + /* sanity check */ + if (present <= 0 || !r || !data || len <= 0) { + log_info(LD_BUG, "replaycache_add_and_test_internal() called with stupid" + " parameters; please fix this."); + goto done; + } + + /* compute digest */ + crypto_digest(digest, (const char *)data, len); + + /* check map */ + access_time = digestmap_get(r->digests_seen, digest); + + /* seen before? */ + if (access_time != NULL) { + /* + * If it's far enough in the past, no hit. If the horizon is zero, we + * never expire. + */ + if (*access_time >= present - r->horizon || r->horizon == 0) { + /* replay cache hit, return 1 */ + rv = 1; + /* If we want to output an elapsed time, do so */ + if (elapsed) { + if (present >= *access_time) { + *elapsed = present - *access_time; + } else { + /* We shouldn't really be seeing hits from the future, but... */ + *elapsed = 0; + } + } + } + /* + * If it's ahead of the cached time, update + */ + if (*access_time < present) { + *access_time = present; + } + } else { + /* No, so no hit and update the digest map with the current time */ + access_time = tor_malloc(sizeof(*access_time)); + *access_time = present; + digestmap_set(r->digests_seen, digest, access_time); + } + + /* now scrub the cache if it's time */ + replaycache_scrub_if_needed_internal(present, r); + + done: + return rv; +} + +/** See documentation for replaycache_scrub_if_needed() + */ + +void +replaycache_scrub_if_needed_internal(time_t present, replaycache_t *r) +{ + digestmap_iter_t *itr = NULL; + const char *digest; + void *valp; + time_t *access_time; + char scrub_this; + + /* sanity check */ + if (!r || !(r->digests_seen)) { + log_info(LD_BUG, "replaycache_scrub_if_needed_internal() called with" + " stupid parameters; please fix this."); + return; + } + + /* scrub time yet? (scrubbed == 0 indicates never scrubbed before) */ + if (present - r->scrubbed < r->scrub_interval && r->scrubbed > 0) return; + + /* if we're never expiring, don't bother scrubbing */ + if (r->horizon == 0) return; + + /* okay, scrub time */ + itr = digestmap_iter_init(r->digests_seen); + while (!digestmap_iter_done(itr)) { + scrub_this = 0; + digestmap_iter_get(itr, &digest, &valp); + access_time = (time_t *)valp; + if (access_time) { + /* aged out yet? */ + if (*access_time < present - r->horizon) scrub_this = 1; + } else { + /* Buh? Get rid of it, anyway */ + log_info(LD_BUG, "replaycache_scrub_if_needed_internal() saw a NULL" + " entry in the digestmap."); + scrub_this = 1; + } + + if (scrub_this) { + /* Advance the iterator and remove this one */ + itr = digestmap_iter_next_rmv(r->digests_seen, itr); + /* Free the value removed */ + tor_free(access_time); + } else { + /* Just advance the iterator */ + itr = digestmap_iter_next(r->digests_seen, itr); + } + } + + /* update scrubbed timestamp */ + if (present > r->scrubbed) r->scrubbed = present; +} + +/** Test the buffer of length len point to by data against the replay cache r; + * the digest of the buffer will be added to the cache at the current time, + * and the function will return 1 if it was already seen within the cache's + * horizon, or 0 otherwise. + */ + +int +replaycache_add_and_test(replaycache_t *r, const void *data, int len) +{ + return replaycache_add_and_test_internal(time(NULL), r, data, len, NULL); +} + +/** Like replaycache_add_and_test(), but if it's a hit also return the time + * elapsed since this digest was last seen. + */ + +int +replaycache_add_test_and_elapsed( + replaycache_t *r, const void *data, int len, time_t *elapsed) +{ + return replaycache_add_and_test_internal(time(NULL), r, data, len, elapsed); +} + +/** Scrub aged entries out of r if sufficiently long has elapsed since r was + * last scrubbed. + */ + +void +replaycache_scrub_if_needed(replaycache_t *r) +{ + replaycache_scrub_if_needed_internal(time(NULL), r); +} + diff --git a/src/or/replaycache.h b/src/or/replaycache.h new file mode 100644 index 0000000000..de20cab627 --- /dev/null +++ b/src/or/replaycache.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file replaycache.h + * \brief Header file for replaycache.c. + **/ + +#ifndef TOR_REPLAYCACHE_H +#define TOR_REPLAYCACHE_H + +typedef struct replaycache_s replaycache_t; + +#ifdef REPLAYCACHE_PRIVATE + +struct replaycache_s { + /* Scrub interval */ + time_t scrub_interval; + /* Last scrubbed */ + time_t scrubbed; + /* + * Horizon + * (don't return true on digests in the cache but older than this) + */ + time_t horizon; + /* + * Digest map: keys are digests, values are times the digest was last seen + */ + digestmap_t *digests_seen; +}; + +#endif /* REPLAYCACHE_PRIVATE */ + +/* replaycache_t free/new */ + +void replaycache_free(replaycache_t *r); +replaycache_t * replaycache_new(time_t horizon, time_t interval); + +#ifdef REPLAYCACHE_PRIVATE + +/* + * replaycache_t internal functions: + * + * These take the time to treat as the present as an argument for easy unit + * testing. For everything else, use the wrappers below instead. + */ + +int replaycache_add_and_test_internal( + time_t present, replaycache_t *r, const void *data, int len, + time_t *elapsed); +void replaycache_scrub_if_needed_internal( + time_t present, replaycache_t *r); + +#endif /* REPLAYCACHE_PRIVATE */ + +/* + * replaycache_t methods + */ + +int replaycache_add_and_test(replaycache_t *r, const void *data, int len); +int replaycache_add_test_and_elapsed( + replaycache_t *r, const void *data, int len, time_t *elapsed); +void replaycache_scrub_if_needed(replaycache_t *r); + +#endif + diff --git a/src/or/router.c b/src/or/router.c index a3459aec71..eabd9c3f59 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define ROUTER_PRIVATE @@ -13,6 +13,7 @@ #include "config.h" #include "connection.h" #include "control.h" +#include "crypto_curve25519.h" #include "directory.h" #include "dirserv.h" #include "dns.h" @@ -27,6 +28,9 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "statefile.h" +#include "transports.h" +#include "routerset.h" /** * \file router.c @@ -51,6 +55,13 @@ static crypto_pk_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_t *lastonionkey=NULL; +#ifdef CURVE25519_ENABLED +/** Current private ntor secret key: used to perform the ntor handshake. */ +static curve25519_keypair_t curve25519_onion_key; +/** Previous private ntor secret key: used to perform the ntor handshake + * with clients that have an older version of our descriptor. */ +static curve25519_keypair_t last_curve25519_onion_key; +#endif /** Private server "identity key": used to sign directory info and TLS * certificates. Never changes. */ static crypto_pk_t *server_identitykey=NULL; @@ -84,7 +95,7 @@ static authority_cert_t *legacy_key_certificate = NULL; static void set_onion_key(crypto_pk_t *k) { - if (onionkey && !crypto_pk_cmp_keys(onionkey, k)) { + if (onionkey && crypto_pk_eq_keys(onionkey, k)) { /* k is already our onion key; free it and return */ crypto_pk_free(k); return; @@ -123,6 +134,55 @@ dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last) tor_mutex_release(key_lock); } +#ifdef CURVE25519_ENABLED +/** Return the current secret onion key for the ntor handshake. Must only + * be called from the main thread. */ +static const curve25519_keypair_t * +get_current_curve25519_keypair(void) +{ + return &curve25519_onion_key; +} +/** Return a map from KEYID (the key itself) to keypairs for use in the ntor + * handshake. Must only be called from the main thread. */ +di_digest256_map_t * +construct_ntor_key_map(void) +{ + di_digest256_map_t *m = NULL; + + dimap_add_entry(&m, + curve25519_onion_key.pubkey.public_key, + tor_memdup(&curve25519_onion_key, + sizeof(curve25519_keypair_t))); + if (!tor_mem_is_zero((const char*) + last_curve25519_onion_key.pubkey.public_key, + CURVE25519_PUBKEY_LEN)) { + dimap_add_entry(&m, + last_curve25519_onion_key.pubkey.public_key, + tor_memdup(&last_curve25519_onion_key, + sizeof(curve25519_keypair_t))); + } + + return m; +} +/** Helper used to deallocate a di_digest256_map_t returned by + * construct_ntor_key_map. */ +static void +ntor_key_map_free_helper(void *arg) +{ + curve25519_keypair_t *k = arg; + memwipe(k, 0, sizeof(*k)); + tor_free(k); +} +/** Release all storage from a keymap returned by construct_ntor_key_map. */ +void +ntor_key_map_free(di_digest256_map_t *map) +{ + if (!map) + return; + dimap_free(map, ntor_key_map_free_helper); +} +#endif + /** Return the time when the onion key was last set. This is either the time * when the process launched, or the time of the most recent key rotation since * the process launched. @@ -152,12 +212,11 @@ assert_identity_keys_ok(void) 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)); + tor_assert(crypto_pk_eq_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)); + tor_assert(!crypto_pk_eq_keys(client_identitykey, server_identitykey)); } } @@ -251,11 +310,18 @@ void rotate_onion_key(void) { char *fname, *fname_prev; - crypto_pk_t *prkey; + crypto_pk_t *prkey = NULL; or_state_t *state = get_or_state(); +#ifdef CURVE25519_ENABLED + curve25519_keypair_t new_curve25519_keypair; +#endif time_t now; fname = get_datadir_fname2("keys", "secret_onion_key"); fname_prev = get_datadir_fname2("keys", "secret_onion_key.old"); + if (file_status(fname) == FN_FILE) { + if (replace_file(fname, fname_prev)) + goto error; + } if (!(prkey = crypto_pk_new())) { log_err(LD_GENERAL,"Error constructing rotated onion key"); goto error; @@ -264,19 +330,38 @@ rotate_onion_key(void) log_err(LD_BUG,"Error generating onion key"); goto error; } + if (crypto_pk_write_private_key_to_filename(prkey, fname)) { + log_err(LD_FS,"Couldn't write generated onion key to \"%s\".", fname); + goto error; + } +#ifdef CURVE25519_ENABLED + tor_free(fname); + tor_free(fname_prev); + fname = get_datadir_fname2("keys", "secret_onion_key_ntor"); + fname_prev = get_datadir_fname2("keys", "secret_onion_key_ntor.old"); + if (curve25519_keypair_generate(&new_curve25519_keypair, 1) < 0) + goto error; if (file_status(fname) == FN_FILE) { if (replace_file(fname, fname_prev)) goto error; } - if (crypto_pk_write_private_key_to_filename(prkey, fname)) { - log_err(LD_FS,"Couldn't write generated onion key to \"%s\".", fname); + if (curve25519_keypair_write_to_file(&new_curve25519_keypair, fname, + "onion") < 0) { + log_err(LD_FS,"Couldn't write curve25519 onion key to \"%s\".",fname); goto error; } +#endif log_info(LD_GENERAL, "Rotating onion key"); tor_mutex_acquire(key_lock); crypto_pk_free(lastonionkey); lastonionkey = onionkey; onionkey = prkey; +#ifdef CURVE25519_ENABLED + memcpy(&last_curve25519_onion_key, &curve25519_onion_key, + sizeof(curve25519_keypair_t)); + memcpy(&curve25519_onion_key, &new_curve25519_keypair, + sizeof(curve25519_keypair_t)); +#endif now = time(NULL); state->LastRotatedOnionKey = onionkey_set_at = now; tor_mutex_release(key_lock); @@ -288,6 +373,9 @@ rotate_onion_key(void) if (prkey) crypto_pk_free(prkey); done: +#ifdef CURVE25519_ENABLED + memwipe(&new_curve25519_keypair, 0, sizeof(new_curve25519_keypair)); +#endif tor_free(fname); tor_free(fname_prev); } @@ -303,14 +391,14 @@ init_key_from_file(const char *fname, int generate, int severity) crypto_pk_t *prkey = NULL; if (!(prkey = crypto_pk_new())) { - log(severity, LD_GENERAL,"Error constructing key"); + tor_log(severity, LD_GENERAL,"Error constructing key"); goto error; } switch (file_status(fname)) { case FN_DIR: case FN_ERROR: - log(severity, LD_FS,"Can't read key from \"%s\"", fname); + tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname); goto error; case FN_NOENT: if (generate) { @@ -318,8 +406,8 @@ init_key_from_file(const char *fname, int generate, int severity) if (try_locking(get_options(), 0)<0) { /* Make sure that --list-fingerprint only creates new keys * if there is no possibility for a deadlock. */ - log(severity, LD_FS, "Another Tor process has locked \"%s\". Not " - "writing any new keys.", fname); + tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". " + "Not writing any new keys.", fname); /*XXXX The 'other process' might make a key in a second or two; * maybe we should wait for it. */ goto error; @@ -328,16 +416,16 @@ init_key_from_file(const char *fname, int generate, int severity) log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.", fname); if (crypto_pk_generate_key(prkey)) { - log(severity, LD_GENERAL,"Error generating onion key"); + tor_log(severity, LD_GENERAL,"Error generating onion key"); goto error; } if (crypto_pk_check_key(prkey) <= 0) { - log(severity, LD_GENERAL,"Generated key seems invalid"); + tor_log(severity, LD_GENERAL,"Generated key seems invalid"); goto error; } log_info(LD_GENERAL, "Generated key seems valid"); if (crypto_pk_write_private_key_to_filename(prkey, fname)) { - log(severity, LD_FS, + tor_log(severity, LD_FS, "Couldn't write generated key to \"%s\".", fname); goto error; } @@ -347,7 +435,7 @@ init_key_from_file(const char *fname, int generate, int severity) return prkey; case FN_FILE: if (crypto_pk_read_private_key_from_filename(prkey, fname)) { - log(severity, LD_GENERAL,"Error loading private key."); + tor_log(severity, LD_GENERAL,"Error loading private key."); goto error; } return prkey; @@ -361,6 +449,77 @@ init_key_from_file(const char *fname, int generate, int severity) return NULL; } +#ifdef CURVE25519_ENABLED +/** Load a curve25519 keypair from the file <b>fname</b>, writing it into + * <b>keys_out</b>. If the file isn't found and <b>generate</b> is true, + * create a new keypair and write it into the file. If there are errors, log + * them at level <b>severity</b>. Generate files using <b>tag</b> in their + * ASCII wrapper. */ +static int +init_curve25519_keypair_from_file(curve25519_keypair_t *keys_out, + const char *fname, + int generate, + int severity, + const char *tag) +{ + switch (file_status(fname)) { + case FN_DIR: + case FN_ERROR: + tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname); + goto error; + case FN_NOENT: + if (generate) { + if (!have_lockfile()) { + if (try_locking(get_options(), 0)<0) { + /* Make sure that --list-fingerprint only creates new keys + * if there is no possibility for a deadlock. */ + tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". " + "Not writing any new keys.", fname); + /*XXXX The 'other process' might make a key in a second or two; + * maybe we should wait for it. */ + goto error; + } + } + log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.", + fname); + if (curve25519_keypair_generate(keys_out, 1) < 0) + goto error; + if (curve25519_keypair_write_to_file(keys_out, fname, tag)<0) { + tor_log(severity, LD_FS, + "Couldn't write generated key to \"%s\".", fname); + memset(keys_out, 0, sizeof(*keys_out)); + goto error; + } + } else { + log_info(LD_GENERAL, "No key found in \"%s\"", fname); + } + return 0; + case FN_FILE: + { + char *tag_in=NULL; + if (curve25519_keypair_read_from_file(keys_out, &tag_in, fname) < 0) { + tor_log(severity, LD_GENERAL,"Error loading private key."); + tor_free(tag_in); + goto error; + } + if (!tag_in || strcmp(tag_in, tag)) { + tor_log(severity, LD_GENERAL,"Unexpected tag %s on private key.", + escaped(tag_in)); + tor_free(tag_in); + goto error; + } + tor_free(tag_in); + return 0; + } + default: + tor_assert(0); + } + + error: + return -1; +} +#endif + /** Try to load the vote-signing private key and certificate for being a v3 * directory authority, and make sure they match. If <b>legacy</b>, load a * legacy key/cert set for emergency key migration; otherwise load the regular @@ -397,7 +556,7 @@ load_authority_keyset(int legacy, crypto_pk_t **key_out, log_warn(LD_DIR, "Unable to parse certificate in %s", fname); goto done; } - if (crypto_pk_cmp_keys(signing_key, parsed->signing_key) != 0) { + if (!crypto_pk_eq_keys(signing_key, parsed->signing_key)) { log_warn(LD_DIR, "Stored signing key does not match signing key in " "certificate"); goto done; @@ -472,14 +631,14 @@ v3_authority_check_key_expiry(void) return; if (time_left <= 0) { - log(badness, LD_DIR, "Your v3 authority certificate has expired." - " Generate a new one NOW."); + tor_log(badness, LD_DIR, "Your v3 authority certificate has expired." + " Generate a new one NOW."); } else if (time_left <= 24*60*60) { - log(badness, LD_DIR, "Your v3 authority certificate expires in %d hours;" - " Generate a new one NOW.", time_left/(60*60)); + tor_log(badness, LD_DIR, "Your v3 authority certificate expires in %d " + "hours; Generate a new one NOW.", time_left/(60*60)); } else { - log(badness, LD_DIR, "Your v3 authority certificate expires in %d days;" - " Generate a new one soon.", time_left/(24*60*60)); + tor_log(badness, LD_DIR, "Your v3 authority certificate expires in %d " + "days; Generate a new one soon.", time_left/(24*60*60)); } last_warned = now; } @@ -489,11 +648,39 @@ v3_authority_check_key_expiry(void) int router_initialize_tls_context(void) { - return tor_tls_context_init(public_server_mode(get_options()), + unsigned int flags = 0; + const or_options_t *options = get_options(); + int lifetime = options->SSLKeyLifetime; + if (public_server_mode(options)) + flags |= TOR_TLS_CTX_IS_PUBLIC_SERVER; + if (options->TLSECGroup) { + if (!strcasecmp(options->TLSECGroup, "P256")) + flags |= TOR_TLS_CTX_USE_ECDHE_P256; + else if (!strcasecmp(options->TLSECGroup, "P224")) + flags |= TOR_TLS_CTX_USE_ECDHE_P224; + } + if (!lifetime) { /* we should guess a good ssl cert lifetime */ + + /* choose between 5 and 365 days, and round to the day */ + lifetime = 5*24*3600 + crypto_rand_int(361*24*3600); + lifetime -= lifetime % (24*3600); + + if (crypto_rand_int(2)) { + /* Half the time we expire at midnight, and half the time we expire + * one second before midnight. (Some CAs wobble their expiry times a + * bit in practice, perhaps to reduce collision attacks; see ticket + * 8443 for details about observed certs in the wild.) */ + lifetime--; + } + } + + /* It's ok to pass lifetime in as an unsigned int, since + * config_parse_interval() checked it. */ + return tor_tls_context_init(flags, get_tlsclient_identity_key(), - server_mode(get_options()) ? + server_mode(options) ? get_server_identity_key() : NULL, - MAX_SSL_KEY_LIFETIME_ADVERTISED); + (unsigned int)lifetime); } /** Initialize all OR private keys, and the TLS context, as necessary. @@ -515,7 +702,7 @@ init_keys(void) const or_options_t *options = get_options(); dirinfo_type_t type; time_t now = time(NULL); - trusted_dir_server_t *ds; + dir_server_t *ds; int v3_digest_set = 0; authority_cert_t *cert = NULL; @@ -628,12 +815,35 @@ init_keys(void) keydir = get_datadir_fname2("keys", "secret_onion_key.old"); if (!lastonionkey && file_status(keydir) == FN_FILE) { - prkey = init_key_from_file(keydir, 1, LOG_ERR); + prkey = init_key_from_file(keydir, 1, LOG_ERR); /* XXXX Why 1? */ if (prkey) lastonionkey = prkey; } tor_free(keydir); +#ifdef CURVE25519_ENABLED + { + /* 2b. Load curve25519 onion keys. */ + int r; + keydir = get_datadir_fname2("keys", "secret_onion_key_ntor"); + r = init_curve25519_keypair_from_file(&curve25519_onion_key, + keydir, 1, LOG_ERR, "onion"); + tor_free(keydir); + if (r<0) + return -1; + + keydir = get_datadir_fname2("keys", "secret_onion_key_ntor.old"); + if (tor_mem_is_zero((const char *) + last_curve25519_onion_key.pubkey.public_key, + CURVE25519_PUBKEY_LEN) && + file_status(keydir) == FN_FILE) { + init_curve25519_keypair_from_file(&last_curve25519_onion_key, + keydir, 0, LOG_ERR, "onion"); + } + tor_free(keydir); + } +#endif + /* 3. Initialize link key and TLS context. */ if (router_initialize_tls_context() < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); @@ -671,7 +881,7 @@ init_keys(void) * we don't really need new keys yet so the descriptor doesn't * change and the old one is still fresh. */ log_info(LD_GENERAL, "Couldn't add own descriptor to directory " - "after key init: %s. This is usually not a problem.", + "after key init: %s This is usually not a problem.", m?m:"<unknown error>"); } } @@ -709,7 +919,7 @@ init_keys(void) tor_free(cp); tor_free(keydir); - log(LOG_NOTICE, LD_GENERAL, + log_notice(LD_GENERAL, "Your Tor server's identity key fingerprint is '%s %s'", options->Nickname, fingerprint); if (!authdir_mode(options)) @@ -730,35 +940,37 @@ init_keys(void) ds = router_get_trusteddirserver_by_digest(digest); if (!ds) { - ds = add_trusted_dir_server(options->Nickname, NULL, + ds = trusted_dir_server_new(options->Nickname, NULL, router_get_advertised_dir_port(options, 0), router_get_advertised_or_port(options), digest, v3_digest, - type); + type, 0.0); if (!ds) { log_err(LD_GENERAL,"We want to be a directory authority, but we " "couldn't add ourselves to the authority list. Failing."); return -1; } + dir_server_add(ds); } if (ds->type != type) { log_warn(LD_DIR, "Configured authority type does not match authority " - "type in DirServer list. Adjusting. (%d v %d)", + "type in DirAuthority list. Adjusting. (%d v %d)", type, ds->type); ds->type = type; } if (v3_digest_set && (ds->type & V3_DIRINFO) && tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "V3 identity key does not match identity declared in " - "DirServer line. Adjusting."); + "DirAuthority line. Adjusting."); memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN); } if (cert) { /* add my own cert to the list of known certs */ log_info(LD_DIR, "adding my own v3 cert"); if (trusted_dirs_load_certs_from_string( - cert->cache_info.signed_descriptor_body, 0, 0)<0) { + cert->cache_info.signed_descriptor_body, + TRUSTED_DIRS_CERTS_SRC_SELF, 0)<0) { log_warn(LD_DIR, "Unable to parse my own v3 cert! Failing."); return -1; } @@ -868,10 +1080,10 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) if (advertising != new_choice) { if (new_choice == 1) { - log(LOG_NOTICE, LD_DIR, "Advertising DirPort as %d", dir_port); + log_notice(LD_DIR, "Advertising DirPort as %d", dir_port); } else { tor_assert(reason); - log(LOG_NOTICE, LD_DIR, "Not advertising DirPort (Reason: %s)", reason); + log_notice(LD_DIR, "Not advertising DirPort (Reason: %s)", reason); } advertising = new_choice; } @@ -879,6 +1091,22 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) return advertising ? dir_port : 0; } +/** Allocate and return a new extend_info_t that can be used to build + * a circuit to or through the router <b>r</b>. Use the primary + * address of the router unless <b>for_direct_connect</b> is true, in + * which case the preferred address is used instead. */ +static extend_info_t * +extend_info_from_router(const routerinfo_t *r) +{ + tor_addr_port_t ap; + tor_assert(r); + + router_get_prim_orport(r, &ap); + return extend_info_new(r->nickname, r->cache_info.identity_digest, + r->onion_pkey, r->onion_curve25519_pkey, + &ap.addr, ap.port); +} + /** Some time has passed, or we just got new directory information. * See if we currently believe our ORPort or DirPort to be * unreachable. If so, launch a new test for it. @@ -907,25 +1135,21 @@ consider_testing_reachability(int test_or, int test_dir) if (test_or || test_dir) { #define SELF_EXCLUDED_WARN_INTERVAL 3600 static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL); - char *msg; - if ((msg = rate_limit_log(&warning_limit, approx_time()))) { - log_warn(LD_CIRC, "Can't peform self-tests for this relay: we have " + log_fn_ratelim(&warning_limit, LOG_WARN, LD_CIRC, + "Can't peform self-tests for this relay: we have " "listed ourself in ExcludeNodes, and StrictNodes is set. " "We cannot learn whether we are usable, and will not " - "be able to advertise ourself.%s", msg); - tor_free(msg); - } + "be able to advertise ourself."); } return; } if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) { - extend_info_t *ei; + extend_info_t *ei = extend_info_from_router(me); + /* XXX IPv6 self testing */ log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.", !orport_reachable ? "reachability" : "bandwidth", me->address, me->or_port); - /* XXX IPv6 self testing IPv6 orports will need pref_addr */ - ei = extend_info_from_router(me, 0); circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei, CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL); extend_info_free(ei); @@ -939,11 +1163,10 @@ consider_testing_reachability(int test_or, int test_dir) /* ask myself, via tor, for my server descriptor. */ directory_initiate_command(me->address, &addr, me->or_port, me->dir_port, - 0, /* does not matter */ - 0, me->cache_info.identity_digest, + me->cache_info.identity_digest, DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_GENERAL, - 1, "authority.z", NULL, 0, 0); + DIRIND_ANON_DIRPORT, "authority.z", NULL, 0, 0); } } @@ -955,7 +1178,7 @@ router_orport_found_reachable(void) if (!can_reach_or_port && me) { log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from " "the outside. Excellent.%s", - get_options()->_PublishServerDescriptor != NO_DIRINFO ? + get_options()->PublishServerDescriptor_ != NO_DIRINFO ? " Publishing server descriptor." : ""); can_reach_or_port = 1; mark_my_descriptor_dirty("ORPort found reachable"); @@ -987,7 +1210,8 @@ router_dirport_found_reachable(void) void router_perform_bandwidth_test(int num_circs, time_t now) { - int num_cells = (int)(get_options()->BandwidthRate * 10 / CELL_NETWORK_SIZE); + int num_cells = (int)(get_options()->BandwidthRate * 10 / + CELL_MAX_NETWORK_SIZE); int max_cells = num_cells < CIRCWINDOW_START ? num_cells : CIRCWINDOW_START; int cells_per_circuit = max_cells / num_circs; @@ -998,9 +1222,9 @@ router_perform_bandwidth_test(int num_circs, time_t now) CIRCUIT_PURPOSE_TESTING))) { /* dump cells_per_circuit drop cells onto this circ */ int i = cells_per_circuit; - if (circ->_base.state != CIRCUIT_STATE_OPEN) + if (circ->base_.state != CIRCUIT_STATE_OPEN) continue; - circ->_base.timestamp_dirty = now; + circ->base_.timestamp_dirty = now; while (i-- > 0) { if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), RELAY_COMMAND_DROP, @@ -1194,7 +1418,7 @@ decide_if_publishable_server(void) if (options->ClientOnly) return 0; - if (options->_PublishServerDescriptor == NO_DIRINFO) + if (options->PublishServerDescriptor_ == NO_DIRINFO) return 0; if (!server_mode(options)) return 0; @@ -1236,13 +1460,18 @@ consider_publishable_server(int force) /** XXX not a very good interface. it's not reliable when there are multiple listeners. */ uint16_t -router_get_active_listener_port_by_type(int listener_type) +router_get_active_listener_port_by_type_af(int listener_type, + sa_family_t family) { /* Iterate all connections, find one of the right kind and return the port. Not very sophisticated or fast, but effective. */ - const connection_t *c = connection_get_by_type(listener_type); - if (c) - return c->port; + smartlist_t *conns = get_connection_array(); + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { + if (conn->type == listener_type && !conn->marked_for_close && + conn->socket_family == family) { + return conn->port; + } + } SMARTLIST_FOREACH_END(conn); return 0; } @@ -1254,13 +1483,24 @@ router_get_active_listener_port_by_type(int listener_type) uint16_t router_get_advertised_or_port(const or_options_t *options) { - int port = get_primary_or_port(); + return router_get_advertised_or_port_by_af(options, AF_INET); +} + +/** As router_get_advertised_or_port(), but allows an address family argument. + */ +uint16_t +router_get_advertised_or_port_by_af(const or_options_t *options, + sa_family_t family) +{ + int port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER, + family); (void)options; /* If the port is in 'auto' mode, we have to use router_get_listener_port_by_type(). */ if (port == CFG_AUTO_PORT) - return router_get_active_listener_port_by_type(CONN_TYPE_OR_LISTENER); + return router_get_active_listener_port_by_type_af(CONN_TYPE_OR_LISTENER, + family); return port; } @@ -1280,7 +1520,8 @@ router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) return dirport; if (dirport_configured == CFG_AUTO_PORT) - return router_get_active_listener_port_by_type(CONN_TYPE_DIR_LISTENER); + return router_get_active_listener_port_by_type_af(CONN_TYPE_DIR_LISTENER, + AF_INET); return dirport_configured; } @@ -1315,7 +1556,7 @@ router_upload_dir_desc_to_dirservers(int force) extrainfo_t *ei; char *msg; size_t desc_len, extra_len = 0, total_len; - dirinfo_type_t auth = get_options()->_PublishServerDescriptor; + dirinfo_type_t auth = get_options()->PublishServerDescriptor_; ri = router_get_my_routerinfo(); if (!ri) { @@ -1355,22 +1596,34 @@ router_upload_dir_desc_to_dirservers(int force) * conn. Return 0 if we accept; non-0 if we reject. */ int -router_compare_to_my_exit_policy(edge_connection_t *conn) +router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port) { if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */ return -1; /* make sure it's resolved to something. this way we can't get a 'maybe' below. */ - if (tor_addr_is_null(&conn->_base.addr)) + if (tor_addr_is_null(addr)) return -1; - /* XXXX IPv6 */ - if (tor_addr_family(&conn->_base.addr) != AF_INET) + /* look at desc_routerinfo->exit_policy for both the v4 and the v6 + * policies. The exit_policy field in desc_routerinfo is a bit unusual, + * in that it contains IPv6 and IPv6 entries. We don't want to look + * at desc_routerinfio->ipv6_exit_policy, since that's a port summary. */ + if ((tor_addr_family(addr) == AF_INET || + tor_addr_family(addr) == AF_INET6)) { + return compare_tor_addr_to_addr_policy(addr, port, + desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; +#if 0 + } else if (tor_addr_family(addr) == AF_INET6) { + return get_options()->IPv6Exit && + desc_routerinfo->ipv6_exit_policy && + compare_tor_addr_to_short_policy(addr, port, + desc_routerinfo->ipv6_exit_policy) != ADDR_POLICY_ACCEPTED; +#endif + } else { return -1; - - return compare_tor_addr_to_addr_policy(&conn->_base.addr, conn->_base.port, - desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; + } } /** Return true iff my exit policy is reject *:*. Return -1 if we don't @@ -1393,6 +1646,13 @@ router_digest_is_me(const char *digest) tor_memeq(server_identitykey_digest, digest, DIGEST_LEN)); } +/** Return my identity digest. */ +const uint8_t * +router_get_my_id_digest(void) +{ + return (const uint8_t *)server_identitykey_digest; +} + /** Return true iff I'm a server and <b>digest</b> is equal to * my identity digest. */ int @@ -1488,7 +1748,9 @@ static int router_guess_address_from_dir_headers(uint32_t *guess); int router_pick_published_address(const or_options_t *options, uint32_t *addr) { - if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) { + *addr = get_last_resolved_addr(); + if (!*addr && + resolve_my_address(LOG_INFO, options, addr, NULL, NULL) < 0) { log_info(LD_CONFIG, "Could not determine our address locally. " "Checking if directory headers provide any hints."); if (router_guess_address_from_dir_headers(addr) < 0) { @@ -1539,13 +1801,19 @@ 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 */ - if (options->BridgeRelay) { - /* For now, only bridges advertise an ipv6 or-address. And only one. */ +#ifdef CURVE25519_ENABLED + ri->onion_curve25519_pkey = + tor_memdup(&get_current_curve25519_keypair()->pubkey, + sizeof(curve25519_public_key_t)); +#endif + + /* For now, at most one IPv6 or-address is being advertised. */ + { const port_cfg_t *ipv6_orport = NULL; SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) { if (p->type == CONN_TYPE_OR_LISTENER && ! p->no_advertise && - ! p->ipv4_only && + ! p->bind_ipv4_only && tor_addr_family(&p->addr) == AF_INET6) { if (! tor_addr_is_internal(&p->addr, 0)) { ipv6_orport = p; @@ -1565,6 +1833,7 @@ router_rebuild_descriptor(int force) ri->ipv6_orport = ipv6_orport->port; } } + 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) { @@ -1587,11 +1856,20 @@ router_rebuild_descriptor(int force) policies_exit_policy_append_reject_star(&ri->exit_policy); } else { policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy, + options->IPv6Exit, options->ExitPolicyRejectPrivate, ri->address, !options->BridgeRelay); } ri->policy_is_reject_star = - policy_is_reject_star(ri->exit_policy); + policy_is_reject_star(ri->exit_policy, AF_INET) && + policy_is_reject_star(ri->exit_policy, AF_INET6); + + if (options->IPv6Exit) { + char *p_tmp = policy_summarize(ri->exit_policy, AF_INET6); + if (p_tmp) + ri->ipv6_exit_policy = parse_short_policy(p_tmp); + tor_free(p_tmp); + } #if 0 /* XXXX NM NM I belive this is safe to remove */ @@ -1615,7 +1893,7 @@ router_rebuild_descriptor(int force) member = node_get_by_nickname(name, 1); if (!member) { int is_legal = is_legal_nickname_or_hexdigest(name); - if (!smartlist_string_isin(warned_nonexistent_family, name) && + if (!smartlist_contains_string(warned_nonexistent_family, name) && !is_legal_hexdigest(name)) { if (is_legal) log_warn(LD_CONFIG, @@ -1641,7 +1919,7 @@ router_rebuild_descriptor(int force) base16_encode(fp+1,HEX_DIGEST_LEN+1, member->identity, DIGEST_LEN); smartlist_add(ri->declared_family, fp); - if (smartlist_string_isin(warned_nonexistent_family, name)) + if (smartlist_contains_string(warned_nonexistent_family, name)) smartlist_string_remove(warned_nonexistent_family, name); } skip: @@ -1684,9 +1962,8 @@ router_rebuild_descriptor(int force) /* 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_server_identity_key()) < 0) { + if (! (ri->cache_info.signed_descriptor_body = router_dump_router_to_string( + ri, get_server_identity_key()))) { log_warn(LD_BUG, "Couldn't generate router descriptor."); routerinfo_free(ri); extrainfo_free(ei); @@ -1783,7 +2060,7 @@ void mark_my_descriptor_dirty(const char *reason) { const or_options_t *options = get_options(); - if (server_mode(options) && options->_PublishServerDescriptor) + if (server_mode(options) && options->PublishServerDescriptor_) log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason); desc_clean_since = 0; if (!desc_dirty_reason) @@ -1853,6 +2130,9 @@ check_descriptor_ipaddress_changed(time_t now) { uint32_t prev, cur; const or_options_t *options = get_options(); + const char *method = NULL; + char *hostname = NULL; + (void) now; if (!desc_routerinfo) @@ -1860,18 +2140,29 @@ check_descriptor_ipaddress_changed(time_t now) /* XXXX ipv6 */ prev = desc_routerinfo->addr; - if (resolve_my_address(LOG_INFO, options, &cur, NULL) < 0) { + if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) { log_info(LD_CONFIG,"options->Address didn't resolve into an IP."); return; } if (prev != cur) { + char *source; tor_addr_t tmp_prev, tmp_cur; + tor_addr_from_ipv4h(&tmp_prev, prev); tor_addr_from_ipv4h(&tmp_cur, cur); - log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, "resolve"); + + tor_asprintf(&source, "METHOD=%s%s%s", method, + hostname ? " HOSTNAME=" : "", + hostname ? hostname : ""); + + log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, source); + tor_free(source); + ip_address_changed(0); } + + tor_free(hostname); } /** The most recently guessed value of our IP address, based on directory @@ -1905,7 +2196,9 @@ router_new_address_suggestion(const char *suggestion, } /* XXXX ipv6 */ - if (resolve_my_address(LOG_INFO, options, &cur, NULL) >= 0) { + cur = get_last_resolved_addr(); + if (cur || + resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) { /* We're all set -- we already know our address. Great. */ tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we need it later */ @@ -1915,7 +2208,7 @@ router_new_address_suggestion(const char *suggestion, /* Don't believe anybody who says our IP is, say, 127.0.0.1. */ return; } - if (tor_addr_eq(&d_conn->_base.addr, &addr)) { + if (tor_addr_eq(&d_conn->base_.addr, &addr)) { /* Don't believe anybody who says our IP is their IP. */ log_debug(LD_DIR, "A directory server told us our IP address is %s, " "but he's just reporting his own IP address. Ignoring.", @@ -1931,7 +2224,7 @@ router_new_address_suggestion(const char *suggestion, "EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV", suggestion); log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr, - d_conn->_base.address); + d_conn->base_.address); ip_address_changed(0); tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor() will fetch it */ @@ -1970,55 +2263,54 @@ get_platform_str(char *platform, size_t len) #define DEBUG_ROUTER_DUMP_ROUTER_TO_STRING /** OR only: Given a routerinfo for this router, and an identity key to sign - * with, encode the routerinfo as a signed server descriptor and write the - * result into <b>s</b>, using at most <b>maxlen</b> bytes. Return -1 on - * failure, and the number of bytes used on success. + * with, encode the routerinfo as a signed server descriptor and return a new + * string encoding the result, or NULL on failure. */ -int -router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, +char * +router_dump_router_to_string(routerinfo_t *router, crypto_pk_t *ident_key) { - char *onion_pkey; /* Onion key, PEM-encoded. */ - char *identity_pkey; /* Identity key, PEM-encoded. */ + /* XXXX025 Make this look entirely at its arguments, and not at globals. + */ + char *onion_pkey = NULL; /* Onion key, PEM-encoded. */ + char *identity_pkey = NULL; /* Identity key, PEM-encoded. */ 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; - int result=0; - addr_policy_t *tmpe; - char *family_line; + char *family_line = NULL; char *extra_or_address = NULL; const or_options_t *options = get_options(); + smartlist_t *chunks = NULL; + char *output = NULL; /* Make sure the identity key matches the one in the routerinfo. */ - if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) { + if (!crypto_pk_eq_keys(ident_key, router->identity_pkey)) { log_warn(LD_BUG,"Tried to sign a router with a private key that didn't " "match router's public key!"); - return -1; + goto err; } /* record our fingerprint, so we can include it in the descriptor */ if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 1)<0) { log_err(LD_BUG,"Error computing fingerprint"); - return -1; + goto err; } /* PEM-encode the onion key */ if (crypto_pk_write_public_key_to_string(router->onion_pkey, &onion_pkey,&onion_pkeylen)<0) { log_warn(LD_BUG,"write onion_pkey to string failed!"); - return -1; + goto err; } /* 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!"); - tor_free(onion_pkey); - return -1; + goto err; } /* Encode the publication time. */ @@ -2053,14 +2345,15 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, } } + chunks = smartlist_new(); /* Generate the easy portion of the router descriptor. */ - result = tor_snprintf(s, maxlen, + smartlist_add_asprintf(chunks, "router %s %s %d 0 %d\n" "%s" "platform %s\n" - "opt protocols Link 1 2 Circuit 1\n" + "protocols Link 1 2 Circuit 1\n" "published %s\n" - "opt fingerprint %s\n" + "fingerprint %s\n" "uptime %ld\n" "bandwidth %d %d %d\n" "%s%s%s%s" @@ -2079,113 +2372,115 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, (int) router->bandwidthrate, (int) router->bandwidthburst, (int) router->bandwidthcapacity, - has_extra_info_digest ? "opt extra-info-digest " : "", + has_extra_info_digest ? "extra-info-digest " : "", has_extra_info_digest ? extra_info_digest : "", has_extra_info_digest ? "\n" : "", - options->DownloadExtraInfo ? "opt caches-extra-info\n" : "", + options->DownloadExtraInfo ? "caches-extra-info\n" : "", onion_pkey, identity_pkey, family_line, - we_are_hibernating() ? "opt hibernating 1\n" : "", - options->HidServDirectoryV2 ? "opt hidden-service-dir\n" : "", - options->AllowSingleHopExits ? "opt allow-single-hop-exits\n" : ""); - - tor_free(family_line); - tor_free(onion_pkey); - tor_free(identity_pkey); - tor_free(extra_or_address); - - if (result < 0) { - log_warn(LD_BUG,"descriptor snprintf #1 ran out of room!"); - return -1; - } - /* From now on, we use 'written' to remember the current length of 's'. */ - written = result; + we_are_hibernating() ? "hibernating 1\n" : "", + options->HidServDirectoryV2 ? "hidden-service-dir\n" : "", + options->AllowSingleHopExits ? "allow-single-hop-exits\n" : ""); if (options->ContactInfo && strlen(options->ContactInfo)) { const char *ci = options->ContactInfo; if (strchr(ci, '\n') || strchr(ci, '\r')) ci = escaped(ci); - result = tor_snprintf(s+written,maxlen-written, "contact %s\n", ci); - if (result<0) { - log_warn(LD_BUG,"descriptor snprintf #2 ran out of room!"); - return -1; - } - written += result; + smartlist_add_asprintf(chunks, "contact %s\n", ci); } +#ifdef CURVE25519_ENABLED + if (router->onion_curve25519_pkey) { + char kbuf[128]; + base64_encode(kbuf, sizeof(kbuf), + (const char *)router->onion_curve25519_pkey->public_key, + CURVE25519_PUBKEY_LEN); + smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf); + } +#endif + /* Write the exit policy to the end of 's'. */ if (!router->exit_policy || !smartlist_len(router->exit_policy)) { - strlcat(s+written, "reject *:*\n", maxlen-written); - written += strlen("reject *:*\n"); - tmpe = NULL; + smartlist_add(chunks, tor_strdup("reject *:*\n")); } else if (router->exit_policy) { int i; for (i = 0; i < smartlist_len(router->exit_policy); ++i) { - tmpe = smartlist_get(router->exit_policy, i); - result = policy_write_item(s+written, maxlen-written, tmpe, 1); + char pbuf[POLICY_BUF_LEN]; + addr_policy_t *tmpe = smartlist_get(router->exit_policy, i); + int result; + if (tor_addr_family(&tmpe->addr) == AF_INET6) + continue; /* Don't include IPv6 parts of address policy */ + result = policy_write_item(pbuf, POLICY_BUF_LEN, tmpe, 1); if (result < 0) { log_warn(LD_BUG,"descriptor policy_write_item ran out of room!"); - return -1; - } - tor_assert(result == (int)strlen(s+written)); - written += result; - if (written+2 > maxlen) { - log_warn(LD_BUG,"descriptor policy_write_item ran out of room (2)!"); - return -1; + goto err; } - s[written++] = '\n'; + smartlist_add_asprintf(chunks, "%s\n", pbuf); } } - 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; + if (router->ipv6_exit_policy) { + char *p6 = write_short_policy(router->ipv6_exit_policy); + if (p6 && strcmp(p6, "reject 1-65535")) { + smartlist_add_asprintf(chunks, + "ipv6-policy %s\n", p6); + } + tor_free(p6); } /* Sign the descriptor */ - strlcpy(s+written, "router-signature\n", maxlen-written); - written += strlen(s+written); - s[written] = '\0'; - if (router_get_router_hash(s, strlen(s), digest) < 0) { - return -1; - } + smartlist_add(chunks, tor_strdup("router-signature\n")); + + crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1); note_crypto_pk_op(SIGN_RTR); - if (router_append_dirobj_signature(s+written,maxlen-written, - digest,DIGEST_LEN,ident_key)<0) { - log_warn(LD_BUG, "Couldn't sign router descriptor"); - return -1; + { + char *sig; + if (!(sig = router_get_dirobj_signature(digest, DIGEST_LEN, ident_key))) { + log_warn(LD_BUG, "Couldn't sign router descriptor"); + goto err; + } + smartlist_add(chunks, sig); } - written += strlen(s+written); - if (written+2 > maxlen) { - log_warn(LD_BUG,"Not enough room to finish descriptor."); - return -1; - } /* include a last '\n' */ - s[written] = '\n'; - s[written+1] = 0; + smartlist_add(chunks, tor_strdup("\n")); + + output = smartlist_join_strings(chunks, "", 0, NULL); #ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING { char *s_dup; const char *cp; routerinfo_t *ri_tmp; - cp = s_dup = tor_strdup(s); + cp = s_dup = tor_strdup(output); ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL); if (!ri_tmp) { log_err(LD_BUG, "We just generated a router descriptor we can't parse."); - log_err(LD_BUG, "Descriptor was: <<%s>>", s); - return -1; + log_err(LD_BUG, "Descriptor was: <<%s>>", output); + goto err; } tor_free(s_dup); routerinfo_free(ri_tmp); } #endif - return (int)written+1; + goto done; + + err: + tor_free(output); /* sets output to NULL */ + done: + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + } + tor_free(family_line); + tor_free(onion_pkey); + tor_free(identity_pkey); + tor_free(extra_or_address); + + return output; } /** Copy the primary (IPv4) OR port (IP address and TCP port) for @@ -2198,40 +2493,24 @@ router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out) ap_out->port = router->or_port; } -/** Return 1 if we prefer the IPv6 address and OR TCP port of - * <b>router</b>, else 0. - * - * We prefer the IPv6 address if the router has one and - * i) the routerinfo_t says so - * or - * ii) the router has no IPv4 address. */ +/** Return 1 if any of <b>router</b>'s addresses are <b>addr</b>. + * Otherwise return 0. */ int -router_ipv6_preferred(const routerinfo_t *router) +router_has_addr(const routerinfo_t *router, const tor_addr_t *addr) { - return (!tor_addr_is_null(&router->ipv6_addr) - && (router->ipv6_preferred || router->addr == 0)); -} - -/** Copy the preferred OR port (IP address and TCP port) for - * <b>router</b> into *<b>addr_out</b>. */ -void -router_get_pref_orport(const routerinfo_t *router, tor_addr_port_t *ap_out) -{ - if (router_ipv6_preferred(router)) - router_get_pref_ipv6_orport(router, ap_out); - else - router_get_prim_orport(router, ap_out); + return + tor_addr_eq_ipv4h(addr, router->addr) || + tor_addr_eq(&router->ipv6_addr, addr); } -/** Copy the preferred IPv6 OR port (IP address and TCP port) for - * <b>router</b> into *<b>ap_out</b>. */ -void -router_get_pref_ipv6_orport(const routerinfo_t *router, - tor_addr_port_t *ap_out) +int +router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport) { - tor_assert(ap_out != NULL); - tor_addr_copy(&ap_out->addr, &router->ipv6_addr); - ap_out->port = router->ipv6_orport; + return + (tor_addr_eq_ipv4h(&orport->addr, router->addr) && + orport->port == router->or_port) || + (tor_addr_eq(&orport->addr, &router->ipv6_addr) && + orport->port == router->ipv6_orport); } /** Load the contents of <b>filename</b>, find the last line starting with @@ -2316,9 +2595,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, tor_free(bandwidth_usage); smartlist_add(chunks, pre); - if (geoip_is_loaded()) { - smartlist_add_asprintf(chunks, "geoip-db-digest %s\n", geoip_db_digest()); - } + if (geoip_is_loaded(AF_INET)) + smartlist_add_asprintf(chunks, "geoip-db-digest %s\n", + geoip_db_digest(AF_INET)); + if (geoip_is_loaded(AF_INET6)) + smartlist_add_asprintf(chunks, "geoip6-db-digest %s\n", + geoip_db_digest(AF_INET6)); if (options->ExtraInfoStatistics && write_stats_to_extrainfo) { log_info(LD_GENERAL, "Adding stats to extra-info descriptor."); @@ -2349,6 +2631,13 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, } } + /* Add information about the pluggable transports we support. */ + if (options->ServerTransportPlugin) { + char *pluggable_transports = pt_get_extra_info_descriptor_string(); + if (pluggable_transports) + smartlist_add(chunks, pluggable_transports); + } + if (should_record_bridge_info(options) && write_stats_to_extrainfo) { const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now); if (bridge_stats) { @@ -2431,7 +2720,9 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, return result; } -/** Return true iff <b>s</b> is a legally valid server nickname. */ +/** Return true iff <b>s</b> is a valid server nickname. (That is, a string + * containing between 1 and MAX_NICKNAME_LEN characters from + * LEGAL_NICKNAME_CHARACTERS.) */ int is_legal_nickname(const char *s) { @@ -2442,7 +2733,7 @@ is_legal_nickname(const char *s) strspn(s,LEGAL_NICKNAME_CHARACTERS) == len; } -/** Return true iff <b>s</b> is a legally valid server nickname or +/** Return true iff <b>s</b> is a valid server nickname or * hex-encoded identity-key digest. */ int is_legal_nickname_or_hexdigest(const char *s) @@ -2453,8 +2744,11 @@ is_legal_nickname_or_hexdigest(const char *s) return is_legal_hexdigest(s); } -/** Return true iff <b>s</b> is a legally valid hex-encoded identity-key - * digest. */ +/** Return true iff <b>s</b> is a valid hex-encoded identity-key + * digest. (That is, an optional $, followed by 40 hex characters, + * followed by either nothing, or = or ~ followed by a nickname, or + * a character other than =, ~, or a hex character.) + */ int is_legal_hexdigest(const char *s) { @@ -2677,23 +2971,6 @@ router_get_verbose_nickname(char *buf, const routerinfo_t *router) strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1); } -/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the - * verbose representation of the identity of <b>router</b>. The format is: - * A dollar sign. - * The upper-case hexadecimal encoding of the SHA1 hash of router's identity. - * A "=" if the router is named; a "~" if it is not. - * The router's nickname. - **/ -void -routerstatus_get_verbose_nickname(char *buf, const routerstatus_t *router) -{ - buf[0] = '$'; - base16_encode(buf+1, HEX_DIGEST_LEN+1, router->identity_digest, - DIGEST_LEN); - buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~'; - strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1); -} - /** Forget that we have issued any router-related warnings, so that we'll * warn again if we see the same errors. */ void @@ -2752,9 +3029,41 @@ router_free_all(void) crypto_pk_free(legacy_signing_key); authority_cert_free(legacy_key_certificate); +#ifdef CURVE25519_ENABLED + memwipe(&curve25519_onion_key, 0, sizeof(curve25519_onion_key)); + memwipe(&last_curve25519_onion_key, 0, sizeof(last_curve25519_onion_key)); +#endif + if (warned_nonexistent_family) { SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp)); smartlist_free(warned_nonexistent_family); } } +/** Return a smartlist of tor_addr_port_t's with all the OR ports of + <b>ri</b>. Note that freeing of the items in the list as well as + the smartlist itself is the callers responsibility. + + XXX duplicating code from node_get_all_orports(). */ +smartlist_t * +router_get_all_orports(const routerinfo_t *ri) +{ + smartlist_t *sl = smartlist_new(); + tor_assert(ri); + + if (ri->addr != 0) { + tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); + tor_addr_from_ipv4h(&ap->addr, ri->addr); + ap->port = ri->or_port; + smartlist_add(sl, ap); + } + if (!tor_addr_is_null(&ri->ipv6_addr)) { + tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); + tor_addr_copy(&ap->addr, &ri->ipv6_addr); + ap->port = ri->or_port; + smartlist_add(sl, ap); + } + + return sl; +} + diff --git a/src/or/router.h b/src/or/router.h index 69805d6f2d..60095d087b 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,8 +9,8 @@ * \brief Header file for router.c. **/ -#ifndef _TOR_ROUTER_H -#define _TOR_ROUTER_H +#ifndef TOR_ROUTER_H +#define TOR_ROUTER_H crypto_pk_t *get_onion_key(void); time_t get_onion_key_set_at(void); @@ -30,6 +30,11 @@ crypto_pk_t *init_key_from_file(const char *fname, int generate, int severity); void v3_authority_check_key_expiry(void); +#ifdef CURVE25519_ENABLED +di_digest256_map_t *construct_ntor_key_map(void); +void ntor_key_map_free(di_digest256_map_t *map); +#endif + int router_initialize_tls_context(void); int init_keys(void); @@ -53,8 +58,11 @@ int authdir_mode_publishes_statuses(const or_options_t *options); int authdir_mode_tests_reachability(const or_options_t *options); int authdir_mode_bridge(const or_options_t *options); -uint16_t router_get_active_listener_port_by_type(int listener_type); +uint16_t router_get_active_listener_port_by_type_af(int listener_type, + sa_family_t family); uint16_t router_get_advertised_or_port(const or_options_t *options); +uint16_t router_get_advertised_or_port_by_af(const or_options_t *options, + sa_family_t family); uint16_t router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport); @@ -72,20 +80,21 @@ 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_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port); int router_my_exit_policy_is_reject_star(void); const routerinfo_t *router_get_my_routerinfo(void); extrainfo_t *router_get_my_extrainfo(void); const char *router_get_my_descriptor(void); const char *router_get_descriptor_gen_reason(void); int router_digest_is_me(const char *digest); +const uint8_t *router_get_my_id_digest(void); int router_extrainfo_digest_is_me(const char *digest); int router_is_me(const routerinfo_t *router); int router_fingerprint_is_me(const char *fp); int router_pick_published_address(const or_options_t *options, uint32_t *addr); int router_rebuild_descriptor(int force); -int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, - crypto_pk_t *ident_key); +char *router_dump_router_to_string(routerinfo_t *router, + crypto_pk_t *ident_key); void router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *addr_port_out); void router_get_pref_orport(const routerinfo_t *router, @@ -93,6 +102,9 @@ void router_get_pref_orport(const routerinfo_t *router, void router_get_pref_ipv6_orport(const routerinfo_t *router, tor_addr_port_t *addr_port_out); int router_ipv6_preferred(const routerinfo_t *router); +int router_has_addr(const routerinfo_t *router, const tor_addr_t *addr); +int router_has_orport(const routerinfo_t *router, + const tor_addr_port_t *orport); int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo, crypto_pk_t *ident_key); int is_legal_nickname(const char *s); @@ -123,8 +135,6 @@ const char *routerstatus_describe(const routerstatus_t *ri); const char *extend_info_describe(const extend_info_t *ei); void router_get_verbose_nickname(char *buf, const routerinfo_t *router); -void routerstatus_get_verbose_nickname(char *buf, - const routerstatus_t *router); void router_reset_warnings(void); void router_reset_reachability(void); void router_free_all(void); @@ -132,6 +142,8 @@ void router_free_all(void); const char *router_purpose_to_string(uint8_t p); uint8_t router_purpose_from_string(const char *s); +smartlist_t *router_get_all_orports(const routerinfo_t *ri); + #ifdef ROUTER_PRIVATE /* Used only by router.c and test.c */ void get_platform_str(char *platform, size_t len); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 9e59c332a1..8fe496b51e 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,14 +11,17 @@ * servers. **/ +#define ROUTERLIST_PRIVATE #include "or.h" -#include "circuitbuild.h" +#include "circuitstats.h" #include "config.h" #include "connection.h" #include "control.h" #include "directory.h" #include "dirserv.h" #include "dirvote.h" +#include "entrynodes.h" +#include "fp_pair.h" #include "geoip.h" #include "hibernate.h" #include "main.h" @@ -33,55 +36,81 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "routerset.h" // #define DEBUG_ROUTERLIST /****************************************************************************/ +DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t) +DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t) +DECLARE_TYPED_DIGESTMAP_FNS(eimap_, digest_ei_map_t, extrainfo_t) +DECLARE_TYPED_DIGESTMAP_FNS(dsmap_, digest_ds_map_t, download_status_t) +#define SDMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(sdmap_to_digestmap(map), keyvar, signed_descriptor_t *, \ + valvar) +#define RIMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(rimap_to_digestmap(map), keyvar, routerinfo_t *, valvar) +#define EIMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(eimap_to_digestmap(map), keyvar, extrainfo_t *, valvar) +#define DSMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(dsmap_to_digestmap(map), keyvar, download_status_t *, \ + valvar) + +/* Forward declaration for cert_list_t */ +typedef struct cert_list_t cert_list_t; + /* static function prototypes */ +static int compute_weighted_bandwidths(const smartlist_t *sl, + bandwidth_weight_rule_t rule, + u64_dbl_t **bandwidths_out); static const routerstatus_t *router_pick_directory_server_impl( dirinfo_type_t auth, int flags); static const routerstatus_t *router_pick_trusteddirserver_impl( - dirinfo_type_t auth, int flags, int *n_busy_out); -static void mark_all_trusteddirservers_up(void); -static int router_nickname_matches(const routerinfo_t *router, - const char *nickname); -static int node_nickname_matches(const node_t *router, - const char *nickname); -static void trusted_dir_server_free(trusted_dir_server_t *ds); + const smartlist_t *sourcelist, dirinfo_type_t auth, + int flags, int *n_busy_out); +static const routerstatus_t *router_pick_dirserver_generic( + smartlist_t *sourcelist, + dirinfo_type_t type, int flags); +static void mark_all_dirservers_up(smartlist_t *server_list); +static void dir_server_free(dir_server_t *ds); 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( const signed_descriptor_t *desc, int with_annotations); static void list_pending_downloads(digestmap_t *result, int purpose, const char *prefix); +static void list_pending_fpsk_downloads(fp_pair_map_t *result); static void launch_dummy_descriptor_download_as_needed(time_t now, const or_options_t *options); - -DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t) -DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t) -DECLARE_TYPED_DIGESTMAP_FNS(eimap_, digest_ei_map_t, extrainfo_t) -#define SDMAP_FOREACH(map, keyvar, valvar) \ - DIGESTMAP_FOREACH(sdmap_to_digestmap(map), keyvar, signed_descriptor_t *, \ - valvar) -#define RIMAP_FOREACH(map, keyvar, valvar) \ - DIGESTMAP_FOREACH(rimap_to_digestmap(map), keyvar, routerinfo_t *, valvar) -#define EIMAP_FOREACH(map, keyvar, valvar) \ - DIGESTMAP_FOREACH(eimap_to_digestmap(map), keyvar, extrainfo_t *, valvar) +static void download_status_reset_by_sk_in_cl(cert_list_t *cl, + const char *digest); +static int download_status_is_ready_by_sk_in_cl(cert_list_t *cl, + const char *digest, + time_t now, int max_failures); /****************************************************************************/ -/** Global list of a trusted_dir_server_t object for each trusted directory - * server. */ +/** Global list of a dir_server_t object for each directory + * authority. */ static smartlist_t *trusted_dir_servers = NULL; +/** Global list of dir_server_t objects for all directory authorities + * and all fallback directory servers. */ +static smartlist_t *fallback_dir_servers = NULL; /** List of for a given authority, and download status for latest certificate. */ -typedef struct cert_list_t { - download_status_t dl_status; +struct cert_list_t { + /* + * The keys of download status map are cert->signing_key_digest for pending + * downloads by (identity digest/signing key digest) pair; functions such + * as authority_cert_get_by_digest() already assume these are unique. + */ + struct digest_ds_map_t *dl_status_map; + /* There is also a dlstatus for the download by identity key only */ + download_status_t dl_status_by_id; smartlist_t *certs; -} cert_list_t; +}; /** Map from v3 identity key digest to cert_list_t. */ static digestmap_t *trusted_dir_certs = NULL; /** True iff any key certificate in at least one member of @@ -119,12 +148,78 @@ get_n_authorities(dirinfo_type_t type) int n = 0; if (!trusted_dir_servers) return 0; - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, + SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ds, if (ds->type & type) ++n); return n; } +/** Reset the download status of a specified element in a dsmap */ +static void +download_status_reset_by_sk_in_cl(cert_list_t *cl, const char *digest) +{ + download_status_t *dlstatus = NULL; + + tor_assert(cl); + tor_assert(digest); + + /* Make sure we have a dsmap */ + if (!(cl->dl_status_map)) { + cl->dl_status_map = dsmap_new(); + } + /* Look for a download_status_t in the map with this digest */ + dlstatus = dsmap_get(cl->dl_status_map, digest); + /* Got one? */ + if (!dlstatus) { + /* Insert before we reset */ + dlstatus = tor_malloc_zero(sizeof(*dlstatus)); + dsmap_set(cl->dl_status_map, digest, dlstatus); + } + tor_assert(dlstatus); + /* Go ahead and reset it */ + download_status_reset(dlstatus); +} + +/** + * Return true if the download for this signing key digest in cl is ready + * to be re-attempted. + */ +static int +download_status_is_ready_by_sk_in_cl(cert_list_t *cl, + const char *digest, + time_t now, int max_failures) +{ + int rv = 0; + download_status_t *dlstatus = NULL; + + tor_assert(cl); + tor_assert(digest); + + /* Make sure we have a dsmap */ + if (!(cl->dl_status_map)) { + cl->dl_status_map = dsmap_new(); + } + /* Look for a download_status_t in the map with this digest */ + dlstatus = dsmap_get(cl->dl_status_map, digest); + /* Got one? */ + if (dlstatus) { + /* Use download_status_is_ready() */ + rv = download_status_is_ready(dlstatus, now, max_failures); + } else { + /* + * If we don't know anything about it, return 1, since we haven't + * tried this one before. We need to create a new entry here, + * too. + */ + dlstatus = tor_malloc_zero(sizeof(*dlstatus)); + download_status_reset(dlstatus); + dsmap_set(cl->dl_status_map, digest, dlstatus); + rv = 1; + } + + return rv; +} + #define get_n_v2_authorities() get_n_authorities(V2_DIRINFO) /** Helper: Return the cert_list_t for an authority whose authority ID is @@ -138,13 +233,35 @@ get_cert_list(const char *id_digest) cl = digestmap_get(trusted_dir_certs, id_digest); if (!cl) { cl = tor_malloc_zero(sizeof(cert_list_t)); - cl->dl_status.schedule = DL_SCHED_CONSENSUS; + cl->dl_status_by_id.schedule = DL_SCHED_CONSENSUS; cl->certs = smartlist_new(); + cl->dl_status_map = dsmap_new(); digestmap_set(trusted_dir_certs, id_digest, cl); } return cl; } +/** Release all space held by a cert_list_t */ +static void +cert_list_free(cert_list_t *cl) +{ + if (!cl) + return; + + SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert, + authority_cert_free(cert)); + smartlist_free(cl->certs); + dsmap_free(cl->dl_status_map, tor_free_); + tor_free(cl); +} + +/** Wrapper for cert_list_free so we can pass it to digestmap_free */ +static void +cert_list_free_(void *cl) +{ + cert_list_free(cl); +} + /** Reload the cached v3 key certificates from the cached-certs file in * the data directory. Return 0 on success, -1 on failure. */ int @@ -159,7 +276,9 @@ trusted_dirs_reload_certs(void) tor_free(filename); if (!contents) return 0; - r = trusted_dirs_load_certs_from_string(contents, 1, 1); + r = trusted_dirs_load_certs_from_string( + contents, + TRUSTED_DIRS_CERTS_SRC_FROM_STORE, 1); tor_free(contents); return r; } @@ -182,17 +301,23 @@ 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>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. */ + * <b>source</b> is TRUSTED_DIRS_CERTS_SRC_FROM_STORE, the certificates are + * from the cache, and we don't need to flush them to disk. If we are a + * dirauth loading our own cert, source is TRUSTED_DIRS_CERTS_SRC_SELF. + * Otherwise, source is download type: TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST + * or TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST. 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, +trusted_dirs_load_certs_from_string(const char *contents, int source, int flush) { - trusted_dir_server_t *ds; + dir_server_t *ds; const char *s, *eos; int failure_code = 0; + int from_store = (source == TRUSTED_DIRS_CERTS_SRC_FROM_STORE); for (s = contents; *s; s = eos) { authority_cert_t *cert = authority_cert_parse_from_string(s, &eos); @@ -213,9 +338,13 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, from_store ? "cached" : "downloaded", 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. */ + /* + * A duplicate on download should be treated as a failure, so we call + * authority_cert_dl_failed() to reset the download status to make sure + * we can't try again. Since we've implemented the fp-sk mechanism + * to download certs by signing key, this should be much rarer than it + * was and is perhaps cause for concern. + */ if (!from_store) { if (authdir_mode(get_options())) { log_warn(LD_DIR, @@ -229,7 +358,18 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store, ds ? ds->nickname : "an old or new authority"); } - authority_cert_dl_failed(cert->cache_info.identity_digest, 404); + /* + * This is where we care about the source; authority_cert_dl_failed() + * needs to know whether the download was by fp or (fp,sk) pair to + * twiddle the right bit in the download map. + */ + if (source == TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST) { + authority_cert_dl_failed(cert->cache_info.identity_digest, + NULL, 404); + } else if (source == TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST) { + authority_cert_dl_failed(cert->cache_info.identity_digest, + cert->signing_key_digest, 404); + } } authority_cert_free(cert); @@ -329,7 +469,6 @@ trusted_dirs_remove_old_certs(void) time_t now = time(NULL); #define DEAD_CERT_LIFETIME (2*24*60*60) #define OLD_CERT_LIFETIME (7*24*60*60) -#define CERT_EXPIRY_SKEW (60*60) if (!trusted_dir_certs) return; @@ -445,17 +584,53 @@ authority_cert_get_all(smartlist_t *certs_out) } /** Called when an attempt to download a certificate with the authority with - * ID <b>id_digest</b> fails with HTTP response code <b>status</b>: remember - * the failure, so we don't try again immediately. */ + * ID <b>id_digest</b> and, if not NULL, signed with key signing_key_digest + * fails with HTTP response code <b>status</b>: remember the failure, so we + * don't try again immediately. */ void -authority_cert_dl_failed(const char *id_digest, int status) +authority_cert_dl_failed(const char *id_digest, + const char *signing_key_digest, int status) { cert_list_t *cl; + download_status_t *dlstatus = NULL; + char id_digest_str[2*DIGEST_LEN+1]; + char sk_digest_str[2*DIGEST_LEN+1]; + if (!trusted_dir_certs || !(cl = digestmap_get(trusted_dir_certs, id_digest))) return; - download_status_failed(&cl->dl_status, status); + /* + * Are we noting a failed download of the latest cert for the id digest, + * or of a download by (id, signing key) digest pair? + */ + if (!signing_key_digest) { + /* Just by id digest */ + download_status_failed(&cl->dl_status_by_id, status); + } else { + /* Reset by (id, signing key) digest pair + * + * Look for a download_status_t in the map with this digest + */ + dlstatus = dsmap_get(cl->dl_status_map, signing_key_digest); + /* Got one? */ + if (dlstatus) { + download_status_failed(dlstatus, status); + } else { + /* + * Do this rather than hex_str(), since hex_str clobbers + * old results and we call twice in the param list. + */ + base16_encode(id_digest_str, sizeof(id_digest_str), + id_digest, DIGEST_LEN); + base16_encode(sk_digest_str, sizeof(sk_digest_str), + signing_key_digest, DIGEST_LEN); + log_warn(LD_BUG, + "Got failure for cert fetch with (fp,sk) = (%s,%s), with " + "status %d, but knew nothing about the download.", + id_digest_str, sk_digest_str, status); + } + } } static const char *BAD_SIGNING_KEYS[] = { @@ -502,7 +677,7 @@ authority_cert_dl_looks_uncertain(const char *id_digest) !(cl = digestmap_get(trusted_dir_certs, id_digest))) return 0; - n_failures = download_status_get_n_failures(&cl->dl_status); + n_failures = download_status_get_n_failures(&cl->dl_status_by_id); return n_failures >= N_AUTH_CERT_DL_FAILURES_TO_BUG_USER; } @@ -518,20 +693,88 @@ authority_cert_dl_looks_uncertain(const char *id_digest) void authority_certs_fetch_missing(networkstatus_t *status, time_t now) { - digestmap_t *pending; + /* + * The pending_id digestmap tracks pending certificate downloads by + * identity digest; the pending_cert digestmap tracks pending downloads + * by (identity digest, signing key digest) pairs. + */ + digestmap_t *pending_id; + fp_pair_map_t *pending_cert; authority_cert_t *cert; - smartlist_t *missing_digests; + /* + * The missing_id_digests smartlist will hold a list of id digests + * we want to fetch the newest cert for; the missing_cert_digests + * smartlist will hold a list of fp_pair_t with an identity and + * signing key digest. + */ + smartlist_t *missing_cert_digests, *missing_id_digests; char *resource = NULL; cert_list_t *cl; const int cache = directory_caches_unknown_auth_certs(get_options()); + fp_pair_t *fp_tmp = NULL; + char id_digest_str[2*DIGEST_LEN+1]; + char sk_digest_str[2*DIGEST_LEN+1]; if (should_delay_dir_fetches(get_options())) return; - pending = digestmap_new(); - missing_digests = smartlist_new(); + pending_cert = fp_pair_map_new(); + pending_id = digestmap_new(); + missing_cert_digests = smartlist_new(); + missing_id_digests = smartlist_new(); + + /* + * First, we get the lists of already pending downloads so we don't + * duplicate effort. + */ + list_pending_downloads(pending_id, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); + list_pending_fpsk_downloads(pending_cert); - list_pending_downloads(pending, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); + /* + * Now, we download any trusted authority certs we don't have by + * identity digest only. This gets the latest cert for that authority. + */ + SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ds) { + int found = 0; + if (!(ds->type & V3_DIRINFO)) + continue; + if (smartlist_contains_digest(missing_id_digests, + ds->v3_identity_digest)) + continue; + cl = get_cert_list(ds->v3_identity_digest); + SMARTLIST_FOREACH_BEGIN(cl->certs, authority_cert_t *, cert) { + if (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_by_id)); + /* No sense trying to download it specifically by signing key hash */ + download_status_reset_by_sk_in_cl(cl, cert->signing_key_digest); + found = 1; + break; + } + } SMARTLIST_FOREACH_END(cert); + if (!found && + download_status_is_ready(&(cl->dl_status_by_id), now, + MAX_CERT_DL_FAILURES) && + !digestmap_get(pending_id, ds->v3_identity_digest)) { + log_info(LD_DIR, + "No current certificate known for authority %s " + "(ID digest %s); launching request.", + ds->nickname, hex_str(ds->v3_identity_digest, DIGEST_LEN)); + smartlist_add(missing_id_digests, ds->v3_identity_digest); + } + } SMARTLIST_FOREACH_END(ds); + + /* + * Next, if we have a consensus, scan through it and look for anything + * signed with a key from a cert we don't have. Those get downloaded + * by (fp,sk) pair, but if we don't know any certs at all for the fp + * (identity digest), and it's one of the trusted dir server certs + * we started off above or a pending download in pending_id, don't + * try to get it yet. Most likely, the one we'll get for that will + * have the right signing key too, and we'd just be downloading + * redundantly. + */ if (status) { SMARTLIST_FOREACH_BEGIN(status->voters, networkstatus_voter_info_t *, voter) { @@ -541,84 +784,164 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now) if (!cache && !trusteddirserver_get_by_v3_auth_digest(voter->identity_digest)) continue; /* We are not a cache, and we don't know this authority.*/ + + /* + * If we don't know *any* cert for this authority, and a download by ID + * is pending or we added it to missing_id_digests above, skip this + * one for now to avoid duplicate downloads. + */ cl = get_cert_list(voter->identity_digest); + if (smartlist_len(cl->certs) == 0) { + /* We have no certs at all for this one */ + + /* Do we have a download of one pending? */ + if (digestmap_get(pending_id, voter->identity_digest)) + continue; + + /* + * Are we about to launch a download of one due to the trusted + * dir server check above? + */ + if (smartlist_contains_digest(missing_id_digests, + voter->identity_digest)) + continue; + } + SMARTLIST_FOREACH_BEGIN(voter->sigs, document_signature_t *, sig) { cert = authority_cert_get_by_digests(voter->identity_digest, sig->signing_key_digest); if (cert) { if (now < cert->expires) - download_status_reset(&cl->dl_status); + download_status_reset_by_sk_in_cl(cl, sig->signing_key_digest); continue; } - if (download_status_is_ready(&cl->dl_status, now, - MAX_CERT_DL_FAILURES) && - !digestmap_get(pending, voter->identity_digest)) { - log_info(LD_DIR, "We're missing a certificate from authority " - "with signing key %s: launching request.", - hex_str(sig->signing_key_digest, DIGEST_LEN)); - smartlist_add(missing_digests, sig->identity_digest); + if (download_status_is_ready_by_sk_in_cl( + cl, sig->signing_key_digest, + now, MAX_CERT_DL_FAILURES) && + !fp_pair_map_get_by_digests(pending_cert, + voter->identity_digest, + sig->signing_key_digest)) { + /* + * Do this rather than hex_str(), since hex_str clobbers + * old results and we call twice in the param list. + */ + base16_encode(id_digest_str, sizeof(id_digest_str), + voter->identity_digest, DIGEST_LEN); + base16_encode(sk_digest_str, sizeof(sk_digest_str), + sig->signing_key_digest, DIGEST_LEN); + + if (voter->nickname) { + log_info(LD_DIR, + "We're missing a certificate from authority %s " + "(ID digest %s) with signing key %s: " + "launching request.", + voter->nickname, id_digest_str, sk_digest_str); + } else { + log_info(LD_DIR, + "We're missing a certificate from authority ID digest " + "%s with signing key %s: launching request.", + id_digest_str, sk_digest_str); + } + + /* Allocate a new fp_pair_t to append */ + fp_tmp = tor_malloc(sizeof(*fp_tmp)); + memcpy(fp_tmp->first, voter->identity_digest, sizeof(fp_tmp->first)); + memcpy(fp_tmp->second, sig->signing_key_digest, + sizeof(fp_tmp->second)); + smartlist_add(missing_cert_digests, fp_tmp); } } SMARTLIST_FOREACH_END(sig); } SMARTLIST_FOREACH_END(voter); } - SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) { - int found = 0; - if (!(ds->type & V3_DIRINFO)) - 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 (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_info(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; - } else { + /* Do downloads by identity digest */ + if (smartlist_len(missing_id_digests) > 0) { + int need_plus = 0; smartlist_t *fps = smartlist_new(); + smartlist_add(fps, tor_strdup("fp/")); - SMARTLIST_FOREACH(missing_digests, const char *, d, { - char *fp; - if (digestmap_get(pending, d)) - continue; - fp = tor_malloc(HEX_DIGEST_LEN+2); - base16_encode(fp, HEX_DIGEST_LEN+1, d, DIGEST_LEN); - fp[HEX_DIGEST_LEN] = '+'; - fp[HEX_DIGEST_LEN+1] = '\0'; - smartlist_add(fps, fp); - }); - if (smartlist_len(fps) == 1) { - /* we didn't add any: they were all pending */ - SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp)); - smartlist_free(fps); - goto done; + + SMARTLIST_FOREACH_BEGIN(missing_id_digests, const char *, d) { + char *fp = NULL; + + if (digestmap_get(pending_id, d)) + continue; + + base16_encode(id_digest_str, sizeof(id_digest_str), + d, DIGEST_LEN); + + if (need_plus) { + tor_asprintf(&fp, "+%s", id_digest_str); + } else { + /* No need for tor_asprintf() in this case; first one gets no '+' */ + fp = tor_strdup(id_digest_str); + need_plus = 1; + } + + smartlist_add(fps, fp); + } SMARTLIST_FOREACH_END(d); + + if (smartlist_len(fps) > 1) { + resource = smartlist_join_strings(fps, "", 0, NULL); + directory_get_from_dirserver(DIR_PURPOSE_FETCH_CERTIFICATE, 0, + resource, PDS_RETRY_IF_NO_SERVERS); + tor_free(resource); } - resource = smartlist_join_strings(fps, "", 0, NULL); - resource[strlen(resource)-1] = '\0'; + /* else we didn't add any: they were all pending */ + SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp)); smartlist_free(fps); } - directory_get_from_dirserver(DIR_PURPOSE_FETCH_CERTIFICATE, 0, - resource, PDS_RETRY_IF_NO_SERVERS); - done: - tor_free(resource); - smartlist_free(missing_digests); - digestmap_free(pending, NULL); + /* Do downloads by identity digest/signing key pair */ + if (smartlist_len(missing_cert_digests) > 0) { + int need_plus = 0; + smartlist_t *fp_pairs = smartlist_new(); + + smartlist_add(fp_pairs, tor_strdup("fp-sk/")); + + SMARTLIST_FOREACH_BEGIN(missing_cert_digests, const fp_pair_t *, d) { + char *fp_pair = NULL; + + if (fp_pair_map_get(pending_cert, d)) + continue; + + /* Construct string encodings of the digests */ + base16_encode(id_digest_str, sizeof(id_digest_str), + d->first, DIGEST_LEN); + base16_encode(sk_digest_str, sizeof(sk_digest_str), + d->second, DIGEST_LEN); + + /* Now tor_asprintf() */ + if (need_plus) { + tor_asprintf(&fp_pair, "+%s-%s", id_digest_str, sk_digest_str); + } else { + /* First one in the list doesn't get a '+' */ + tor_asprintf(&fp_pair, "%s-%s", id_digest_str, sk_digest_str); + need_plus = 1; + } + + /* Add it to the list of pairs to request */ + smartlist_add(fp_pairs, fp_pair); + } SMARTLIST_FOREACH_END(d); + + if (smartlist_len(fp_pairs) > 1) { + resource = smartlist_join_strings(fp_pairs, "", 0, NULL); + directory_get_from_dirserver(DIR_PURPOSE_FETCH_CERTIFICATE, 0, + resource, PDS_RETRY_IF_NO_SERVERS); + tor_free(resource); + } + /* else they were all pending */ + + SMARTLIST_FOREACH(fp_pairs, char *, p, tor_free(p)); + smartlist_free(fp_pairs); + } + + smartlist_free(missing_id_digests); + SMARTLIST_FOREACH(missing_cert_digests, fp_pair_t *, p, tor_free(p)); + smartlist_free(missing_cert_digests); + digestmap_free(pending_id, NULL); + fp_pair_map_free(pending_cert, NULL); } /* Router descriptor storage. @@ -686,7 +1009,7 @@ signed_desc_append_to_journal(signed_descriptor_t *desc, * signed_descriptor_t* in *<b>a</b> is older, the same age as, or newer than * the signed_descriptor_t* in *<b>b</b>. */ static int -_compare_signed_descriptors_by_age(const void **_a, const void **_b) +compare_signed_descriptors_by_age_(const void **_a, const void **_b) { const signed_descriptor_t *r1 = *_a, *r2 = *_b; return (int)(r1->published_on - r2->published_on); @@ -759,7 +1082,7 @@ router_rebuild_store(int flags, desc_store_t *store) smartlist_add(signed_descriptors, &ri->cache_info)); } - smartlist_sort(signed_descriptors, _compare_signed_descriptors_by_age); + smartlist_sort(signed_descriptors, compare_signed_descriptors_by_age_); /* Now, add the appropriate members to chunk_list */ SMARTLIST_FOREACH_BEGIN(signed_descriptors, signed_descriptor_t *, sd) { @@ -945,11 +1268,11 @@ router_reload_router_list(void) return 0; } -/** Return a smartlist containing a list of trusted_dir_server_t * for all +/** Return a smartlist containing a list of dir_server_t * for all * known trusted dirservers. Callers must not modify the list or its * contents. */ -smartlist_t * +const smartlist_t * router_get_trusted_dir_servers(void) { if (!trusted_dir_servers) @@ -958,6 +1281,15 @@ router_get_trusted_dir_servers(void) return trusted_dir_servers; } +const smartlist_t * +router_get_fallback_dir_servers(void) +{ + if (!fallback_dir_servers) + fallback_dir_servers = smartlist_new(); + + return fallback_dir_servers; +} + /** Try to find a running dirserver that supports operations of <b>type</b>. * * If there are no running dirservers in our routerlist and the @@ -978,7 +1310,7 @@ router_pick_directory_server(dirinfo_type_t type, int flags) { const routerstatus_t *choice; if (get_options()->PreferTunneledDirConns) - flags |= _PDS_PREFER_TUNNELED_DIR_CONNS; + flags |= PDS_PREFER_TUNNELED_DIR_CONNS_; if (!routerlist) return NULL; @@ -991,7 +1323,7 @@ router_pick_directory_server(dirinfo_type_t type, int flags) "No reachable router entries for dirservers. " "Trying them all again."); /* mark all authdirservers as up again */ - mark_all_trusteddirservers_up(); + mark_all_dirservers_up(fallback_dir_servers); /* try again */ choice = router_pick_directory_server_impl(type, flags); return choice; @@ -1026,7 +1358,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out, } } - if (rs->version_supports_v3_dir) { + { sl_last_total_weighted_bw = 0; router_pick_directory_server(V3_DIRINFO, pds_flags); if (sl_last_total_weighted_bw != 0) { @@ -1038,16 +1370,16 @@ router_get_my_share_of_directory_requests(double *v2_share_out, return 0; } -/** Return the trusted_dir_server_t for the directory authority whose identity +/** Return the dir_server_t for the directory authority whose identity * key hashes to <b>digest</b>, or NULL if no such authority is known. */ -trusted_dir_server_t * +dir_server_t * router_get_trusteddirserver_by_digest(const char *digest) { if (!trusted_dir_servers) return NULL; - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, + SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ds, { if (tor_memeq(ds->digest, digest, DIGEST_LEN)) return ds; @@ -1056,17 +1388,35 @@ router_get_trusteddirserver_by_digest(const char *digest) return NULL; } -/** Return the trusted_dir_server_t for the directory authority whose +/** Return the dir_server_t for the fallback dirserver whose identity + * key hashes to <b>digest</b>, or NULL if no such authority is known. + */ +dir_server_t * +router_get_fallback_dirserver_by_digest(const char *digest) +{ + if (!trusted_dir_servers) + return NULL; + + SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ds, + { + if (tor_memeq(ds->digest, digest, DIGEST_LEN)) + return ds; + }); + + return NULL; +} + +/** Return the 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 * +dir_server_t * trusteddirserver_get_by_v3_auth_digest(const char *digest) { if (!trusted_dir_servers) return NULL; - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, + SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ds, { if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) && (ds->type & V3_DIRINFO)) @@ -1076,18 +1426,37 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest) return NULL; } -/** Try to find a running trusted dirserver. Flags are as for +/** Try to find a running directory authority. Flags are as for * router_pick_directory_server. */ const routerstatus_t * router_pick_trusteddirserver(dirinfo_type_t type, int flags) { + return router_pick_dirserver_generic(trusted_dir_servers, type, flags); +} + +/** Try to find a running fallback directory Flags are as for + * router_pick_directory_server. + */ +const routerstatus_t * +router_pick_fallback_dirserver(dirinfo_type_t type, int flags) +{ + return router_pick_dirserver_generic(fallback_dir_servers, type, flags); +} + +/** Try to find a running fallback directory Flags are as for + * router_pick_directory_server. + */ +static const routerstatus_t * +router_pick_dirserver_generic(smartlist_t *sourcelist, + dirinfo_type_t type, int flags) +{ const routerstatus_t *choice; int busy = 0; if (get_options()->PreferTunneledDirConns) - flags |= _PDS_PREFER_TUNNELED_DIR_CONNS; + flags |= PDS_PREFER_TUNNELED_DIR_CONNS_; - choice = router_pick_trusteddirserver_impl(type, flags, &busy); + choice = router_pick_trusteddirserver_impl(sourcelist, type, flags, &busy); if (choice || !(flags & PDS_RETRY_IF_NO_SERVERS)) return choice; if (busy) { @@ -1100,9 +1469,9 @@ router_pick_trusteddirserver(dirinfo_type_t type, int flags) } log_info(LD_DIR, - "No trusted dirservers are reachable. Trying them all again."); - mark_all_trusteddirservers_up(); - return router_pick_trusteddirserver_impl(type, flags, NULL); + "No dirservers are reachable. Trying them all again."); + mark_all_dirservers_up(sourcelist); + return router_pick_trusteddirserver_impl(sourcelist, type, flags, NULL); } /** How long do we avoid using a directory server after it's given us a 503? */ @@ -1112,7 +1481,7 @@ router_pick_trusteddirserver(dirinfo_type_t type, int flags) * routerlist. Arguments are as for router_pick_directory_server(), except * that RETRY_IF_NO_SERVERS is ignored, and: * - * If the _PDS_PREFER_TUNNELED_DIR_CONNS flag is set, prefer directory servers + * If the PDS_PREFER_TUNNELED_DIR_CONNS_ flag is set, prefer directory servers * that we can use with BEGINDIR. */ static const routerstatus_t * @@ -1127,7 +1496,8 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) const networkstatus_t *consensus = networkstatus_get_latest_consensus(); int requireother = ! (flags & PDS_ALLOW_SELF); int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL); - int prefer_tunnel = (flags & _PDS_PREFER_TUNNELED_DIR_CONNS); + int prefer_tunnel = (flags & PDS_PREFER_TUNNELED_DIR_CONNS_); + int for_guard = (flags & PDS_FOR_GUARD); int try_excluding = 1, n_excluded = 0; if (!consensus) @@ -1158,12 +1528,6 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) continue; if (requireother && router_digest_is_me(node->identity)) continue; - if (type & V3_DIRINFO) { - if (!(status->version_supports_v3_dir || - router_digest_is_trusted_dir_type(node->identity, - V3_DIRINFO))) - continue; - } is_trusted = router_digest_is_trusted_dir(node->identity); if ((type & V2_DIRINFO) && !(node->rs->is_v2_dir || is_trusted)) continue; @@ -1173,6 +1537,8 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) if ((type & MICRODESC_DIRINFO) && !is_trusted && !node->rs->version_supports_microdesc_cache) continue; + if (for_guard && node->using_as_guard) + continue; /* Don't make the same node a guard twice. */ if (try_excluding && routerset_contains_routerstatus(options->ExcludeNodes, status, country)) { @@ -1186,7 +1552,6 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now; if (prefer_tunnel && - status->version_supports_begindir && (!fascistfirewall || fascist_firewall_allows_address_or(&addr, status->or_port))) smartlist_add(is_trusted ? trusted_tunnel : @@ -1234,28 +1599,56 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags) return result ? result->rs : NULL; } -/** Choose randomly from among the trusted dirservers that are up. Flags - * are as for router_pick_directory_server_impl(). +/** Pick a random element from a list of dir_server_t, weighting by their + * <b>weight</b> field. */ +static const dir_server_t * +dirserver_choose_by_weight(const smartlist_t *servers, double authority_weight) +{ + int n = smartlist_len(servers); + int i; + u64_dbl_t *weights; + const dir_server_t *ds; + + weights = tor_malloc(sizeof(u64_dbl_t) * n); + for (i = 0; i < n; ++i) { + ds = smartlist_get(servers, i); + weights[i].dbl = ds->weight; + if (ds->is_authority) + weights[i].dbl *= authority_weight; + } + + scale_array_elements_to_u64(weights, n, NULL); + i = choose_array_element_by_weight(weights, n); + tor_free(weights); + return (i < 0) ? NULL : smartlist_get(servers, i); +} + +/** Choose randomly from among the dir_server_ts in sourcelist that + * are up. Flags are as for router_pick_directory_server_impl(). */ static const routerstatus_t * -router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags, +router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, + dirinfo_type_t type, int flags, int *n_busy_out) { const or_options_t *options = get_options(); smartlist_t *direct, *tunnel; smartlist_t *overloaded_direct, *overloaded_tunnel; const routerinfo_t *me = router_get_my_routerinfo(); - const routerstatus_t *result; + const routerstatus_t *result = NULL; time_t now = time(NULL); const int requireother = ! (flags & PDS_ALLOW_SELF); const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL); - const int prefer_tunnel = (flags & _PDS_PREFER_TUNNELED_DIR_CONNS); + const int prefer_tunnel = (flags & PDS_PREFER_TUNNELED_DIR_CONNS_); const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH); const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH); + const double auth_weight = (sourcelist == fallback_dir_servers) ? + options->DirAuthorityFallbackRate : 1.0; + smartlist_t *pick_from; int n_busy = 0; int try_excluding = 1, n_excluded = 0; - if (!trusted_dir_servers) + if (!sourcelist) return NULL; retry_without_exclude: @@ -1265,7 +1658,7 @@ router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags, overloaded_direct = smartlist_new(); overloaded_tunnel = smartlist_new(); - SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, d) + SMARTLIST_FOREACH_BEGIN(sourcelist, const dir_server_t *, d) { int is_overloaded = d->fake_status.last_dir_503_at + DIR_503_TIMEOUT > now; @@ -1311,23 +1704,29 @@ router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags, d->or_port && (!fascistfirewall || fascist_firewall_allows_address_or(&addr, d->or_port))) - smartlist_add(is_overloaded ? overloaded_tunnel : tunnel, - &d->fake_status); + smartlist_add(is_overloaded ? overloaded_tunnel : tunnel, (void*)d); else if (!fascistfirewall || fascist_firewall_allows_address_dir(&addr, d->dir_port)) - smartlist_add(is_overloaded ? overloaded_direct : direct, - &d->fake_status); + smartlist_add(is_overloaded ? overloaded_direct : direct, (void*)d); } SMARTLIST_FOREACH_END(d); if (smartlist_len(tunnel)) { - result = smartlist_choose(tunnel); + pick_from = tunnel; } else if (smartlist_len(overloaded_tunnel)) { - result = smartlist_choose(overloaded_tunnel); + pick_from = overloaded_tunnel; } else if (smartlist_len(direct)) { - result = smartlist_choose(direct); + pick_from = direct; } else { - result = smartlist_choose(overloaded_direct); + pick_from = overloaded_direct; + } + + { + const dir_server_t *selection = + dirserver_choose_by_weight(pick_from, auth_weight); + + if (selection) + result = &selection->fake_status; } if (n_busy_out) @@ -1349,19 +1748,19 @@ router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags, return result; } -/** Go through and mark the authoritative dirservers as up. */ +/** Mark as running every dir_server_t in <b>server_list</b>. */ static void -mark_all_trusteddirservers_up(void) +mark_all_dirservers_up(smartlist_t *server_list) { - SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, { - if (router_digest_is_trusted_dir(node->identity)) - node->is_running = 1; - }); - if (trusted_dir_servers) { - SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, dir) { + if (server_list) { + SMARTLIST_FOREACH_BEGIN(server_list, dir_server_t *, dir) { routerstatus_t *rs; + node_t *node; dir->is_running = 1; download_status_reset(&dir->v2_ns_dl_status); + node = node_get_mutable_by_id(dir->digest); + if (node) + node->is_running = 1; rs = router_get_mutable_consensus_status_by_id(dir->digest); if (rs) { rs->last_dir_503_at = 0; @@ -1374,9 +1773,11 @@ mark_all_trusteddirservers_up(void) /** 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) +routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2) { - return r1->addr == r2->addr && r1->or_port == r2->or_port; + return r1->addr == r2->addr && r1->or_port == r2->or_port && + tor_addr_eq(&r1->ipv6_addr, &r2->ipv6_addr) && + r1->ipv6_orport == r2->ipv6_orport; } /** Reset all internal variables used to count failed downloads of network @@ -1384,89 +1785,7 @@ routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2) void router_reset_status_download_failures(void) { - mark_all_trusteddirservers_up(); -} - -/** Return true iff router1 and router2 have similar enough network addresses - * that we should treat them as being in the same family */ -static INLINE int -addrs_in_same_network_family(const tor_addr_t *a1, - const tor_addr_t *a2) -{ - /* XXXX MOVE ? */ - return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC); -} - -/** - * Add all the family of <b>node</b>, including <b>node</b> itself, to - * the smartlist <b>sl</b>. - * - * This is used to make sure we don't pick siblings in a single path, or - * pick more than one relay from a family for our entry guard list. - * Note that a node may be added to <b>sl</b> more than once if it is - * part of <b>node</b>'s family for more than one reason. - */ -void -nodelist_add_node_and_family(smartlist_t *sl, const node_t *node) -{ - /* XXXX MOVE */ - const smartlist_t *all_nodes = nodelist_get_list(); - const smartlist_t *declared_family; - const or_options_t *options = get_options(); - - tor_assert(node); - - declared_family = node_get_declared_family(node); - - /* Let's make sure that we have the node itself, if it's a real node. */ - { - const node_t *real_node = node_get_by_id(node->identity); - if (real_node) - smartlist_add(sl, (node_t*)real_node); - } - - /* First, add any nodes with similar network addresses. */ - if (options->EnforceDistinctSubnets) { - tor_addr_t node_addr; - node_get_addr(node, &node_addr); - - SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) { - tor_addr_t a; - node_get_addr(node2, &a); - if (addrs_in_same_network_family(&a, &node_addr)) - smartlist_add(sl, (void*)node2); - } SMARTLIST_FOREACH_END(node2); - } - - /* Now, add all nodes in the declared_family of this node, if they - * also declare this node to be in their family. */ - if (declared_family) { - /* Add every r such that router declares familyness with node, and node - * declares familyhood with router. */ - SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) { - const node_t *node2; - const smartlist_t *family2; - if (!(node2 = node_get_by_nickname(name, 0))) - continue; - if (!(family2 = node_get_declared_family(node2))) - continue; - SMARTLIST_FOREACH_BEGIN(family2, const char *, name2) { - if (node_nickname_matches(node, name2)) { - smartlist_add(sl, (void*)node2); - break; - } - } SMARTLIST_FOREACH_END(name2); - } SMARTLIST_FOREACH_END(name); - } - - /* If the user declared any families locally, honor those too. */ - if (options->NodeFamilySets) { - SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { - if (routerset_contains_node(rs, node)) { - routerset_get_all_nodes(sl, rs, NULL, 0); - } - }); - } + mark_all_dirservers_up(fallback_dir_servers); } /** Given a <b>router</b>, add every node_t in its family (including the @@ -1490,83 +1809,6 @@ routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router) nodelist_add_node_and_family(sl, node); } -/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */ -static INLINE int -node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node) -{ - /* XXXX MOVE */ - if (!lst) return 0; - SMARTLIST_FOREACH(lst, const char *, name, { - if (node_nickname_matches(node, name)) - return 1; - }); - return 0; -} - -/** Return true iff r1 and r2 are in the same family, but not the same - * router. */ -int -nodes_in_same_family(const node_t *node1, const node_t *node2) -{ - /* XXXX MOVE */ - const or_options_t *options = get_options(); - - /* Are they in the same family because of their addresses? */ - if (options->EnforceDistinctSubnets) { - tor_addr_t a1, a2; - node_get_addr(node1, &a1); - node_get_addr(node2, &a2); - if (addrs_in_same_network_family(&a1, &a2)) - return 1; - } - - /* Are they in the same family because the agree they are? */ - { - const smartlist_t *f1, *f2; - f1 = node_get_declared_family(node1); - f2 = node_get_declared_family(node2); - if (f1 && f2 && - node_in_nickname_smartlist(f1, node2) && - node_in_nickname_smartlist(f2, node1)) - return 1; - } - - /* Are they in the same option because the user says they are? */ - if (options->NodeFamilySets) { - SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { - if (routerset_contains_node(rs, node1) && - routerset_contains_node(rs, node2)) - return 1; - }); - } - - return 0; -} - -/** Return 1 iff any member of the (possibly NULL) comma-separated list - * <b>list</b> is an acceptable nickname or hexdigest for <b>router</b>. Else - * return 0. - */ -int -router_nickname_is_in_list(const routerinfo_t *router, const char *list) -{ - smartlist_t *nickname_list; - int v = 0; - - if (!list) - return 0; /* definitely not */ - tor_assert(router); - - nickname_list = smartlist_new(); - smartlist_split_string(nickname_list, list, ",", - SPLIT_SKIP_SPACE|SPLIT_STRIP_SPACE|SPLIT_IGNORE_BLANK, 0); - SMARTLIST_FOREACH(nickname_list, const char *, cp, - if (router_nickname_matches(router, cp)) {v=1;break;}); - SMARTLIST_FOREACH(nickname_list, char *, cp, tor_free(cp)); - smartlist_free(nickname_list); - return v; -} - /** Add every suitable node from our nodelist to <b>sl</b>, so that * we can pick a node for a circuit. */ @@ -1606,56 +1848,6 @@ routerlist_find_my_routerinfo(void) return NULL; } -/** Find a router that's up, that has this IP address, and - * that allows exit to this address:port, or return NULL if there - * isn't a good one. - * Don't exit enclave to excluded relays -- it wouldn't actually - * hurt anything, but this way there are fewer confused users. - */ -const node_t * -router_find_exact_exit_enclave(const char *address, uint16_t port) -{/*XXXX MOVE*/ - uint32_t addr; - struct in_addr in; - tor_addr_t a; - const or_options_t *options = get_options(); - - if (!tor_inet_aton(address, &in)) - return NULL; /* it's not an IP already */ - addr = ntohl(in.s_addr); - - tor_addr_from_ipv4h(&a, addr); - - SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, { - if (node_get_addr_ipv4h(node) == addr && - node->is_running && - compare_tor_addr_to_node_policy(&a, port, node) == - ADDR_POLICY_ACCEPTED && - !routerset_contains_node(options->_ExcludeExitNodesUnion, node)) - return node; - }); - return NULL; -} - -/** Return 1 if <b>router</b> is not suitable for these parameters, else 0. - * If <b>need_uptime</b> is non-zero, we require a minimum uptime. - * If <b>need_capacity</b> is non-zero, we require a minimum advertised - * bandwidth. - * If <b>need_guard</b>, we require that the router is a possible entry guard. - */ -int -node_is_unreliable(const node_t *node, int need_uptime, - int need_capacity, int need_guard) -{ - if (need_uptime && !node->is_stable) - return 1; - if (need_capacity && !node->is_fast) - return 1; - if (need_guard && !node->is_possible_guard) - return 1; - return 0; -} - /** Return the smaller of the router's configured BandwidthRate * and its advertised capacity. */ uint32_t @@ -1683,6 +1875,92 @@ router_get_advertised_bandwidth_capped(const routerinfo_t *router) return result; } +/** Given an array of double/uint64_t unions that are currently being used as + * doubles, convert them to uint64_t, and try to scale them linearly so as to + * much of the range of uint64_t. If <b>total_out</b> is provided, set it to + * the sum of all elements in the array _before_ scaling. */ +/* private */ void +scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries, + uint64_t *total_out) +{ + double total = 0.0; + double scale_factor; + int i; + /* big, but far away from overflowing an int64_t */ +#define SCALE_TO_U64_MAX (INT64_MAX / 4) + + for (i = 0; i < n_entries; ++i) + total += entries[i].dbl; + + scale_factor = SCALE_TO_U64_MAX / total; + + for (i = 0; i < n_entries; ++i) + entries[i].u64 = tor_llround(entries[i].dbl * scale_factor); + + if (total_out) + *total_out = (uint64_t) total; + +#undef SCALE_TO_U64_MAX +} + +/** Time-invariant 64-bit greater-than; works on two integers in the range + * (0,INT64_MAX). */ +#if SIZEOF_VOID_P == 8 +#define gt_i64_timei(a,b) ((a) > (b)) +#else +static INLINE int +gt_i64_timei(uint64_t a, uint64_t b) +{ + int64_t diff = (int64_t) (b - a); + int res = diff >> 63; + return res & 1; +} +#endif + +/** Pick a random element of <b>n_entries</b>-element array <b>entries</b>, + * choosing each element with a probability proportional to its (uint64_t) + * value, and return the index of that element. If all elements are 0, choose + * an index at random. Return -1 on error. + */ +/* private */ int +choose_array_element_by_weight(const u64_dbl_t *entries, int n_entries) +{ + int i, i_chosen=-1, n_chosen=0; + uint64_t total_so_far = 0; + uint64_t rand_val; + uint64_t total = 0; + + for (i = 0; i < n_entries; ++i) + total += entries[i].u64; + + if (n_entries < 1) + return -1; + + if (total == 0) + return crypto_rand_int(n_entries); + + tor_assert(total < INT64_MAX); + + rand_val = crypto_rand_uint64(total); + + for (i = 0; i < n_entries; ++i) { + total_so_far += entries[i].u64; + if (gt_i64_timei(total_so_far, rand_val)) { + i_chosen = i; + n_chosen++; + /* Set rand_val to INT64_MAX rather than stopping the loop. This way, + * the time we spend in the loop does not leak which element we chose. */ + rand_val = INT64_MAX; + } + } + tor_assert(total_so_far == total); + tor_assert(n_chosen == 1); + tor_assert(i_chosen >= 0); + tor_assert(i_chosen < n_entries); + + return i_chosen; +} + /** 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. */ @@ -1729,20 +2007,40 @@ kb_to_bytes(uint32_t bw) * guards proportionally less. */ static const node_t * -smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, +smartlist_choose_node_by_bandwidth_weights(const smartlist_t *sl, bandwidth_weight_rule_t rule) { + u64_dbl_t *bandwidths=NULL; + + if (compute_weighted_bandwidths(sl, rule, &bandwidths) < 0) + return NULL; + + scale_array_elements_to_u64(bandwidths, smartlist_len(sl), + &sl_last_total_weighted_bw); + + { + int idx = choose_array_element_by_weight(bandwidths, + smartlist_len(sl)); + tor_free(bandwidths); + return idx < 0 ? NULL : smartlist_get(sl, idx); + } +} + +/** Given a list of routers and a weighting rule as in + * smartlist_choose_node_by_bandwidth_weights, compute weighted bandwidth + * values for each node and store them in a freshly allocated + * *<b>bandwidths_out</b> of the same length as <b>sl</b>, and holding results + * as doubles. Return 0 on success, -1 on failure. */ +static int +compute_weighted_bandwidths(const smartlist_t *sl, + bandwidth_weight_rule_t rule, + u64_dbl_t **bandwidths_out) +{ 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, unweighted_bw = 0; - double *bandwidths; - double tmp = 0; - unsigned int i; - unsigned int i_chosen; - unsigned int i_has_been_chosen; - int have_unknown = 0; /* true iff sl contains element not in consensus. */ + uint64_t weighted_bw = 0; + u64_dbl_t *bandwidths; /* Can't choose exit and guard at same time */ tor_assert(rule == NO_WEIGHTING || @@ -1756,10 +2054,10 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, "Empty routerlist passed in to consensus weight node " "selection for rule %s", bandwidth_weight_rule_to_string(rule)); - return NULL; + return -1; } - weight_scale = circuit_build_times_get_bw_scale(NULL); + weight_scale = networkstatus_get_weight_scale_param(NULL); if (rule == WEIGHT_FOR_GUARD) { Wg = networkstatus_get_bw_weight(NULL, "Wgg", -1); @@ -1810,7 +2108,7 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, log_debug(LD_CIRC, "Got negative bandwidth weights. Defaulting to old selection" " algorithm."); - return NULL; // Use old algorithm. + return -1; // Use old algorithm. } Wg /= weight_scale; @@ -1823,7 +2121,7 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, Web /= weight_scale; Wdb /= weight_scale; - bandwidths = tor_malloc_zero(sizeof(double)*smartlist_len(sl)); + bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl)); // Cycle through smartlist and total the bandwidth. SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { @@ -1840,13 +2138,12 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, log_warn(LD_BUG, "Consensus is not listing bandwidths. Defaulting back to " "old router selection algorithm."); - return NULL; + return -1; } - this_bw = kb_to_bytes(node->rs->bandwidth); + this_bw = kb_to_bytes(node->rs->bandwidth_kb); } else if (node->ri) { /* bridge or other descriptor not in our consensus */ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri); - have_unknown = 1; } else { /* We can't use this one. */ continue; @@ -1862,72 +2159,65 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, } else { // middle weight = (is_dir ? Wmb*Wm : Wm); } - - bandwidths[node_sl_idx] = weight*this_bw; - weighted_bw += weight*this_bw; - unweighted_bw += this_bw; + /* These should be impossible; but overflows here would be bad, so let's + * make sure. */ + if (this_bw < 0) + this_bw = 0; + if (weight < 0.0) + weight = 0.0; + + bandwidths[node_sl_idx].dbl = weight*this_bw + 0.5; if (is_me) - sl_last_weighted_bw_of_me = weight*this_bw; + sl_last_weighted_bw_of_me = (uint64_t) bandwidths[node_sl_idx].dbl; } SMARTLIST_FOREACH_END(node); - /* XXXX 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=%f Wm=%f We=%f Wd=%f with total bw %f", + log_debug(LD_CIRC, "Generated weighted bandwidths for rule %s based " + "on weights " + "Wg=%f Wm=%f We=%f Wd=%f with total bw "U64_FORMAT, 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) { -#define ZERO_BANDWIDTH_WARNING_INTERVAL (15) - static ratelim_t zero_bandwidth_warning_limit = - RATELIM_INIT(ZERO_BANDWIDTH_WARNING_INTERVAL); - char *msg; - if ((msg = rate_limit_log(&zero_bandwidth_warning_limit, - approx_time()))) { - log_warn(LD_CIRC, - "Weighted bandwidth is %f in node selection for rule %s " - "(unweighted was %f) %s", - weighted_bw, bandwidth_weight_rule_to_string(rule), - unweighted_bw, msg); - } - } - tor_free(bandwidths); - return smartlist_choose(sl); - } + Wg, Wm, We, Wd, U64_PRINTF_ARG(weighted_bw)); - 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. */ + *bandwidths_out = bandwidths; - /* Last, count through sl until we get to the element we picked */ - i_chosen = (unsigned)smartlist_len(sl); - i_has_been_chosen = 0; - tmp = 0.0; - for (i=0; i < (unsigned)smartlist_len(sl); i++) { - tmp += bandwidths[i]; - if (tmp >= rand_bw && !i_has_been_chosen) { - i_chosen = i; - i_has_been_chosen = 1; - } - } - i = i_chosen; + return 0; +} + +/** For all nodes in <b>sl</b>, return the fraction of those nodes, weighted + * by their weighted bandwidths with rule <b>rule</b>, for which we have + * descriptors. */ +double +frac_nodes_with_descriptors(const smartlist_t *sl, + bandwidth_weight_rule_t rule) +{ + u64_dbl_t *bandwidths = NULL; + double total, present; + + if (smartlist_len(sl) == 0) + return 0.0; - 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. " - "%f " U64_FORMAT " %f", tmp, U64_PRINTF_ARG(rand_bw), - weighted_bw); + if (compute_weighted_bandwidths(sl, rule, &bandwidths) < 0) { + int n_with_descs = 0; + SMARTLIST_FOREACH(sl, const node_t *, node, { + if (node_has_descriptor(node)) + n_with_descs++; + }); + return ((double)n_with_descs) / (double)smartlist_len(sl); } + + total = present = 0.0; + SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { + const double bw = bandwidths[node_sl_idx].dbl; + total += bw; + if (node_has_descriptor(node)) + present += bw; + } SMARTLIST_FOREACH_END(node); + tor_free(bandwidths); - return smartlist_get(sl, i); + + if (total < 1.0) + return 0; + + return present / total; } /** Helper function: @@ -1944,21 +2234,20 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, * guards proportionally less. */ static const node_t * -smartlist_choose_node_by_bandwidth(smartlist_t *sl, +smartlist_choose_node_by_bandwidth(const smartlist_t *sl, bandwidth_weight_rule_t rule) { unsigned int i; - unsigned int i_chosen; - unsigned int i_has_been_chosen; - int32_t *bandwidths; + u64_dbl_t *bandwidths; int is_exit; int is_guard; - uint64_t total_nonexit_bw = 0, total_exit_bw = 0, total_bw = 0; - uint64_t total_nonguard_bw = 0, total_guard_bw = 0; - uint64_t rand_bw, tmp; + int is_fast; + double total_nonexit_bw = 0, total_exit_bw = 0; + double total_nonguard_bw = 0, total_guard_bw = 0; double exit_weight; double guard_weight; int n_unknown = 0; + bitarray_t *fast_bits; bitarray_t *exit_bits; bitarray_t *guard_bits; int me_idx = -1; @@ -1982,10 +2271,9 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, } /* 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 - * and whether it was an exit (-x)&2 or guard (-x)&4. Yes, it's a hack. */ - bandwidths = tor_malloc(sizeof(int32_t)*smartlist_len(sl)); + * of each value. We use UINT64_MAX to indicate "unknown". */ + bandwidths = tor_malloc_zero(sizeof(u64_dbl_t)*smartlist_len(sl)); + fast_bits = bitarray_init_zero(smartlist_len(sl)); exit_bits = bitarray_init_zero(smartlist_len(sl)); guard_bits = bitarray_init_zero(smartlist_len(sl)); @@ -1993,7 +2281,6 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { /* first, learn what bandwidth we think i has */ int is_known = 1; - int32_t flags = 0; uint32_t this_bw = 0; i = node_sl_idx; @@ -2004,14 +2291,9 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, is_guard = node->is_possible_guard; if (node->rs) { if (node->rs->has_bandwidth) { - this_bw = kb_to_bytes(node->rs->bandwidth); + this_bw = kb_to_bytes(node->rs->bandwidth_kb); } else { /* guess */ - /* XXX024 once consensuses always list bandwidths, we can take - * this guessing business out. -RD */ is_known = 0; - flags = node->rs->is_fast ? 1 : 0; - flags |= is_exit ? 2 : 0; - flags |= is_guard ? 4 : 0; } } else if (node->ri) { /* Must be a bridge if we're willing to use it */ @@ -2022,12 +2304,11 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, bitarray_set(exit_bits, i); if (is_guard) bitarray_set(guard_bits, i); + if (node->is_fast) + bitarray_set(fast_bits, i); + if (is_known) { - bandwidths[i] = (int32_t) this_bw; - /* Casting this_bw to int32_t is safe because both kb_to_bytes - and bridge_get_advertised_bandwidth_bounded limit it to below - INT32_MAX. */ - tor_assert(bandwidths[i] >= 0); + bandwidths[i].dbl = this_bw; if (is_guard) total_guard_bw += this_bw; else @@ -2038,14 +2319,16 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, total_nonexit_bw += this_bw; } else { ++n_unknown; - bandwidths[node_sl_idx] = -flags; + bandwidths[i].dbl = -1.0; } } SMARTLIST_FOREACH_END(node); +#define EPSILON .1 + /* Now, fill in the unknown values. */ if (n_unknown) { int32_t avg_fast, avg_slow; - if (total_exit_bw+total_nonexit_bw) { + if (total_exit_bw+total_nonexit_bw < EPSILON) { /* if there's some bandwidth, there's at least one known router, * so no worries about div by 0 here */ int n_known = smartlist_len(sl)-n_unknown; @@ -2056,26 +2339,27 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, avg_slow = 20000; } for (i=0; i<(unsigned)smartlist_len(sl); ++i) { - int32_t bw = bandwidths[i]; - if (bw>=0) + if (bandwidths[i].dbl >= 0.0) continue; - is_exit = ((-bw)&2); - is_guard = ((-bw)&4); - bandwidths[i] = ((-bw)&1) ? avg_fast : avg_slow; + is_fast = bitarray_is_set(fast_bits, i); + is_exit = bitarray_is_set(exit_bits, i); + is_guard = bitarray_is_set(guard_bits, i); + bandwidths[i].dbl = is_fast ? avg_fast : avg_slow; if (is_exit) - total_exit_bw += bandwidths[i]; + total_exit_bw += bandwidths[i].dbl; else - total_nonexit_bw += bandwidths[i]; + total_nonexit_bw += bandwidths[i].dbl; if (is_guard) - total_guard_bw += bandwidths[i]; + total_guard_bw += bandwidths[i].dbl; else - total_nonguard_bw += bandwidths[i]; + total_nonguard_bw += bandwidths[i].dbl; } } /* If there's no bandwidth at all, pick at random. */ - if (!(total_exit_bw+total_nonexit_bw)) { + if (total_exit_bw+total_nonexit_bw < EPSILON) { tor_free(bandwidths); + tor_free(fast_bits); tor_free(exit_bits); tor_free(guard_bits); return smartlist_choose(sl); @@ -2090,12 +2374,12 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, * For detailed derivation of this formula, see * http://archives.seul.org/or/dev/Jul-2007/msg00056.html */ - if (rule == WEIGHT_FOR_EXIT || !total_exit_bw) + if (rule == WEIGHT_FOR_EXIT || total_exit_bw<EPSILON) exit_weight = 1.0; else exit_weight = 1.0 - all_bw/(3.0*exit_bw); - if (rule == WEIGHT_FOR_GUARD || !total_guard_bw) + if (rule == WEIGHT_FOR_GUARD || total_guard_bw<EPSILON) guard_weight = 1.0; else guard_weight = 1.0 - all_bw/(3.0*guard_bw); @@ -2106,29 +2390,25 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, if (guard_weight <= 0.0) guard_weight = 0.0; - total_bw = 0; sl_last_weighted_bw_of_me = 0; for (i=0; i < (unsigned)smartlist_len(sl); i++) { - uint64_t bw; + tor_assert(bandwidths[i].dbl >= 0.0); + is_exit = bitarray_is_set(exit_bits, i); is_guard = bitarray_is_set(guard_bits, i); if (is_exit && is_guard) - bw = ((uint64_t)(bandwidths[i] * exit_weight * guard_weight)); + bandwidths[i].dbl *= exit_weight * guard_weight; else if (is_guard) - bw = ((uint64_t)(bandwidths[i] * guard_weight)); + bandwidths[i].dbl *= guard_weight; else if (is_exit) - bw = ((uint64_t)(bandwidths[i] * exit_weight)); - else - bw = bandwidths[i]; - total_bw += bw; + bandwidths[i].dbl *= exit_weight; + if (i == (unsigned) me_idx) - sl_last_weighted_bw_of_me = bw; + sl_last_weighted_bw_of_me = (uint64_t) bandwidths[i].dbl; } } - /* XXXX this is a kludge to expose these values. */ - sl_last_total_weighted_bw = total_bw; - +#if 0 log_debug(LD_CIRC, "Total weighted bw = "U64_FORMAT ", exit bw = "U64_FORMAT ", nonexit bw = "U64_FORMAT", exit weight = %f " @@ -2141,56 +2421,26 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, exit_weight, (int)(rule == WEIGHT_FOR_EXIT), U64_PRINTF_ARG(total_guard_bw), U64_PRINTF_ARG(total_nonguard_bw), guard_weight, (int)(rule == WEIGHT_FOR_GUARD)); +#endif - /* 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; - i_chosen = (unsigned)smartlist_len(sl); - i_has_been_chosen = 0; - for (i=0; i < (unsigned)smartlist_len(sl); i++) { - is_exit = bitarray_is_set(exit_bits, i); - is_guard = bitarray_is_set(guard_bits, i); - - /* Weights can be 0 if not counting guards/exits */ - if (is_exit && is_guard) - tmp += ((uint64_t)(bandwidths[i] * exit_weight * guard_weight)); - else if (is_guard) - tmp += ((uint64_t)(bandwidths[i] * guard_weight)); - else if (is_exit) - tmp += ((uint64_t)(bandwidths[i] * exit_weight)); - else - tmp += bandwidths[i]; + scale_array_elements_to_u64(bandwidths, smartlist_len(sl), + &sl_last_total_weighted_bw); - if (tmp >= rand_bw && !i_has_been_chosen) { - i_chosen = i; - i_has_been_chosen = 1; - } - } - i = i_chosen; - 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. " - U64_FORMAT " " U64_FORMAT " " U64_FORMAT, U64_PRINTF_ARG(tmp), - U64_PRINTF_ARG(rand_bw), U64_PRINTF_ARG(total_bw)); + { + int idx = choose_array_element_by_weight(bandwidths, + smartlist_len(sl)); + tor_free(bandwidths); + tor_free(fast_bits); + tor_free(exit_bits); + tor_free(guard_bits); + return idx < 0 ? NULL : smartlist_get(sl, idx); } - tor_free(bandwidths); - tor_free(exit_bits); - tor_free(guard_bits); - return smartlist_get(sl, i); } /** Choose a random element of status list <b>sl</b>, weighted by * the advertised bandwidth of each node */ const node_t * -node_sl_choose_by_bandwidth(smartlist_t *sl, +node_sl_choose_by_bandwidth(const smartlist_t *sl, bandwidth_weight_rule_t rule) { /*XXXX MOVE */ const node_t *ret; @@ -2337,7 +2587,7 @@ hex_digest_nickname_decode(const char *hexdigest, * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b> * (which is optionally prefixed with a single dollar sign). Return false if * <b>hexdigest</b> is malformed, or it doesn't match. */ -static int +int hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest, const char *nickname, int is_named) { @@ -2372,154 +2622,6 @@ router_is_named(const routerinfo_t *router) tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN)); } -/** Return true iff the digest of <b>router</b>'s identity key, - * encoded in hexadecimal, matches <b>hexdigest</b> (which is - * optionally prefixed with a single dollar sign). Return false if - * <b>hexdigest</b> is malformed, or it doesn't match. */ -static INLINE int -router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest) -{ - return hex_digest_nickname_matches(hexdigest, - router->cache_info.identity_digest, - router->nickname, - router_is_named(router)); -} - -/** Return true if <b>router</b>'s nickname matches <b>nickname</b> - * (case-insensitive), or if <b>router's</b> identity key digest - * matches a hexadecimal value stored in <b>nickname</b>. Return - * false otherwise. */ -static int -router_nickname_matches(const routerinfo_t *router, const char *nickname) -{ - if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname)) - return 1; - return router_hex_digest_matches(router, nickname); -} - -/** Return true if <b>node</b>'s nickname matches <b>nickname</b> - * (case-insensitive), or if <b>node's</b> identity key digest - * matches a hexadecimal value stored in <b>nickname</b>. Return - * false otherwise. */ -static int -node_nickname_matches(const node_t *node, const char *nickname) -{ - const char *n = node_get_nickname(node); - if (n && nickname[0]!='$' && !strcasecmp(n, nickname)) - return 1; - return hex_digest_nickname_matches(nickname, - node->identity, - n, - node_is_named(node)); -} - -/** Return the router in our routerlist whose (case-insensitive) - * nickname or (case-sensitive) hexadecimal key digest is - * <b>nickname</b>. Return NULL if no such router is known. - */ -const routerinfo_t * -router_get_by_nickname(const char *nickname, int warn_if_unnamed) -{ -#if 1 - const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed); - if (node) - return node->ri; - else - return NULL; -#else - int maybedigest; - char digest[DIGEST_LEN]; - routerinfo_t *best_match=NULL; - int n_matches = 0; - const char *named_digest = NULL; - - tor_assert(nickname); - if (!routerlist) - return NULL; - if (nickname[0] == '$') - return router_get_by_hexdigest(nickname); - if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME)) - return NULL; - - maybedigest = (strlen(nickname) >= HEX_DIGEST_LEN) && - (base16_decode(digest,DIGEST_LEN,nickname,HEX_DIGEST_LEN) == 0); - - if ((named_digest = networkstatus_get_router_digest_by_nickname(nickname))) { - return rimap_get(routerlist->identity_map, named_digest); - } - if (networkstatus_nickname_is_unnamed(nickname)) - return NULL; - - /* If we reach this point, there's no canonical value for the nickname. */ - - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, - { - if (!strcasecmp(router->nickname, nickname)) { - ++n_matches; - if (n_matches <= 1 || router->is_running) - best_match = router; - } else if (maybedigest && - tor_memeq(digest, router->cache_info.identity_digest, - DIGEST_LEN)) { - if (router_hex_digest_matches(router, nickname)) - return router; - /* If we reach this point, we have a ID=name syntax that matches the - * identity but not the name. That isn't an acceptable match. */ - } - }); - - if (best_match) { - if (warn_if_unnamed && n_matches > 1) { - smartlist_t *fps = smartlist_new(); - int any_unwarned = 0; - SMARTLIST_FOREACH_BEGIN(routerlist->routers, routerinfo_t *, router) { - routerstatus_t *rs; - char fp[HEX_DIGEST_LEN+1]; - if (strcasecmp(router->nickname, nickname)) - continue; - rs = router_get_mutable_consensus_status_by_id( - router->cache_info.identity_digest); - if (rs && !rs->name_lookup_warned) { - rs->name_lookup_warned = 1; - any_unwarned = 1; - } - base16_encode(fp, sizeof(fp), - router->cache_info.identity_digest, DIGEST_LEN); - smartlist_add_asprintf(fps, "\"$%s\" for the one at %s:%d", - fp, router->address, router->or_port); - } SMARTLIST_FOREACH_END(router); - if (any_unwarned) { - char *alternatives = smartlist_join_strings(fps, "; ",0,NULL); - log_warn(LD_CONFIG, - "There are multiple matches for the nickname \"%s\"," - " but none is listed as named by the directory authorities. " - "Choosing one arbitrarily. If you meant one in particular, " - "you should say %s.", nickname, alternatives); - tor_free(alternatives); - } - SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp)); - smartlist_free(fps); - } else if (warn_if_unnamed) { - routerstatus_t *rs = router_get_mutable_consensus_status_by_id( - best_match->cache_info.identity_digest); - if (rs && !rs->name_lookup_warned) { - char fp[HEX_DIGEST_LEN+1]; - base16_encode(fp, sizeof(fp), - best_match->cache_info.identity_digest, DIGEST_LEN); - log_warn(LD_CONFIG, "You specified a server \"%s\" by name, but this " - "name is not registered, so it could be used by any server, " - "not just the one you meant. " - "To make sure you get the same server in the future, refer to " - "it by key, as \"$%s\".", nickname, fp); - rs->name_lookup_warned = 1; - } - } - return best_match; - } - return NULL; -#endif -} - /** Return true iff <b>digest</b> is the digest of the identity key of a * trusted directory matching at least one bit of <b>type</b>. If <b>type</b> * is zero, any authority is okay. */ @@ -2530,7 +2632,7 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type) return 0; if (authdir_mode(get_options()) && router_digest_is_me(digest)) return 1; - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent, + SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ent, if (tor_memeq(digest, ent->digest, DIGEST_LEN)) { return (!type) || ((type & ent->type) != 0); }); @@ -2544,7 +2646,7 @@ router_addr_is_trusted_dir(uint32_t addr) { if (!trusted_dir_servers) return 0; - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent, + SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ent, if (ent->addr == addr) return 1; ); @@ -2566,18 +2668,6 @@ hexdigest_to_digest(const char *hexdigest, char *digest) return 0; } -/** Return the router in our routerlist whose hexadecimal key digest - * is <b>hexdigest</b>. Return NULL if no such router is known. */ -const routerinfo_t * -router_get_by_hexdigest(const char *hexdigest) -{ - if (is_legal_nickname(hexdigest)) - return NULL; - - /* It's not a legal nickname, so it must be a hexdigest or nothing. */ - return router_get_by_nickname(hexdigest, 1); -} - /** As router_get_by_id_digest,but return a pointer that you're allowed to * modify */ routerinfo_t * @@ -2752,6 +2842,7 @@ routerinfo_free(routerinfo_t *router) tor_free(router->contact_info); if (router->onion_pkey) crypto_pk_free(router->onion_pkey); + tor_free(router->onion_curve25519_pkey); if (router->identity_pkey) crypto_pk_free(router->identity_pkey); if (router->declared_family) { @@ -2759,6 +2850,7 @@ routerinfo_free(routerinfo_t *router) smartlist_free(router->declared_family); } addr_policy_list_free(router->exit_policy); + short_policy_free(router->ipv6_exit_policy); memset(router, 77, sizeof(routerinfo_t)); @@ -2809,7 +2901,7 @@ signed_descriptor_from_routerinfo(routerinfo_t *ri) /** Helper: free the storage held by the extrainfo_t in <b>e</b>. */ static void -_extrainfo_free(void *e) +extrainfo_free_(void *e) { extrainfo_free(e); } @@ -2823,7 +2915,7 @@ routerlist_free(routerlist_t *rl) rimap_free(rl->identity_map, NULL); sdmap_free(rl->desc_digest_map, NULL); sdmap_free(rl->desc_by_eid_map, NULL); - eimap_free(rl->extra_info_map, _extrainfo_free); + eimap_free(rl->extra_info_map, extrainfo_free_); SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r, routerinfo_free(r)); SMARTLIST_FOREACH(rl->old_routers, signed_descriptor_t *, sd, @@ -2853,7 +2945,7 @@ dump_routerlist_mem_usage(int severity) SMARTLIST_FOREACH(routerlist->old_routers, signed_descriptor_t *, sd, olddescs += sd->signed_descriptor_len); - log(severity, LD_DIR, + tor_log(severity, LD_DIR, "In %d live descriptors: "U64_FORMAT" bytes. " "In %d old descriptors: "U64_FORMAT" bytes.", smartlist_len(routerlist->routers), U64_PRINTF_ARG(livedescs), @@ -2865,7 +2957,7 @@ dump_routerlist_mem_usage(int severity) * <b>ri</b>. Return the index of <b>ri</b> in <b>sl</b>, or -1 if <b>ri</b> * is not in <b>sl</b>. */ static INLINE int -_routerlist_find_elt(smartlist_t *sl, void *ri, int idx) +routerlist_find_elt_(smartlist_t *sl, void *ri, int idx) { if (idx < 0) { idx = -1; @@ -2921,7 +3013,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri) &ri->cache_info); smartlist_add(rl->routers, ri); ri->cache_info.routerlist_index = smartlist_len(rl->routers) - 1; - nodelist_add_routerinfo(ri); + nodelist_set_routerinfo(ri, NULL); router_dir_info_changed(); #ifdef DEBUG_ROUTERLIST routerlist_assert_ok(rl); @@ -3150,8 +3242,11 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, tor_assert(0 <= idx && idx < smartlist_len(rl->routers)); tor_assert(smartlist_get(rl->routers, idx) == ri_old); - nodelist_remove_routerinfo(ri_old); - nodelist_add_routerinfo(ri_new); + { + routerinfo_t *ri_old_tmp=NULL; + nodelist_set_routerinfo(ri_new, &ri_old_tmp); + tor_assert(ri_old == ri_old_tmp); + } router_dir_info_changed(); if (idx >= 0) { @@ -3159,7 +3254,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, ri_old->cache_info.routerlist_index = -1; ri_new->cache_info.routerlist_index = idx; /* Check that ri_old is not in rl->routers anymore: */ - tor_assert( _routerlist_find_elt(rl->routers, ri_old, -1) == -1 ); + tor_assert( routerlist_find_elt_(rl->routers, ri_old, -1) == -1 ); } else { log_warn(LD_BUG, "Appending entry from routerlist_replace."); routerlist_insert(rl, ri_new); @@ -3263,20 +3358,12 @@ routerlist_free_all(void) smartlist_free(warned_nicknames); warned_nicknames = NULL; } - if (trusted_dir_servers) { - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, - trusted_dir_server_free(ds)); - smartlist_free(trusted_dir_servers); - trusted_dir_servers = NULL; - } + clear_dir_servers(); + smartlist_free(trusted_dir_servers); + smartlist_free(fallback_dir_servers); + trusted_dir_servers = fallback_dir_servers = NULL; if (trusted_dir_certs) { - DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) { - SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert, - authority_cert_free(cert)); - smartlist_free(cl->certs); - tor_free(cl); - } DIGESTMAP_FOREACH_END; - digestmap_free(trusted_dir_certs, NULL); + digestmap_free(trusted_dir_certs, cert_list_free_); trusted_dir_certs = NULL; } } @@ -3294,33 +3381,6 @@ routerlist_reset_warnings(void) networkstatus_reset_warnings(); } -/** Mark the router with ID <b>digest</b> as running or non-running - * in our routerlist. */ -void -router_set_status(const char *digest, int up) -{ - node_t *node; - tor_assert(digest); - - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d, - if (tor_memeq(d->digest, digest, DIGEST_LEN)) - d->is_running = up); - - node = node_get_mutable_by_id(digest); - if (node) { -#if 0 - log_debug(LD_DIR,"Marking router %s as %s.", - node_describe(node), up ? "up" : "down"); -#endif - if (!up && node_is_me(node) && !net_is_disabled()) - log_warn(LD_NET, "We just marked ourself as down. Are your external " - "addresses reachable?"); - node->is_running = up; - } - - router_dir_info_changed(); -} - /** Add <b>router</b> to the routerlist, if we don't already have it. Replace * older entries (if any) with the same key. Note: Callers should not hold * their pointers to <b>router</b> if this function fails; <b>router</b> @@ -3488,11 +3548,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, /* Same key, and either new, or listed in the consensus. */ log_debug(LD_DIR, "Replacing entry for router %s", router_describe(router)); - if (routers_have_same_or_addr(router, old_router)) { - /* these carry over when the address and orport are unchanged. */ - router->last_reachable = old_router->last_reachable; - router->testing_since = old_router->testing_since; - } routerlist_replace(routerlist, old_router, router); if (!from_cache) { signed_desc_append_to_journal(&router->cache_info, @@ -3553,7 +3608,7 @@ router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg, * signed_descriptor_t* in *<b>a</b> has an identity digest preceding, equal * to, or later than that of *<b>b</b>. */ static int -_compare_old_routers_by_identity(const void **_a, const void **_b) +compare_old_routers_by_identity_(const void **_a, const void **_b) { int i; const signed_descriptor_t *r1 = *_a, *r2 = *_b; @@ -3573,7 +3628,7 @@ struct duration_idx_t { /** Sorting helper: compare two duration_idx_t by their duration. */ static int -_compare_duration_idx(const void *_d1, const void *_d2) +compare_duration_idx_(const void *_d1, const void *_d2) { const struct duration_idx_t *d1 = _d1; const struct duration_idx_t *d2 = _d2; @@ -3626,7 +3681,7 @@ routerlist_remove_old_cached_routers_with_id(time_t now, signed_descriptor_t *r_next; lifespans[i-lo].idx = i; if (r->last_listed_as_valid_until >= now || - (retain && digestset_isin(retain, r->signed_descriptor_digest))) { + (retain && digestset_contains(retain, r->signed_descriptor_digest))) { must_keep[i-lo] = 1; } if (i < hi) { @@ -3650,7 +3705,7 @@ routerlist_remove_old_cached_routers_with_id(time_t now, * the duration of liveness, and remove the ones we're not already going to * remove based on how long they were alive. **/ - qsort(lifespans, n, sizeof(struct duration_idx_t), _compare_duration_idx); + qsort(lifespans, n, sizeof(struct duration_idx_t), compare_duration_idx_); for (i = 0; i < n && n_rmv < n_extra; ++i) { if (!must_keep[lifespans[i].idx-lo] && !lifespans[i].old) { rmv[lifespans[i].idx-lo] = 1; @@ -3760,7 +3815,7 @@ routerlist_remove_old_routers(void) router = smartlist_get(routerlist->routers, i); if (router->cache_info.published_on <= cutoff && router->cache_info.last_listed_as_valid_until < now && - !digestset_isin(retain, + !digestset_contains(retain, router->cache_info.signed_descriptor_digest)) { /* Too old: remove it. (If we're a cache, just move it into * old_routers.) */ @@ -3781,7 +3836,7 @@ routerlist_remove_old_routers(void) sd = smartlist_get(routerlist->old_routers, i); if (sd->published_on <= cutoff && sd->last_listed_as_valid_until < now && - !digestset_isin(retain, sd->signed_descriptor_digest)) { + !digestset_contains(retain, sd->signed_descriptor_digest)) { /* Too old. Remove it. */ routerlist_remove_old(routerlist, sd, i--); } @@ -3804,7 +3859,7 @@ routerlist_remove_old_routers(void) goto done; /* Sort by identity, then fix indices. */ - smartlist_sort(routerlist->old_routers, _compare_old_routers_by_identity); + smartlist_sort(routerlist->old_routers, compare_old_routers_by_identity_); /* Fix indices. */ for (i = 0; i < smartlist_len(routerlist->old_routers); ++i) { signed_descriptor_t *r = smartlist_get(routerlist->old_routers, i); @@ -3960,7 +4015,7 @@ router_load_routers_from_string(const char *s, const char *eos, ri->cache_info.signed_descriptor_digest : ri->cache_info.identity_digest, DIGEST_LEN); - if (smartlist_string_isin(requested_fingerprints, fp)) { + if (smartlist_contains_string(requested_fingerprints, fp)) { smartlist_string_remove(requested_fingerprints, fp); } else { char *requested = @@ -4099,27 +4154,6 @@ routerlist_retry_directory_downloads(time_t now) update_all_descriptor_downloads(now); } -/** Return 1 if all running sufficiently-stable routers we can use will reject - * addr:port, return 0 if any might accept it. */ -int -router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port, - int need_uptime) -{ /* XXXX MOVE */ - addr_policy_result_t r; - - SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { - if (node->is_running && - !node_is_unreliable(node, need_uptime, 0, 0)) { - - r = compare_tor_addr_to_node_policy(addr, port, node); - - if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED) - return 0; /* this one could be ok. good enough. */ - } - } SMARTLIST_FOREACH_END(node); - return 1; /* all will reject. */ -} - /** Return true iff <b>router</b> does not permit exit streams. */ int @@ -4128,47 +4162,47 @@ router_exit_policy_rejects_all(const routerinfo_t *router) return router->policy_is_reject_star; } -/** Add to the list of authoritative directory servers one at - * <b>address</b>:<b>port</b>, with identity key <b>digest</b>. If - * <b>address</b> is NULL, add ourself. Return the new trusted directory - * server entry on success or NULL if we couldn't add it. */ -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, - dirinfo_type_t type) -{ - trusted_dir_server_t *ent; +/** Create an directory server at <b>address</b>:<b>port</b>, with OR identity + * key <b>digest</b>. If <b>address</b> is NULL, add ourself. If + * <b>is_authority</b>, this is a directory authority. Return the new + * directory server entry on success or NULL on failure. */ +static dir_server_t * +dir_server_new(int is_authority, + const char *nickname, + const tor_addr_t *addr, + const char *hostname, + uint16_t dir_port, uint16_t or_port, + const char *digest, const char *v3_auth_digest, + dirinfo_type_t type, + double weight) +{ + dir_server_t *ent; uint32_t a; - char *hostname = NULL; - if (!trusted_dir_servers) - trusted_dir_servers = smartlist_new(); + char *hostname_ = NULL; - if (!address) { /* The address is us; we should guess. */ - if (resolve_my_address(LOG_WARN, get_options(), &a, &hostname) < 0) { - log_warn(LD_CONFIG, - "Couldn't find a suitable address when adding ourself as a " - "trusted directory server."); - return NULL; - } - } else { - if (tor_lookup_hostname(address, &a)) { - log_warn(LD_CONFIG, - "Unable to lookup address for directory server at '%s'", - address); - return NULL; - } - hostname = tor_strdup(address); - } + if (weight < 0) + return NULL; + + if (tor_addr_family(addr) == AF_INET) + a = tor_addr_to_ipv4h(addr); + else + return NULL; /*XXXX Support IPv6 */ + + if (!hostname) + hostname_ = tor_dup_addr(addr); + else + hostname_ = tor_strdup(hostname); - ent = tor_malloc_zero(sizeof(trusted_dir_server_t)); + ent = tor_malloc_zero(sizeof(dir_server_t)); ent->nickname = nickname ? tor_strdup(nickname) : NULL; - ent->address = hostname; + ent->address = hostname_; ent->addr = a; ent->dir_port = dir_port; ent->or_port = or_port; ent->is_running = 1; + ent->is_authority = is_authority; ent->type = type; + ent->weight = weight; memcpy(ent->digest, digest, DIGEST_LEN); if (v3_auth_digest && (type & V3_DIRINFO)) memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN); @@ -4190,14 +4224,78 @@ add_trusted_dir_server(const char *nickname, const char *address, ent->fake_status.dir_port = ent->dir_port; ent->fake_status.or_port = ent->or_port; - if (ent->or_port) - ent->fake_status.version_supports_begindir = 1; + return ent; +} + +/** Create an authoritative directory server at + * <b>address</b>:<b>port</b>, with identity key <b>digest</b>. If + * <b>address</b> is NULL, add ourself. Return the new trusted directory + * server entry on success or NULL if we couldn't add it. */ +dir_server_t * +trusted_dir_server_new(const char *nickname, const char *address, + uint16_t dir_port, uint16_t or_port, + const char *digest, const char *v3_auth_digest, + dirinfo_type_t type, double weight) +{ + uint32_t a; + tor_addr_t addr; + char *hostname=NULL; + dir_server_t *result; + + if (!address) { /* The address is us; we should guess. */ + if (resolve_my_address(LOG_WARN, get_options(), + &a, NULL, &hostname) < 0) { + log_warn(LD_CONFIG, + "Couldn't find a suitable address when adding ourself as a " + "trusted directory server."); + return NULL; + } + if (!hostname) + hostname = tor_dup_ip(a); + } else { + if (tor_lookup_hostname(address, &a)) { + log_warn(LD_CONFIG, + "Unable to lookup address for directory server at '%s'", + address); + return NULL; + } + hostname = tor_strdup(address); + } + tor_addr_from_ipv4h(&addr, a); + + result = dir_server_new(1, nickname, &addr, hostname, + dir_port, or_port, digest, + v3_auth_digest, type, weight); + tor_free(hostname); + return result; +} + +/** Return a new dir_server_t for a fallback directory server at + * <b>addr</b>:<b>or_port</b>/<b>dir_port</b>, with identity key digest + * <b>id_digest</b> */ +dir_server_t * +fallback_dir_server_new(const tor_addr_t *addr, + uint16_t dir_port, uint16_t or_port, + const char *id_digest, double weight) +{ + return dir_server_new(0, NULL, addr, NULL, dir_port, or_port, id_digest, + NULL, ALL_DIRINFO, weight); +} + +/** Add a directory server to the global list(s). */ +void +dir_server_add(dir_server_t *ent) +{ + if (!trusted_dir_servers) + trusted_dir_servers = smartlist_new(); + if (!fallback_dir_servers) + fallback_dir_servers = smartlist_new(); - ent->fake_status.version_supports_conditional_consensus = 1; + if (ent->is_authority) + smartlist_add(trusted_dir_servers, ent); - smartlist_add(trusted_dir_servers, ent); + smartlist_add(fallback_dir_servers, ent); router_dir_info_changed(); - return ent; } /** Free storage held in <b>cert</b>. */ @@ -4216,7 +4314,7 @@ authority_cert_free(authority_cert_t *cert) /** Free storage held in <b>ds</b>. */ static void -trusted_dir_server_free(trusted_dir_server_t *ds) +dir_server_free(dir_server_t *ds) { if (!ds) return; @@ -4227,13 +4325,18 @@ trusted_dir_server_free(trusted_dir_server_t *ds) tor_free(ds); } -/** Remove all members from the list of trusted dir servers. */ +/** Remove all members from the list of dir servers. */ void -clear_trusted_dir_servers(void) +clear_dir_servers(void) { + if (fallback_dir_servers) { + SMARTLIST_FOREACH(fallback_dir_servers, dir_server_t *, ent, + dir_server_free(ent)); + smartlist_clear(fallback_dir_servers); + } else { + fallback_dir_servers = smartlist_new(); + } if (trusted_dir_servers) { - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent, - trusted_dir_server_free(ent)); smartlist_clear(trusted_dir_servers); } else { trusted_dir_servers = smartlist_new(); @@ -4241,17 +4344,6 @@ clear_trusted_dir_servers(void) router_dir_info_changed(); } -/** Return 1 if any trusted dir server supports v1 directories, - * else return 0. */ -int -any_trusted_dir_is_v1_authority(void) -{ - if (trusted_dir_servers) - return get_n_authorities(V1_DIRINFO) > 0; - - return 0; -} - /** For every current directory connection whose purpose is <b>purpose</b>, * and where the resource being downloaded begins with <b>prefix</b>, split * rest of the resource into base16 fingerprints (or base64 fingerprints if @@ -4314,6 +4406,41 @@ list_pending_microdesc_downloads(digestmap_t *result) list_pending_downloads(result, DIR_PURPOSE_FETCH_MICRODESC, "d/"); } +/** For every certificate we are currently downloading by (identity digest, + * signing key digest) pair, set result[fp_pair] to (void *1). + */ +static void +list_pending_fpsk_downloads(fp_pair_map_t *result) +{ + const char *pfx = "fp-sk/"; + smartlist_t *tmp; + smartlist_t *conns; + const char *resource; + + tor_assert(result); + + tmp = smartlist_new(); + conns = get_connection_array(); + + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { + if (conn->type == CONN_TYPE_DIR && + conn->purpose == DIR_PURPOSE_FETCH_CERTIFICATE && + !conn->marked_for_close) { + resource = TO_DIR_CONN(conn)->requested_resource; + if (!strcmpstart(resource, pfx)) + dir_split_resource_into_fingerprint_pairs(resource + strlen(pfx), + tmp); + } + } SMARTLIST_FOREACH_END(conn); + + SMARTLIST_FOREACH_BEGIN(tmp, fp_pair_t *, fp) { + fp_pair_map_set(result, fp, (void*)1); + tor_free(fp); + } SMARTLIST_FOREACH_END(fp); + + smartlist_free(tmp); +} + /** Launch downloads for all the descriptors whose digests or digests256 * are listed as digests[i] for lo <= i < hi. (Lo and hi may be out of * range.) If <b>source</b> is given, download from <b>source</b>; @@ -4369,7 +4496,7 @@ initiate_descriptor_downloads(const routerstatus_t *source, /* We know which authority we want. */ directory_initiate_command_routerstatus(source, purpose, ROUTER_PURPOSE_GENERAL, - 0, /* not private */ + DIRIND_ONEHOP, resource, NULL, 0, 0); } else { directory_get_from_dirserver(purpose, ROUTER_PURPOSE_GENERAL, resource, @@ -4378,30 +4505,6 @@ initiate_descriptor_downloads(const routerstatus_t *source, tor_free(resource); } -/** Return 0 if this routerstatus is obsolete, too new, isn't - * running, or otherwise not a descriptor that we would make any - * use of even if we had it. Else return 1. */ -static INLINE int -client_would_use_router(const routerstatus_t *rs, time_t now, - const or_options_t *options) -{ - if (!rs->is_flagged_running && !options->FetchUselessDescriptors) { - /* If we had this router descriptor, we wouldn't even bother using it. - * But, if we want to have a complete list, fetch it anyway. */ - return 0; - } - if (rs->published_on + options->TestingEstimatedDescriptorPropagationTime - > now) { - /* Most caches probably don't have this descriptor yet. */ - return 0; - } - if (rs->published_on + OLD_ROUTER_DESC_MAX_AGE < now) { - /* We'd drop it immediately for being too old. */ - return 0; - } - return 1; -} - /** Max amount of hashes to download per request. * Since squid does not like URLs >= 4096 bytes we limit it to 96. * 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058 @@ -4471,11 +4574,6 @@ launch_descriptor_downloads(int purpose, } } } - /* XXX should we consider having even the dir mirrors delay - * a little bit, so we don't load the authorities as much? -RD - * I don't think so. If we do, clients that want those descriptors may - * not actually find them if the caches haven't got them yet. -NM - */ if (! should_delay && n_downloadable) { int i, n_per_request; @@ -4515,9 +4613,9 @@ launch_descriptor_downloads(int purpose, rtr_plural = "s"; log_info(LD_DIR, - "Launching %d request%s for %d router%s, %d at a time", - CEIL_DIV(n_downloadable, n_per_request), - req_plural, n_downloadable, rtr_plural, n_per_request); + "Launching %d request%s for %d %s%s, %d at a time", + CEIL_DIV(n_downloadable, n_per_request), req_plural, + n_downloadable, descname, rtr_plural, n_per_request); smartlist_sort_digests(downloadable); for (i=0; i < n_downloadable; i += n_per_request) { initiate_descriptor_downloads(source, purpose, @@ -4568,7 +4666,7 @@ update_router_descriptor_cache_downloads_v2(time_t now) */ n_download = 0; SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) { - trusted_dir_server_t *ds; + dir_server_t *ds; smartlist_t *dl; dl = downloadable[ns_sl_idx] = smartlist_new(); download_from[ns_sl_idx] = smartlist_new(); @@ -4643,7 +4741,7 @@ update_router_descriptor_cache_downloads_v2(time_t now) /* Now, we can actually launch our requests. */ for (i=0; i<n; ++i) { networkstatus_v2_t *ns = smartlist_get(networkstatus_v2_list, i); - trusted_dir_server_t *ds = + dir_server_t *ds = router_get_trusteddirserver_by_digest(ns->identity_digest); smartlist_t *dl = download_from[i]; int pds_flags = PDS_RETRY_IF_NO_SERVERS; @@ -4696,7 +4794,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, if (is_vote) { /* where's it from, so we know whom to ask for descriptors */ - trusted_dir_server_t *ds; + 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); @@ -4720,7 +4818,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, sd->signed_descriptor_digest, DIGEST_LEN)) { /* We have a descriptor with this digest, but either there is no * entry in routerlist with the same ID (!ri), or there is one, - * but the identity digest differs (memcmp). + * but the identity digest differs (memneq). */ smartlist_add(no_longer_old, sd); ++n_in_oldrouters; /* We have it in old_routers. */ @@ -4919,230 +5017,6 @@ update_extrainfo_downloads(time_t now) smartlist_free(wanted); } -/** True iff, the last time we checked whether we had enough directory info - * to build circuits, the answer was "yes". */ -static int have_min_dir_info = 0; -/** True iff enough has changed since the last time we checked whether we had - * enough directory info to build circuits that our old answer can no longer - * be trusted. */ -static int need_to_update_have_min_dir_info = 1; -/** String describing what we're missing before we have enough directory - * info. */ -static char dir_info_status[128] = ""; - -/** Return true iff we have enough networkstatus and router information to - * start building circuits. Right now, this means "more than half the - * networkstatus documents, and at least 1/4 of expected routers." */ -//XXX should consider whether we have enough exiting nodes here. -int -router_have_minimum_dir_info(void) -{ - if (PREDICT_UNLIKELY(need_to_update_have_min_dir_info)) { - update_router_have_minimum_dir_info(); - need_to_update_have_min_dir_info = 0; - } - return have_min_dir_info; -} - -/** Called when our internal view of the directory has changed. This can be - * when the authorities change, networkstatuses change, the list of routerdescs - * changes, or number of running routers changes. - */ -void -router_dir_info_changed(void) -{ - need_to_update_have_min_dir_info = 1; - rend_hsdir_routers_changed(); -} - -/** Return a string describing what we're missing before we have enough - * directory info. */ -const char * -get_dir_info_status_string(void) -{ - return dir_info_status; -} - -/** 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>. If <b>in_set</b> is non-NULL, only consider those - * routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes - * with the Exit flag. - */ -static void -count_usable_descriptors(int *num_present, int *num_usable, - const networkstatus_t *consensus, - const or_options_t *options, time_t now, - routerset_t *in_set, int exit_only) -{ - const int md = (consensus->flavor == FLAV_MICRODESC); - *num_present = 0, *num_usable=0; - - SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs) - { - if (exit_only && ! rs->is_exit) - continue; - if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1)) - continue; - if (client_would_use_router(rs, now, options)) { - const char * const digest = rs->descriptor_digest; - int present; - ++*num_usable; /* the consensus says we want it. */ - if (md) - present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest); - else - present = NULL != router_get_by_descriptor_digest(digest); - if (present) { - /* we have the descriptor listed in the consensus. */ - ++*num_present; - } - } - } - SMARTLIST_FOREACH_END(rs); - - log_debug(LD_DIR, "%d usable, %d present.", *num_usable, *num_present); -} - -/** We just fetched a new set of descriptors. Compute how far through - * the "loading descriptors" bootstrapping phase we are, so we can inform - * the controller of our progress. */ -int -count_loading_descriptors_progress(void) -{ - int num_present = 0, num_usable=0; - time_t now = time(NULL); - const networkstatus_t *consensus = - networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor()); - double fraction; - - if (!consensus) - return 0; /* can't count descriptors if we have no list of them */ - - count_usable_descriptors(&num_present, &num_usable, - consensus, get_options(), now, NULL, 0); - - if (num_usable == 0) - return 0; /* don't div by 0 */ - fraction = num_present / (num_usable/4.); - if (fraction > 1.0) - return 0; /* it's not the number of descriptors holding us back */ - return BOOTSTRAP_STATUS_LOADING_DESCRIPTORS + (int) - (fraction*(BOOTSTRAP_STATUS_CONN_OR-1 - - BOOTSTRAP_STATUS_LOADING_DESCRIPTORS)); -} - -/** Change the value of have_min_dir_info, setting it true iff we have enough - * network and router information to build circuits. Clear the value of - * need_to_update_have_min_dir_info. */ -static void -update_router_have_minimum_dir_info(void) -{ - int num_present = 0, num_usable=0; - int num_exit_present = 0, num_exit_usable = 0; - time_t now = time(NULL); - int res; - const or_options_t *options = get_options(); - const networkstatus_t *consensus = - networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor()); - int using_md; - - if (!consensus) { - if (!networkstatus_get_latest_consensus()) - strlcpy(dir_info_status, "We have no usable consensus.", - sizeof(dir_info_status)); - else - strlcpy(dir_info_status, "We have no recent usable consensus.", - sizeof(dir_info_status)); - res = 0; - goto done; - } - - if (should_delay_dir_fetches(get_options())) { - log_notice(LD_DIR, "no known bridge descriptors running yet; stalling"); - strlcpy(dir_info_status, "No live bridge descriptors.", - sizeof(dir_info_status)); - res = 0; - goto done; - } - - using_md = consensus->flavor == FLAV_MICRODESC; - - count_usable_descriptors(&num_present, &num_usable, consensus, options, now, - NULL, 0); - count_usable_descriptors(&num_exit_present, &num_exit_usable, - consensus, options, now, options->ExitNodes, 1); - -/* What fraction of desired server descriptors do we need before we will - * build circuits? */ -#define FRAC_USABLE_NEEDED .75 -/* What fraction of desired _exit_ server descriptors do we need before we - * will build circuits? */ -#define FRAC_EXIT_USABLE_NEEDED .5 - - if (num_present < num_usable * FRAC_USABLE_NEEDED) { - tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable %sdescriptors.", - num_present, num_usable, using_md ? "micro" : ""); - res = 0; - control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); - goto done; - } else if (num_present < 2) { - tor_snprintf(dir_info_status, sizeof(dir_info_status), - "Only %d %sdescriptor%s here and believed reachable!", - num_present, using_md ? "micro" : "", num_present ? "" : "s"); - res = 0; - goto done; - } else if (num_exit_present < num_exit_usable * FRAC_EXIT_USABLE_NEEDED) { - tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable exit node descriptors.", - num_exit_present, num_exit_usable); - res = 0; - control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); - goto done; - } - - /* Check for entry nodes. */ - if (options->EntryNodes) { - count_usable_descriptors(&num_present, &num_usable, consensus, options, - now, options->EntryNodes, 0); - - if (!num_usable || !num_present) { - tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable entry node %sdescriptors.", - num_present, num_usable, using_md?"micro":""); - res = 0; - goto done; - } - } - - res = 1; - - done: - if (res && !have_min_dir_info) { - log(LOG_NOTICE, LD_DIR, - "We now have enough directory information to build circuits."); - control_event_client_status(LOG_NOTICE, "ENOUGH_DIR_INFO"); - control_event_bootstrap(BOOTSTRAP_STATUS_CONN_OR, 0); - } - if (!res && have_min_dir_info) { - int quiet = directory_too_idle_to_fetch_descriptors(options, now); - 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; - need_to_update_have_min_dir_info = 0; -} - /** Reset the descriptor download failure count on all routers, so that we * can retry any long-failed routers immediately. */ @@ -5195,8 +5069,8 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2) r1->ipv6_orport != r2->ipv6_orport || r1->dir_port != r2->dir_port || r1->purpose != r2->purpose || - crypto_pk_cmp_keys(r1->onion_pkey, r2->onion_pkey) || - crypto_pk_cmp_keys(r1->identity_pkey, r2->identity_pkey) || + !crypto_pk_eq_keys(r1->onion_pkey, r2->onion_pkey) || + !crypto_pk_eq_keys(r1->identity_pkey, r2->identity_pkey) || strcasecmp(r1->platform, r2->platform) || (r1->contact_info && !r2->contact_info) || /* contact_info is optional */ (!r1->contact_info && r2->contact_info) || @@ -5441,7 +5315,7 @@ esc_router_info(const routerinfo_t *router) /** Helper for sorting: compare two routerinfos by their identity * digest. */ static int -_compare_routerinfo_by_id_digest(const void **a, const void **b) +compare_routerinfo_by_id_digest_(const void **a, const void **b) { routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; return fast_memcmp(first->cache_info.identity_digest, @@ -5453,153 +5327,10 @@ _compare_routerinfo_by_id_digest(const void **a, const void **b) void routers_sort_by_identity(smartlist_t *routers) { - smartlist_sort(routers, _compare_routerinfo_by_id_digest); -} - -/** A routerset specifies constraints on a set of possible routerinfos, based - * on their names, identities, or addresses. It is optimized for determining - * whether a router is a member or not, in O(1+P) time, where P is the number - * of address policy constraints. */ -struct routerset_t { - /** A list of strings for the elements of the policy. Each string is either - * a nickname, a hexadecimal identity fingerprint, or an address policy. A - * router belongs to the set if its nickname OR its identity OR its address - * matches an entry here. */ - smartlist_t *list; - /** A map from lowercase nicknames of routers in the set to (void*)1 */ - strmap_t *names; - /** A map from identity digests routers in the set to (void*)1 */ - digestmap_t *digests; - /** An address policy for routers in the set. For implementation reasons, - * a router belongs to the set if it is _rejected_ by this policy. */ - smartlist_t *policies; - - /** A human-readable description of what this routerset is for. Used in - * log messages. */ - char *description; - - /** A list of the country codes in this set. */ - smartlist_t *country_names; - /** Total number of countries we knew about when we built <b>countries</b>.*/ - int n_countries; - /** Bit array mapping the return value of geoip_get_country() to 1 iff the - * country is a member of this routerset. Note that we MUST call - * routerset_refresh_countries() whenever the geoip country list is - * reloaded. */ - bitarray_t *countries; -}; - -/** Return a new empty routerset. */ -routerset_t * -routerset_new(void) -{ - routerset_t *result = tor_malloc_zero(sizeof(routerset_t)); - result->list = smartlist_new(); - result->names = strmap_new(); - result->digests = digestmap_new(); - result->policies = smartlist_new(); - result->country_names = smartlist_new(); - return result; -} - -/** If <b>c</b> is a country code in the form {cc}, return a newly allocated - * string holding the "cc" part. Else, return NULL. */ -static char * -routerset_get_countryname(const char *c) -{ - char *country; - - if (strlen(c) < 4 || c[0] !='{' || c[3] !='}') - return NULL; - - country = tor_strndup(c+1, 2); - tor_strlower(country); - return country; -} - -/** Update the routerset's <b>countries</b> bitarray_t. Called whenever - * the GeoIP database is reloaded. - */ -void -routerset_refresh_countries(routerset_t *target) -{ - int cc; - bitarray_free(target->countries); - - if (!geoip_is_loaded()) { - target->countries = NULL; - target->n_countries = 0; - return; - } - target->n_countries = geoip_get_n_countries(); - target->countries = bitarray_init_zero(target->n_countries); - SMARTLIST_FOREACH_BEGIN(target->country_names, const char *, country) { - cc = geoip_get_country(country); - if (cc >= 0) { - tor_assert(cc < target->n_countries); - bitarray_set(target->countries, cc); - } else { - log(LOG_WARN, LD_CONFIG, "Country code '%s' is not recognized.", - country); - } - } SMARTLIST_FOREACH_END(country); + smartlist_sort(routers, compare_routerinfo_by_id_digest_); } -/** Parse the string <b>s</b> to create a set of routerset entries, and add - * them to <b>target</b>. In log messages, refer to the string as - * <b>description</b>. Return 0 on success, -1 on failure. - * - * Three kinds of elements are allowed in routersets: nicknames, IP address - * patterns, and fingerprints. They may be surrounded by optional space, and - * must be separated by commas. - */ -int -routerset_parse(routerset_t *target, const char *s, const char *description) -{ - int r = 0; - int added_countries = 0; - char *countryname; - smartlist_t *list = smartlist_new(); - smartlist_split_string(list, s, ",", - SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0); - SMARTLIST_FOREACH_BEGIN(list, char *, nick) { - addr_policy_t *p; - if (is_legal_hexdigest(nick)) { - char d[DIGEST_LEN]; - if (*nick == '$') - ++nick; - log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description); - base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN); - digestmap_set(target->digests, d, (void*)1); - } else if (is_legal_nickname(nick)) { - log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description); - strmap_set_lc(target->names, nick, (void*)1); - } else if ((countryname = routerset_get_countryname(nick)) != NULL) { - log_debug(LD_CONFIG, "Adding country %s to %s", nick, - description); - smartlist_add(target->country_names, countryname); - added_countries = 1; - } else if ((strchr(nick,'.') || strchr(nick, '*')) && - (p = router_parse_addr_policy_item_from_string( - nick, ADDR_POLICY_REJECT))) { - log_debug(LD_CONFIG, "Adding address %s to %s", nick, description); - smartlist_add(target->policies, p); - } else { - log_warn(LD_CONFIG, "Entry '%s' in %s is misformed.", nick, - description); - r = -1; - tor_free(nick); - SMARTLIST_DEL_CURRENT(list, nick); - } - } SMARTLIST_FOREACH_END(nick); - smartlist_add_all(target->list, list); - smartlist_free(list); - if (added_countries) - routerset_refresh_countries(target); - return r; -} - -/** Called when we change a node set, or when we reload the geoip list: +/** Called when we change a node set, or when we reload the geoip IPv4 list: * recompute all country info in all configuration node sets and in the * routerlist. */ void @@ -5615,303 +5346,12 @@ refresh_all_country_info(void) routerset_refresh_countries(options->ExcludeNodes); if (options->ExcludeExitNodes) routerset_refresh_countries(options->ExcludeExitNodes); - if (options->_ExcludeExitNodesUnion) - routerset_refresh_countries(options->_ExcludeExitNodesUnion); + if (options->ExcludeExitNodesUnion_) + routerset_refresh_countries(options->ExcludeExitNodesUnion_); nodelist_refresh_countries(); } -/** Add all members of the set <b>source</b> to <b>target</b>. */ -void -routerset_union(routerset_t *target, const routerset_t *source) -{ - char *s; - tor_assert(target); - if (!source || !source->list) - return; - s = routerset_to_string(source); - routerset_parse(target, s, "other routerset"); - tor_free(s); -} - -/** Return true iff <b>set</b> lists only nicknames and digests, and includes - * no IP ranges or countries. */ -int -routerset_is_list(const routerset_t *set) -{ - return smartlist_len(set->country_names) == 0 && - smartlist_len(set->policies) == 0; -} - -/** Return true iff we need a GeoIP IP-to-country database to make sense of - * <b>set</b>. */ -int -routerset_needs_geoip(const routerset_t *set) -{ - return set && smartlist_len(set->country_names); -} - -/** Return true iff there are no entries in <b>set</b>. */ -int -routerset_is_empty(const routerset_t *set) -{ - return !set || smartlist_len(set->list) == 0; -} - -/** Helper. Return true iff <b>set</b> contains a router based on the other - * provided fields. Return higher values for more specific subentries: a - * single router is more specific than an address range of routers, which is - * more specific in turn than a country code. - * - * (If country is -1, then we take the country - * from addr.) */ -static int -routerset_contains(const routerset_t *set, const tor_addr_t *addr, - uint16_t orport, - const char *nickname, const char *id_digest, - country_t country) -{ - if (!set || !set->list) - return 0; - if (nickname && strmap_get_lc(set->names, nickname)) - return 4; - if (id_digest && digestmap_get(set->digests, id_digest)) - return 4; - if (addr && compare_tor_addr_to_addr_policy(addr, orport, set->policies) - == ADDR_POLICY_REJECTED) - return 3; - if (set->countries) { - if (country < 0 && addr) - country = geoip_get_country_by_ip(tor_addr_to_ipv4h(addr)); - - if (country >= 0 && country < set->n_countries && - bitarray_is_set(set->countries, country)) - return 2; - } - return 0; -} - -/** Return true iff we can tell that <b>ei</b> is a member of <b>set</b>. */ -int -routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei) -{ - return routerset_contains(set, - &ei->addr, - ei->port, - ei->nickname, - ei->identity_digest, - -1 /*country*/); -} - -/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we - * look up the country. */ -int -routerset_contains_router(const routerset_t *set, const routerinfo_t *ri, - country_t country) -{ - tor_addr_t addr; - tor_addr_from_ipv4h(&addr, ri->addr); - return routerset_contains(set, - &addr, - ri->or_port, - ri->nickname, - ri->cache_info.identity_digest, - country); -} - -/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we - * look up the country. */ -int -routerset_contains_routerstatus(const routerset_t *set, - const routerstatus_t *rs, - country_t country) -{ - tor_addr_t addr; - tor_addr_from_ipv4h(&addr, rs->addr); - return routerset_contains(set, - &addr, - rs->or_port, - rs->nickname, - rs->identity_digest, - country); -} - -/** Return true iff <b>node</b> is in <b>set</b>. */ -int -routerset_contains_node(const routerset_t *set, const node_t *node) -{ - if (node->rs) - return routerset_contains_routerstatus(set, node->rs, node->country); - else if (node->ri) - return routerset_contains_router(set, node->ri, node->country); - else - return 0; -} - -/** Add every known node_t that is a member of <b>routerset</b> to - * <b>out</b>, but never add any that are part of <b>excludeset</b>. - * If <b>running_only</b>, only add the running ones. */ -void -routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset, - const routerset_t *excludeset, int running_only) -{ /* XXXX MOVE */ - tor_assert(out); - if (!routerset || !routerset->list) - return; - - if (routerset_is_list(routerset)) { - /* No routers are specified by type; all are given by name or digest. - * we can do a lookup in O(len(routerset)). */ - SMARTLIST_FOREACH(routerset->list, const char *, name, { - const node_t *node = node_get_by_nickname(name, 1); - if (node) { - if (!running_only || node->is_running) - if (!routerset_contains_node(excludeset, node)) - smartlist_add(out, (void*)node); - } - }); - } else { - /* We need to iterate over the routerlist to get all the ones of the - * right kind. */ - smartlist_t *nodes = nodelist_get_list(); - SMARTLIST_FOREACH(nodes, const node_t *, node, { - if (running_only && !node->is_running) - continue; - if (routerset_contains_node(routerset, node) && - !routerset_contains_node(excludeset, node)) - smartlist_add(out, (void*)node); - }); - } -} - -#if 0 -/** Add to <b>target</b> every node_t from <b>source</b> except: - * - * 1) Don't add it if <b>include</b> is non-empty and the relay isn't in - * <b>include</b>; and - * 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_node_disjunction(smartlist_t *target, - const smartlist_t *source, - const routerset_t *include, - const routerset_t *exclude, int running_only) -{ - SMARTLIST_FOREACH(source, const node_t *, node, { - int include_result; - if (running_only && !node->is_running) - continue; - if (!routerset_is_empty(include)) - include_result = routerset_contains_node(include, node); - else - include_result = 1; - - if (include_result) { - int exclude_result = routerset_contains_node(exclude, node); - if (include_result >= exclude_result) - smartlist_add(target, (void*)node); - } - }); -} -#endif - -/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */ -void -routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset) -{ /*XXXX MOVE ? */ - tor_assert(lst); - if (!routerset) - return; - SMARTLIST_FOREACH(lst, const node_t *, node, { - if (routerset_contains_node(routerset, node)) { - //log_debug(LD_DIR, "Subtracting %s",r->nickname); - SMARTLIST_DEL_CURRENT(lst, node); - } - }); -} - -/** Return a new string that when parsed by routerset_parse_string() will - * yield <b>set</b>. */ -char * -routerset_to_string(const routerset_t *set) -{ - if (!set || !set->list) - return tor_strdup(""); - return smartlist_join_strings(set->list, ",", 0, NULL); -} - -/** Helper: return true iff old and new are both NULL, or both non-NULL - * equal routersets. */ -int -routerset_equal(const routerset_t *old, const routerset_t *new) -{ - if (routerset_is_empty(old) && routerset_is_empty(new)) { - /* Two empty sets are equal */ - return 1; - } else if (routerset_is_empty(old) || routerset_is_empty(new)) { - /* An empty set is equal to nothing else. */ - return 0; - } - tor_assert(old != NULL); - tor_assert(new != NULL); - - if (smartlist_len(old->list) != smartlist_len(new->list)) - return 0; - - SMARTLIST_FOREACH(old->list, const char *, cp1, { - const char *cp2 = smartlist_get(new->list, cp1_sl_idx); - if (strcmp(cp1, cp2)) - return 0; - }); - - return 1; -} - -/** 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, - addr_policy_free(p)); - smartlist_free(routerset->policies); - SMARTLIST_FOREACH(routerset->country_names, char *, cp, tor_free(cp)); - smartlist_free(routerset->country_names); - - strmap_free(routerset->names, NULL); - digestmap_free(routerset->digests, NULL); - bitarray_free(routerset->countries); - tor_free(routerset); -} - -/** Refresh the country code of <b>ri</b>. This function MUST be called on - * each router when the GeoIP database is reloaded, and on all new routers. */ -void -node_set_country(node_t *node) -{ - if (node->rs) - node->country = geoip_get_country_by_ip(node->rs->addr); - else if (node->ri) - node->country = geoip_get_country_by_ip(node->ri->addr); - else - node->country = -1; -} - -/** Set the country code of all routers in the routerlist. */ -void -nodelist_refresh_countries(void) /* MOVE */ -{ - smartlist_t *nodes = nodelist_get_list(); - SMARTLIST_FOREACH(nodes, node_t *, node, - node_set_country(node)); -} - /** Determine the routers that are responsible for <b>id</b> (binary) and * add pointers to those routers' routerstatus_t to <b>responsible_dirs</b>. * Return -1 if we're returning an empty smartlist, else return 0. diff --git a/src/or/routerlist.h b/src/or/routerlist.h index bd55b7b201..505685897f 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,12 +8,25 @@ * \brief Header file for routerlist.c. **/ -#ifndef _TOR_ROUTERLIST_H -#define _TOR_ROUTERLIST_H +#ifndef TOR_ROUTERLIST_H +#define TOR_ROUTERLIST_H int get_n_authorities(dirinfo_type_t type); int trusted_dirs_reload_certs(void); -int trusted_dirs_load_certs_from_string(const char *contents, int from_store, + +/* + * Pass one of these as source to trusted_dirs_load_certs_from_string() + * to indicate whence string originates; this controls error handling + * behavior such as marking downloads as failed. + */ + +#define TRUSTED_DIRS_CERTS_SRC_SELF 0 +#define TRUSTED_DIRS_CERTS_SRC_FROM_STORE 1 +#define TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST 2 +#define TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST 3 +#define TRUSTED_DIRS_CERTS_SRC_FROM_VOTE 4 + +int trusted_dirs_load_certs_from_string(const char *contents, int source, int flush); void trusted_dirs_flush_certs_to_disk(void); authority_cert_t *authority_cert_get_newest_by_id(const char *id_digest); @@ -21,41 +34,42 @@ 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_cert_dl_failed(const char *id_digest, + const char *signing_key_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); +const smartlist_t *router_get_trusted_dir_servers(void); +const smartlist_t *router_get_fallback_dir_servers(void); int authority_cert_is_blacklisted(const authority_cert_t *cert); -smartlist_t *router_get_trusted_dir_servers(void); const routerstatus_t *router_pick_directory_server(dirinfo_type_t type, int flags); -trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d); -trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d); +dir_server_t *router_get_trusteddirserver_by_digest(const char *d); +dir_server_t *router_get_fallback_dirserver_by_digest( + const char *digest); +dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d); const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type, int flags); +const routerstatus_t *router_pick_fallback_dirserver(dirinfo_type_t type, + int flags); int router_get_my_share_of_directory_requests(double *v2_share_out, double *v3_share_out); void router_reset_status_download_failures(void); -int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2); -int router_nickname_is_in_list(const routerinfo_t *router, const char *list); +int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2); const routerinfo_t *routerlist_find_my_routerinfo(void); -const node_t *router_find_exact_exit_enclave(const char *address, - uint16_t port); -int node_is_unreliable(const node_t *router, int need_uptime, - int need_capacity, int need_guard); uint32_t router_get_advertised_bandwidth(const routerinfo_t *router); uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router); -const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl, +const node_t *node_sl_choose_by_bandwidth(const smartlist_t *sl, bandwidth_weight_rule_t rule); +double frac_nodes_with_descriptors(const smartlist_t *sl, + bandwidth_weight_rule_t rule); const node_t *router_choose_random_node(smartlist_t *excludedsmartlist, struct routerset_t *excludedset, router_crn_flags_t flags); -const routerinfo_t *router_get_by_nickname(const char *nickname, - int warn_if_unnamed); int router_is_named(const routerinfo_t *router); int router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type); @@ -64,7 +78,6 @@ int router_digest_is_trusted_dir_type(const char *digest, int router_addr_is_trusted_dir(uint32_t addr); int hexdigest_to_digest(const char *hexdigest, char *digest); -const routerinfo_t *router_get_by_hexdigest(const char *hexdigest); const routerinfo_t *router_get_by_id_digest(const char *digest); routerinfo_t *router_get_mutable_by_digest(const char *digest); signed_descriptor_t *router_get_by_descriptor_digest(const char *digest); @@ -81,7 +94,6 @@ 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); @@ -134,27 +146,25 @@ void router_load_extrainfo_from_string(const char *s, const char *eos, int descriptor_digests); void routerlist_retry_directory_downloads(time_t now); -int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port, - int need_uptime); int router_exit_policy_rejects_all(const routerinfo_t *router); -trusted_dir_server_t *add_trusted_dir_server(const char *nickname, - const char *address, - uint16_t dir_port, uint16_t or_port, - const char *digest, const char *v3_auth_digest, - dirinfo_type_t type); + +dir_server_t *trusted_dir_server_new(const char *nickname, const char *address, + uint16_t dir_port, uint16_t or_port, + const char *digest, const char *v3_auth_digest, + dirinfo_type_t type, double weight); +dir_server_t *fallback_dir_server_new(const tor_addr_t *addr, + uint16_t dir_port, uint16_t or_port, + const char *id_digest, double weight); +void dir_server_add(dir_server_t *ent); + void authority_cert_free(authority_cert_t *cert); -void clear_trusted_dir_servers(void); -int any_trusted_dir_is_v1_authority(void); +void clear_dir_servers(void); void update_consensus_router_descriptor_downloads(time_t now, int is_vote, networkstatus_t *consensus); void update_router_descriptor_downloads(time_t now); void update_all_descriptor_downloads(time_t now); void update_extrainfo_downloads(time_t now); -int router_have_minimum_dir_info(void); -void router_dir_info_changed(void); -const char *get_dir_info_status_string(void); -int count_loading_descriptors_progress(void); void router_reset_descriptor_download_failures(void); int router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2); @@ -167,38 +177,6 @@ void routerlist_assert_ok(const routerlist_t *rl); const char *esc_router_info(const routerinfo_t *router); void routers_sort_by_identity(smartlist_t *routers); -routerset_t *routerset_new(void); -void routerset_refresh_countries(routerset_t *rs); -int routerset_parse(routerset_t *target, const char *s, - const char *description); -void routerset_union(routerset_t *target, const routerset_t *source); -int routerset_is_list(const routerset_t *set); -int routerset_needs_geoip(const routerset_t *set); -int routerset_is_empty(const routerset_t *set); -int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri, - country_t country); -int routerset_contains_routerstatus(const routerset_t *set, - const routerstatus_t *rs, - country_t country); -int routerset_contains_extendinfo(const routerset_t *set, - const extend_info_t *ei); - -int routerset_contains_node(const routerset_t *set, const node_t *node); -void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset, - const routerset_t *excludeset, - int running_only); -#if 0 -void routersets_get_node_disjunction(smartlist_t *target, - const smartlist_t *source, - const routerset_t *include, - const routerset_t *exclude, int running_only); -#endif -void routerset_subtract_nodes(smartlist_t *out, - const routerset_t *routerset); - -char *routerset_to_string(const routerset_t *routerset); -int routerset_equal(const routerset_t *old, const routerset_t *new); -void routerset_free(routerset_t *routerset); void refresh_all_country_info(void); int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, @@ -216,6 +194,23 @@ int hex_digest_nickname_decode(const char *hexdigest, char *digest_out, char *nickname_qualifier_out, char *nickname_out); +int hex_digest_nickname_matches(const char *hexdigest, + const char *identity_digest, + const char *nickname, int is_named); + +#ifdef ROUTERLIST_PRIVATE +/** Helper type for choosing routers by bandwidth: contains a union of + * double and uint64_t. Before we call scale_array_elements_to_u64, it holds + * a double; after, it holds a uint64_t. */ +typedef union u64_dbl_t { + uint64_t u64; + double dbl; +} u64_dbl_t; + +int choose_array_element_by_weight(const u64_dbl_t *entries, int n_entries); +void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries, + uint64_t *total_out); +#endif #endif diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 3ff887c3ca..01f65f262b 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,7 +11,7 @@ #include "or.h" #include "config.h" -#include "circuitbuild.h" +#include "circuitstats.h" #include "dirserv.h" #include "dirvote.h" #include "policies.h" @@ -29,8 +29,8 @@ /****************************************************************************/ /** Enumeration of possible token types. The ones starting with K_ correspond - * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF - * is an end-of-file marker, and _NIL is used to encode not-a-token. + * to directory 'keywords'. ERR_ is an error in the tokenizing process, EOF_ + * is an end-of-file marker, and NIL_ is used to encode not-a-token. */ typedef enum { K_ACCEPT = 0, @@ -43,6 +43,7 @@ typedef enum { K_SIGNED_DIRECTORY, K_SIGNING_KEY, K_ONION_KEY, + K_ONION_KEY_NTOR, K_ROUTER_SIGNATURE, K_PUBLISHED, K_RUNNING_ROUTERS, @@ -66,7 +67,9 @@ typedef enum { K_SERVER_VERSIONS, K_OR_ADDRESS, K_P, + K_P6, K_R, + K_A, K_S, K_V, K_W, @@ -76,6 +79,7 @@ typedef enum { K_CACHES_EXTRA_INFO, K_HIDDEN_SERVICE_DIR, K_ALLOW_SINGLE_HOP_EXITS, + K_IPV6_POLICY, K_DIRREQ_END, K_DIRREQ_V2_IPS, @@ -130,7 +134,7 @@ typedef enum { A_PURPOSE, A_LAST_LISTED, - _A_UNKNOWN, + A_UNKNOWN_, R_RENDEZVOUS_SERVICE_DESCRIPTOR, R_VERSION, @@ -151,13 +155,13 @@ typedef enum { C_DESCRIPTOR_COOKIE, C_CLIENT_KEY, - _ERR, - _EOF, - _NIL + ERR_, + EOF_, + NIL_ } directory_keyword; #define MIN_ANNOTATION A_PURPOSE -#define MAX_ANNOTATION _A_UNKNOWN +#define MAX_ANNOTATION A_UNKNOWN_ /** Structure to hold a single directory token. * @@ -180,7 +184,7 @@ typedef struct directory_token_t { crypto_pk_t *key; /**< For public keys only. Heap-allocated. */ - char *error; /**< For _ERR tokens only. */ + char *error; /**< For ERR_ tokens only. */ } directory_token_t; /* ********************************************************************** */ @@ -234,7 +238,7 @@ typedef struct token_rule_t { */ /** Appears to indicate the end of a table. */ -#define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 } +#define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 } /** An item with no restrictions: used for obsolete document types */ #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 } /** An item with no restrictions on multiplicity or location. */ @@ -270,8 +274,10 @@ static token_rule_t routerdesc_token_table[] = { T0N("reject6", K_REJECT6, ARGS, NO_OBJ ), T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ), T1_START( "router", K_ROUTER, GE(5), NO_OBJ ), + T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ), T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ), T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ), + T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ), T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ), T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ), T01("uptime", K_UPTIME, GE(1), NO_OBJ ), @@ -338,6 +344,7 @@ static token_rule_t extrainfo_token_table[] = { static token_rule_t rtrstatus_token_table[] = { T01("p", K_P, CONCAT_ARGS, NO_OBJ ), T1( "r", K_R, GE(7), NO_OBJ ), + T0N("a", K_A, GE(1), NO_OBJ ), T1( "s", K_S, ARGS, NO_OBJ ), T01("v", K_V, CONCAT_ARGS, NO_OBJ ), T01("w", K_W, ARGS, NO_OBJ ), @@ -371,25 +378,6 @@ static token_rule_t dir_footer_token_table[] = { END_OF_TABLE }; -/** List of tokens recognized in v1 directory headers/footers. */ -static token_rule_t dir_token_table[] = { - /* don't enforce counts; this is obsolete. */ - T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ), - T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ), - T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ), - T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ), - - T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ), - T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ), - T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ), - T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ), - T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ), - T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ), - T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ), - - END_OF_TABLE -}; - /** List of tokens common to V3 authority certificates and V3 consensuses. */ #define CERTIFICATE_MEMBERS \ T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \ @@ -522,8 +510,11 @@ static token_rule_t networkstatus_detached_signature_token_table[] = { /** List of tokens recognized in microdescriptors */ static token_rule_t microdesc_token_table[] = { T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024), + T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ), + T0N("a", K_A, GE(1), NO_OBJ ), T01("family", K_FAMILY, ARGS, NO_OBJ ), T01("p", K_P, CONCAT_ARGS, NO_OBJ ), + T01("p6", K_P6, CONCAT_ARGS, NO_OBJ ), A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ), END_OF_TABLE }; @@ -532,7 +523,8 @@ static token_rule_t microdesc_token_table[] = { /* static function prototypes */ static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok); -static addr_policy_t *router_parse_addr_policy(directory_token_t *tok); +static addr_policy_t *router_parse_addr_policy(directory_token_t *tok, + unsigned fmt_flags); 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, @@ -546,10 +538,10 @@ static int router_get_hashes_impl(const char *s, size_t s_len, static void token_clear(directory_token_t *tok); static smartlist_t *find_all_by_keyword(smartlist_t *s, directory_keyword k); static smartlist_t *find_all_exitpolicy(smartlist_t *s); -static directory_token_t *_find_by_keyword(smartlist_t *s, +static directory_token_t *find_by_keyword_(smartlist_t *s, directory_keyword keyword, const char *keyword_str); -#define find_by_keyword(s, keyword) _find_by_keyword((s), (keyword), #keyword) +#define find_by_keyword(s, keyword) find_by_keyword_((s), (keyword), #keyword) static directory_token_t *find_opt_by_keyword(smartlist_t *s, directory_keyword keyword); @@ -573,7 +565,6 @@ static int check_signature_token(const char *digest, crypto_pk_t *pkey, int flags, const char *doctype); -static crypto_pk_t *find_dir_signing_key(const char *str, const char *eos); #undef DEBUG_AREA_ALLOC @@ -671,18 +662,6 @@ router_get_networkstatus_v3_hashes(const char *s, digests_t *digests) ' '); } -/** 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, - 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 <b>s_len</b>-byte * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */ int @@ -693,19 +672,23 @@ router_get_extrainfo_hash(const char *s, size_t s_len, char *digest) } /** Helper: used to generate signatures for routers, directories and - * network-status objects. Given a digest in <b>digest</b> and a secret - * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it, - * surround it with -----BEGIN/END----- pairs, and write it to the - * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on - * failure. + * network-status objects. Given a <b>digest_len</b>-byte digest in + * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded + * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs, + * and return the new signature on success or NULL on failure. */ -int -router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, - size_t digest_len, crypto_pk_t *private_key) +char * +router_get_dirobj_signature(const char *digest, + size_t digest_len, + crypto_pk_t *private_key) { char *signature; size_t i, keysize; int siglen; + char *buf = NULL; + size_t buf_len; + /* overestimate of BEGIN/END lines total len. */ +#define BEGIN_END_OVERHEAD_LEN 64 keysize = crypto_pk_keysize(private_key); signature = tor_malloc(keysize); @@ -715,7 +698,12 @@ router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, log_warn(LD_BUG,"Couldn't sign digest."); goto err; } - if (strlcat(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len) + + /* The *2 here is a ridiculous overestimate of base-64 overhead. */ + buf_len = (siglen * 2) + BEGIN_END_OVERHEAD_LEN; + buf = tor_malloc(buf_len); + + if (strlcpy(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len) goto truncated; i = strlen(buf); @@ -728,13 +716,42 @@ router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, goto truncated; tor_free(signature); - return 0; + return buf; truncated: log_warn(LD_BUG,"tried to exceed string length."); err: tor_free(signature); - return -1; + tor_free(buf); + return NULL; +} + +/** Helper: used to generate signatures for routers, directories and + * network-status objects. Given a digest in <b>digest</b> and a secret + * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it, + * surround it with -----BEGIN/END----- pairs, and write it to the + * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on + * failure. + */ +int +router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, + size_t digest_len, crypto_pk_t *private_key) +{ + size_t sig_len, s_len; + char *sig = router_get_dirobj_signature(digest, digest_len, private_key); + if (!sig) { + log_warn(LD_BUG, "No signature generated"); + return -1; + } + sig_len = strlen(sig); + s_len = strlen(buf); + if (sig_len + s_len + 1 > buf_len) { + log_warn(LD_BUG, "Not enough room for signature"); + tor_free(sig); + return -1; + } + memcpy(buf+s_len, sig, sig_len+1); + return 0; } /** Return VS_RECOMMENDED if <b>myversion</b> is contained in @@ -816,218 +833,6 @@ tor_version_is_obsolete(const char *myversion, const char *versionlist) return ret; } -/** Read a signed directory from <b>str</b>. If it's well-formed, return 0. - * Otherwise, return -1. If we're a directory cache, cache it. - */ -int -router_parse_directory(const char *str) -{ - directory_token_t *tok; - char digest[DIGEST_LEN]; - time_t published_on; - int r; - const char *end, *cp, *str_dup = str; - smartlist_t *tokens = NULL; - crypto_pk_t *declared_key = NULL; - memarea_t *area = memarea_new(); - - /* XXXX This could be simplified a lot, but it will all go away - * once pre-0.1.1.8 is obsolete, and for now it's better not to - * touch it. */ - - if (router_get_dir_hash(str, digest)) { - log_warn(LD_DIR, "Unable to compute digest of directory"); - goto err; - } - log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4)); - - /* Check signature first, before we try to tokenize. */ - cp = str; - while (cp && (end = strstr(cp+1, "\ndirectory-signature"))) - cp = end; - if (cp == str || !cp) { - log_warn(LD_DIR, "No signature found on directory."); goto err; - } - ++cp; - tokens = smartlist_new(); - if (tokenize_string(area,cp,strchr(cp,'\0'),tokens,dir_token_table,0)) { - log_warn(LD_DIR, "Error tokenizing directory signature"); goto err; - } - if (smartlist_len(tokens) != 1) { - log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err; - } - tok=smartlist_get(tokens,0); - if (tok->tp != K_DIRECTORY_SIGNATURE) { - log_warn(LD_DIR,"Expected a single directory signature"); goto err; - } - declared_key = find_dir_signing_key(str, str+strlen(str)); - note_crypto_pk_op(VERIFY_DIR); - 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_clear(t)); - smartlist_clear(tokens); - memarea_clear(area); - - /* Now try to parse the first part of the directory. */ - if ((end = strstr(str,"\nrouter "))) { - ++end; - } else if ((end = strstr(str, "\ndirectory-signature"))) { - ++end; - } else { - end = str + strlen(str); - } - - if (tokenize_string(area,str,end,tokens,dir_token_table,0)) { - log_warn(LD_DIR, "Error tokenizing directory"); goto err; - } - - tok = find_by_keyword(tokens, K_PUBLISHED); - tor_assert(tok->n_args == 1); - - if (parse_iso_time(tok->args[0], &published_on) < 0) { - goto err; - } - - /* Now that we know the signature is okay, and we have a - * publication time, cache the directory. */ - if (directory_caches_v1_dir_info(get_options()) && - !authdir_mode_v1(get_options())) - dirserv_set_cached_directory(str, published_on, 0); - - r = 0; - goto done; - err: - dump_desc(str_dup, "v1 directory"); - r = -1; - done: - if (declared_key) crypto_pk_free(declared_key); - if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); - smartlist_free(tokens); - } - if (area) { - DUMP_AREA(area, "v1 directory"); - memarea_drop_all(area); - } - return r; -} - -/** Read a signed router status statement from <b>str</b>. If it's - * well-formed, return 0. Otherwise, return -1. If we're a directory cache, - * cache it.*/ -int -router_parse_runningrouters(const char *str) -{ - char digest[DIGEST_LEN]; - directory_token_t *tok; - time_t published_on; - int r = -1; - crypto_pk_t *declared_key = NULL; - smartlist_t *tokens = NULL; - const char *eos = str + strlen(str), *str_dup = str; - memarea_t *area = NULL; - - if (router_get_runningrouters_hash(str, digest)) { - log_warn(LD_DIR, "Unable to compute digest of running-routers"); - goto err; - } - area = memarea_new(); - tokens = smartlist_new(); - if (tokenize_string(area,str,eos,tokens,dir_token_table,0)) { - log_warn(LD_DIR, "Error tokenizing running-routers"); goto err; - } - tok = smartlist_get(tokens,0); - if (tok->tp != K_NETWORK_STATUS) { - log_warn(LD_DIR, "Network-status starts with wrong token"); - goto err; - } - - tok = find_by_keyword(tokens, K_PUBLISHED); - tor_assert(tok->n_args == 1); - if (parse_iso_time(tok->args[0], &published_on) < 0) { - goto err; - } - if (!(tok = find_opt_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) { - log_warn(LD_DIR, "Missing signature on running-routers"); - goto err; - } - declared_key = find_dir_signing_key(str, eos); - note_crypto_pk_op(VERIFY_DIR); - if (check_signature_token(digest, DIGEST_LEN, tok, declared_key, - CST_CHECK_AUTHORITY, "running-routers") - < 0) - goto err; - - /* Now that we know the signature is okay, and we have a - * publication time, cache the list. */ - if (get_options()->DirPort_set && !authdir_mode_v1(get_options())) - dirserv_set_cached_directory(str, published_on, 1); - - r = 0; - err: - dump_desc(str_dup, "v1 running-routers"); - if (declared_key) crypto_pk_free(declared_key); - if (tokens) { - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); - smartlist_free(tokens); - } - if (area) { - DUMP_AREA(area, "v1 running-routers"); - memarea_drop_all(area); - } - return r; -} - -/** Given a directory or running-routers string in <b>str</b>, try to - * find the its dir-signing-key token (if any). If this token is - * present, extract and return the key. Return NULL on failure. */ -static crypto_pk_t * -find_dir_signing_key(const char *str, const char *eos) -{ - const char *cp; - directory_token_t *tok; - crypto_pk_t *key = NULL; - memarea_t *area = NULL; - tor_assert(str); - tor_assert(eos); - - /* Is there a dir-signing-key in the directory? */ - cp = tor_memstr(str, eos-str, "\nopt dir-signing-key"); - if (!cp) - cp = tor_memstr(str, eos-str, "\ndir-signing-key"); - if (!cp) - return NULL; - ++cp; /* Now cp points to the start of the token. */ - - area = memarea_new(); - tok = get_next_token(area, &cp, eos, dir_token_table); - if (!tok) { - log_warn(LD_DIR, "Unparseable dir-signing-key token"); - goto done; - } - if (tok->tp != K_DIR_SIGNING_KEY) { - log_warn(LD_DIR, "Dir-signing-key token did not parse as expected"); - goto done; - } - - if (tok->key) { - key = tok->key; - tok->key = NULL; /* steal reference. */ - } else { - log_warn(LD_DIR, "Dir-signing-key token contained no key"); - } - - done: - if (tok) token_clear(tok); - if (area) { - DUMP_AREA(area, "dir-signing-key token"); - memarea_drop_all(area); - } - return key; -} - /** Return true iff <b>key</b> is allowed to sign directories. */ static int @@ -1250,13 +1055,50 @@ dump_distinct_digest_count(int severity) #ifdef COUNT_DISTINCT_DIGESTS if (!verified_digests) verified_digests = digestmap_new(); - log(severity, LD_GENERAL, "%d *distinct* router digests verified", + tor_log(severity, LD_GENERAL, "%d *distinct* router digests verified", digestmap_size(verified_digests)); #else (void)severity; /* suppress "unused parameter" warning */ #endif } +/** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's + * with at least one argument (use GE(1) in setup). If found, store + * address and port number to <b>addr_out</b> and + * <b>port_out</b>. Return number of OR ports found. */ +static int +find_single_ipv6_orport(const smartlist_t *list, + tor_addr_t *addr_out, + uint16_t *port_out) +{ + int ret = 0; + tor_assert(list != NULL); + tor_assert(addr_out != NULL); + tor_assert(port_out != NULL); + + SMARTLIST_FOREACH_BEGIN(list, directory_token_t *, t) { + tor_addr_t a; + maskbits_t bits; + uint16_t port_min, port_max; + tor_assert(t->n_args >= 1); + /* XXXX Prop186 the full spec allows much more than this. */ + if (tor_addr_parse_mask_ports(t->args[0], 0, + &a, &bits, &port_min, + &port_max) == AF_INET6 && + bits == 128 && + port_min == port_max) { + /* Okay, this is one we can understand. Use it and ignore + any potential more addresses in list. */ + tor_addr_copy(addr_out, &a); + *port_out = port_min; + ret = 1; + break; + } + } SMARTLIST_FOREACH_END(t); + + return ret; +} + /** Helper function: reads a single router entry from *<b>s</b> ... * *<b>end</b>. Mallocs a new router and returns it if all goes well, else * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of @@ -1471,6 +1313,17 @@ router_parse_entry_from_string(const char *s, const char *end, router->onion_pkey = tok->key; tok->key = NULL; /* Prevent free */ + if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) { + curve25519_public_key_t k; + tor_assert(tok->n_args >= 1); + if (curve25519_public_from_base64(&k, tok->args[0]) < 0) { + log_warn(LD_DIR, "Bogus ntor-onion-key in routerinfo"); + goto err; + } + router->onion_curve25519_pkey = + tor_memdup(&k, sizeof(curve25519_public_key_t)); + } + tok = find_by_keyword(tokens, K_SIGNING_KEY); router->identity_pkey = tok->key; tok->key = NULL; /* Prevent free */ @@ -1513,21 +1366,8 @@ router_parse_entry_from_string(const char *s, const char *end, { smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS); if (or_addresses) { - SMARTLIST_FOREACH_BEGIN(or_addresses, directory_token_t *, t) { - tor_addr_t a; - maskbits_t bits; - uint16_t port_min, port_max; - /* XXXX Prop186 the full spec allows much more than this. */ - if (tor_addr_parse_mask_ports(t->args[0], &a, &bits, &port_min, - &port_max) == AF_INET6 && - bits == 128 && - port_min == port_max) { - /* Okay, this is one we can understand. */ - tor_addr_copy(&router->ipv6_addr, &a); - router->ipv6_orport = port_min; - break; - } - } SMARTLIST_FOREACH_END(t); + find_single_ipv6_orport(or_addresses, &router->ipv6_addr, + &router->ipv6_orport); smartlist_free(or_addresses); } } @@ -1542,7 +1382,18 @@ router_parse_entry_from_string(const char *s, const char *end, goto err; }); policy_expand_private(&router->exit_policy); - if (policy_is_reject_star(router->exit_policy)) + + if ((tok = find_opt_by_keyword(tokens, K_IPV6_POLICY)) && tok->n_args) { + router->ipv6_exit_policy = parse_short_policy(tok->args[0]); + if (! router->ipv6_exit_policy) { + log_warn(LD_DIR , "Error in ipv6-policy %s", escaped(tok->args[0])); + goto err; + } + } + + if (policy_is_reject_star(router->exit_policy, AF_INET) && + (!router->ipv6_exit_policy || + short_policy_is_reject_star(router->ipv6_exit_policy))) router->policy_is_reject_star = 1; if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) { @@ -1669,7 +1520,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, extrainfo = tor_malloc_zero(sizeof(extrainfo_t)); extrainfo->cache_info.is_extrainfo = 1; if (cache_copy) - extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s); + extrainfo->cache_info.signed_descriptor_body = tor_memdup_nulterm(s,end-s); extrainfo->cache_info.signed_descriptor_len = end-s; memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN); @@ -2060,6 +1911,14 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset], 10,0,65535,NULL,NULL); + { + smartlist_t *a_lines = find_all_by_keyword(tokens, K_A); + if (a_lines) { + find_single_ipv6_orport(a_lines, &rs->ipv6_addr, &rs->ipv6_orport); + smartlist_free(a_lines); + } + } + tok = find_opt_by_keyword(tokens, K_S); if (tok && vote) { int i; @@ -2067,7 +1926,7 @@ routerstatus_parse_entry_from_string(memarea_t *area, for (i=0; i < tok->n_args; ++i) { int p = smartlist_string_pos(vote->known_flags, tok->args[i]); if (p >= 0) { - vote_rs->flags |= (1<<p); + vote_rs->flags |= (U64_LITERAL(1)<<p); } else { log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.", escaped(tok->args[i])); @@ -2112,24 +1971,15 @@ routerstatus_parse_entry_from_string(memarea_t *area, tor_assert(tok->n_args == 1); rs->version_known = 1; if (strcmpstart(tok->args[0], "Tor ")) { - rs->version_supports_begindir = 1; - rs->version_supports_extrainfo_upload = 1; - rs->version_supports_conditional_consensus = 1; rs->version_supports_microdesc_cache = 1; rs->version_supports_optimistic_data = 1; } else { - rs->version_supports_begindir = - tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha"); - rs->version_supports_extrainfo_upload = - tor_version_as_new_as(tok->args[0], "0.2.0.0-alpha-dev (r10070)"); - rs->version_supports_v3_dir = - tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha"); - rs->version_supports_conditional_consensus = - tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha"); rs->version_supports_microdesc_cache = tor_version_supports_microdescriptors(tok->args[0]); rs->version_supports_optimistic_data = tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha"); + rs->version_supports_extend2_cells = + tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha"); } if (vote_rs) { vote_rs->version = tor_strdup(tok->args[0]); @@ -2142,17 +1992,18 @@ routerstatus_parse_entry_from_string(memarea_t *area, for (i=0; i < tok->n_args; ++i) { if (!strcmpstart(tok->args[i], "Bandwidth=")) { int ok; - rs->bandwidth = (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, - 10, 0, UINT32_MAX, - &ok, NULL); + rs->bandwidth_kb = + (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, + 10, 0, UINT32_MAX, + &ok, NULL); if (!ok) { log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i])); goto err; } rs->has_bandwidth = 1; - } else if (!strcmpstart(tok->args[i], "Measured=")) { + } else if (!strcmpstart(tok->args[i], "Measured=") && vote_rs) { int ok; - rs->measured_bw = + vote_rs->measured_bw_kb = (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, 10, 0, UINT32_MAX, &ok, NULL); if (!ok) { @@ -2160,7 +2011,10 @@ routerstatus_parse_entry_from_string(memarea_t *area, escaped(tok->args[i])); goto err; } - rs->has_measured_bw = 1; + vote_rs->has_measured_bw = 1; + vote->has_measured_bws = 1; + } else if (!strcmpstart(tok->args[i], "Unmeasured=1")) { + rs->bw_is_unmeasured = 1; } } } @@ -2203,7 +2057,7 @@ routerstatus_parse_entry_from_string(memarea_t *area, } } else { log_info(LD_BUG, "Found an entry in networkstatus with no " - "microdescriptor digest. (Router %s=%s at %s:%d.)", + "microdescriptor digest. (Router %s ($%s) at %s:%d.)", rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN), fmt_addr32(rs->addr), rs->or_port); } @@ -2238,9 +2092,17 @@ compare_routerstatus_entries(const void **_a, const void **_b) return fast_memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN); } +int +compare_vote_routerstatus_entries(const void **_a, const void **_b) +{ + const vote_routerstatus_t *a = *_a, *b = *_b; + return fast_memcmp(a->status.identity_digest, b->status.identity_digest, + DIGEST_LEN); +} + /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */ static void -_free_duplicate_routerstatus_entry(void *e) +free_duplicate_routerstatus_entry_(void *e) { log_warn(LD_DIR, "Network-status has two entries for the same router. " @@ -2381,7 +2243,7 @@ networkstatus_v2_parse_from_string(const char *s) } smartlist_sort(ns->entries, compare_routerstatus_entries); smartlist_uniq(ns->entries, compare_routerstatus_entries, - _free_duplicate_routerstatus_entry); + free_duplicate_routerstatus_entry_); if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) { log_warn(LD_DIR, "Error tokenizing network-status footer."); @@ -2422,7 +2284,7 @@ networkstatus_v2_parse_from_string(const char *s) /** Verify the bandwidth weights of a network status document */ int -networkstatus_verify_bw_weights(networkstatus_t *ns) +networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method) { int64_t weight_scale; int64_t G=0, M=0, E=0, D=0, T=0; @@ -2431,7 +2293,7 @@ networkstatus_verify_bw_weights(networkstatus_t *ns) const char *casename = NULL; int valid = 1; - weight_scale = circuit_build_times_get_bw_scale(ns); + weight_scale = networkstatus_get_weight_scale_param(ns); Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1); Wgm = networkstatus_get_bw_weight(ns, "Wgm", -1); Wgd = networkstatus_get_bw_weight(ns, "Wgd", -1); @@ -2508,24 +2370,31 @@ networkstatus_verify_bw_weights(networkstatus_t *ns) // Then, gather G, M, E, D, T to determine case SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { + int is_exit = 0; + if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) { + /* Bug #2203: Don't count bad exits as exits for balancing */ + is_exit = rs->is_exit && !rs->is_bad_exit; + } else { + is_exit = rs->is_exit; + } 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; + T += rs->bandwidth_kb; + if (is_exit && rs->is_possible_guard) { + D += rs->bandwidth_kb; + Gtotal += Wgd*rs->bandwidth_kb; + Mtotal += Wmd*rs->bandwidth_kb; + Etotal += Wed*rs->bandwidth_kb; + } else if (is_exit) { + E += rs->bandwidth_kb; + Mtotal += Wme*rs->bandwidth_kb; + Etotal += Wee*rs->bandwidth_kb; } else if (rs->is_possible_guard) { - G += rs->bandwidth; - Gtotal += Wgg*rs->bandwidth; - Mtotal += Wmg*rs->bandwidth; + G += rs->bandwidth_kb; + Gtotal += Wgg*rs->bandwidth_kb; + Mtotal += Wmg*rs->bandwidth_kb; } else { - M += rs->bandwidth; - Mtotal += Wmm*rs->bandwidth; + M += rs->bandwidth_kb; + Mtotal += Wmm*rs->bandwidth_kb; } } else { log_warn(LD_BUG, "Missing consensus bandwidth for router %s", @@ -2981,6 +2850,16 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, log_warn(LD_DIR, "known-flags not in order"); goto err; } + if (ns->type != NS_TYPE_CONSENSUS && + smartlist_len(ns->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) { + /* If we allowed more than 64 flags in votes, then parsing them would make + * us invoke undefined behavior whenever we used 1<<flagnum to do a + * bit-shift. This is only for votes and opinions: consensus users don't + * care about flags they don't recognize, and so don't build a bitfield + * for them. */ + log_warn(LD_DIR, "Too many known-flags in consensus vote or opinion"); + goto err; + } tok = find_opt_by_keyword(tokens, K_PARAMS); if (tok) { @@ -3607,6 +3486,10 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) /** Parse the addr policy in the string <b>s</b> and return it. If * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or * ADDR_POLICY_REJECT) for items that specify no action. + * + * The addr_policy_t returned by this function can have its address set to + * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair + * of AF_INET and AF_INET6 items. */ addr_policy_t * router_parse_addr_policy_item_from_string(const char *s, int assume_action) @@ -3636,7 +3519,7 @@ router_parse_addr_policy_item_from_string(const char *s, int assume_action) eos = cp + strlen(cp); area = memarea_new(); tok = get_next_token(area, &cp, eos, routerdesc_token_table); - if (tok->tp == _ERR) { + if (tok->tp == ERR_) { log_warn(LD_DIR, "Error reading address policy: %s", tok->error); goto err; } @@ -3646,7 +3529,7 @@ router_parse_addr_policy_item_from_string(const char *s, int assume_action) goto err; } - r = router_parse_addr_policy(tok); + r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR); goto done; err: r = NULL; @@ -3665,7 +3548,7 @@ static int router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) { addr_policy_t *newe; - newe = router_parse_addr_policy(tok); + newe = router_parse_addr_policy(tok, 0); if (!newe) return -1; if (! router->exit_policy) @@ -3690,7 +3573,7 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) /** Given a K_ACCEPT or K_REJECT token and a router, create and return * a new exit_policy_t corresponding to the token. */ static addr_policy_t * -router_parse_addr_policy(directory_token_t *tok) +router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags) { addr_policy_t newe; char *arg; @@ -3712,7 +3595,7 @@ router_parse_addr_policy(directory_token_t *tok) else newe.policy_type = ADDR_POLICY_ACCEPT; - if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits, + if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits, &newe.prt_min, &newe.prt_max) < 0) { log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg)); return NULL; @@ -3789,14 +3672,14 @@ token_clear(directory_token_t *tok) STMT_BEGIN \ if (tok) token_clear(tok); \ tok = ALLOC_ZERO(sizeof(directory_token_t)); \ - tok->tp = _ERR; \ + tok->tp = ERR_; \ tok->error = STRDUP(msg); \ goto done_tokenizing; \ STMT_END /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>. - * Return <b>tok</b> on success, or a new _ERR token if the token didn't + * Return <b>tok</b> on success, or a new ERR_ token if the token didn't * conform to the syntax we wanted. **/ static INLINE directory_token_t * @@ -3915,7 +3798,7 @@ get_next_token(memarea_t *area, tor_assert(area); tok = ALLOC_ZERO(sizeof(directory_token_t)); - tok->tp = _ERR; + tok->tp = ERR_; /* Set *s to first token, eol to end-of-line, next to after first token */ *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */ @@ -3972,10 +3855,10 @@ get_next_token(memarea_t *area, } } - if (tok->tp == _ERR) { + if (tok->tp == ERR_) { /* No keyword matched; call it an "K_opt" or "A_unrecognized" */ if (**s == '@') - tok->tp = _A_UNKNOWN; + tok->tp = A_UNKNOWN_; else tok->tp = K_OPT; tok->args = ALLOC(sizeof(char*)); @@ -4014,7 +3897,7 @@ get_next_token(memarea_t *area, if ((size_t)(eol-next) != 9+obname_len+5 || strcmp_len(next+9, tok->object_type, obname_len) || strcmp_len(eol-5, "-----", 5)) { - snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s", + tor_snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s", tok->object_type); ebuf[sizeof(ebuf)-1] = '\0'; RET_ERR(ebuf); @@ -4065,23 +3948,30 @@ tokenize_string(memarea_t *area, { const char **s; directory_token_t *tok = NULL; - int counts[_NIL]; + int counts[NIL_]; int i; int first_nonannotation; int prev_len = smartlist_len(out); tor_assert(area); s = &start; - if (!end) + if (!end) { end = start+strlen(start); - for (i = 0; i < _NIL; ++i) + } else { + /* it's only meaningful to check for nuls if we got an end-of-string ptr */ + if (memchr(start, '\0', end-start)) { + log_warn(LD_DIR, "parse error: internal NUL character."); + return -1; + } + } + for (i = 0; i < NIL_; ++i) counts[i] = 0; SMARTLIST_FOREACH(out, const directory_token_t *, t, ++counts[t->tp]); - while (*s < end && (!tok || tok->tp != _EOF)) { + while (*s < end && (!tok || tok->tp != EOF_)) { tok = get_next_token(area, s, end, table); - if (tok->tp == _ERR) { + if (tok->tp == ERR_) { log_warn(LD_DIR, "parse error: %s", tok->error); token_clear(tok); return -1; @@ -4171,7 +4061,7 @@ find_opt_by_keyword(smartlist_t *s, directory_keyword keyword) * with an assert if no such keyword is found. */ static directory_token_t * -_find_by_keyword(smartlist_t *s, directory_keyword keyword, +find_by_keyword_(smartlist_t *s, directory_keyword keyword, const char *keyword_as_string) { directory_token_t *tok = find_opt_by_keyword(s, keyword); @@ -4259,8 +4149,8 @@ router_get_hash_impl_helper(const char *s, size_t s_len, /** 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. + * first subsequent occurrence of <b>end_str</b>; store the 20-byte or 32-byte + * result in <b>digest</b>; return 0 on success. * * If no such substring exists, return -1. */ @@ -4363,12 +4253,17 @@ find_start_of_next_microdesc(const char *s, const char *eos) /** 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 + * annotations we recognize and ignore ones we don't. + * + * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each + * descriptor in the body field of each microdesc_t. + * + * 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) + int allow_annotations, + saved_location_t where) { smartlist_t *tokens; smartlist_t *result; @@ -4377,6 +4272,7 @@ microdescs_parse_from_string(const char *s, const char *eos, const char *start = s; const char *start_of_next_microdesc; int flags = allow_annotations ? TS_ANNOTATIONS_OK : 0; + const int copy_body = (where != SAVED_IN_CACHE); directory_token_t *tok; @@ -4406,8 +4302,9 @@ microdescs_parse_from_string(const char *s, const char *eos, tor_assert(cp); md->bodylen = start_of_next_microdesc - cp; + md->saved_location = where; if (copy_body) - md->body = tor_strndup(cp, md->bodylen); + md->body = tor_memdup_nulterm(cp, md->bodylen); else md->body = (char*)cp; md->off = cp - start; @@ -4429,6 +4326,25 @@ microdescs_parse_from_string(const char *s, const char *eos, md->onion_pkey = tok->key; tok->key = NULL; + if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) { + curve25519_public_key_t k; + tor_assert(tok->n_args >= 1); + if (curve25519_public_from_base64(&k, tok->args[0]) < 0) { + log_warn(LD_DIR, "Bogus ntor-onion-key in microdesc"); + goto next; + } + md->onion_curve25519_pkey = + tor_memdup(&k, sizeof(curve25519_public_key_t)); + } + + { + smartlist_t *a_lines = find_all_by_keyword(tokens, K_A); + if (a_lines) { + find_single_ipv6_orport(a_lines, &md->ipv6_addr, &md->ipv6_orport); + smartlist_free(a_lines); + } + } + if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) { int i; md->family = smartlist_new(); @@ -4445,6 +4361,9 @@ microdescs_parse_from_string(const char *s, const char *eos, if ((tok = find_opt_by_keyword(tokens, K_P))) { md->exit_policy = parse_short_policy(tok->args[0]); } + if ((tok = find_opt_by_keyword(tokens, K_P6))) { + md->ipv6_exit_policy = parse_short_policy(tok->args[0]); + } crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256); @@ -4664,7 +4583,7 @@ tor_version_same_series(tor_version_t *a, tor_version_t *b) * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent. * Used to sort a list of versions. */ static int -_compare_tor_version_str_ptr(const void **_a, const void **_b) +compare_tor_version_str_ptr_(const void **_a, const void **_b) { const char *a = *_a, *b = *_b; int ca, cb; @@ -4688,10 +4607,10 @@ _compare_tor_version_str_ptr(const void **_a, const void **_b) void sort_version_list(smartlist_t *versions, int remove_duplicates) { - smartlist_sort(versions, _compare_tor_version_str_ptr); + smartlist_sort(versions, compare_tor_version_str_ptr_); if (remove_duplicates) - smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free); + smartlist_uniq(versions, compare_tor_version_str_ptr_, tor_free_); } /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>, diff --git a/src/or/routerparse.h b/src/or/routerparse.h index c6382a7f6b..eb2e885cb1 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,18 +9,19 @@ * \brief Header file for routerparse.c. **/ -#ifndef _TOR_ROUTERPARSE_H -#define _TOR_ROUTERPARSE_H +#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, size_t s_len, char *digest); #define DIROBJ_MAX_SIG_LEN 256 +char *router_get_dirobj_signature(const char *digest, + size_t digest_len, + crypto_pk_t *private_key); int router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, size_t digest_len, @@ -31,8 +32,6 @@ int router_parse_list_from_string(const char **s, const char *eos, 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, @@ -54,8 +53,9 @@ 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); +int compare_vote_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); +int networkstatus_verify_bw_weights(networkstatus_t *ns, int); networkstatus_t *networkstatus_parse_vote_from_string(const char *s, const char **eos_out, networkstatus_type_t ns_type); @@ -64,7 +64,7 @@ ns_detached_signatures_t *networkstatus_parse_detached_signatures( smartlist_t *microdescs_parse_from_string(const char *s, const char *eos, int allow_annotations, - int copy_body); + saved_location_t where); authority_cert_t *authority_cert_parse_from_string(const char *s, const char **end_of_string); diff --git a/src/or/routerset.c b/src/or/routerset.c new file mode 100644 index 0000000000..2e41f7f6c4 --- /dev/null +++ b/src/or/routerset.c @@ -0,0 +1,466 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "geoip.h" +#include "nodelist.h" +#include "policies.h" +#include "router.h" +#include "routerparse.h" +#include "routerset.h" + +/** A routerset specifies constraints on a set of possible routerinfos, based + * on their names, identities, or addresses. It is optimized for determining + * whether a router is a member or not, in O(1+P) time, where P is the number + * of address policy constraints. */ +struct routerset_t { + /** A list of strings for the elements of the policy. Each string is either + * a nickname, a hexadecimal identity fingerprint, or an address policy. A + * router belongs to the set if its nickname OR its identity OR its address + * matches an entry here. */ + smartlist_t *list; + /** A map from lowercase nicknames of routers in the set to (void*)1 */ + strmap_t *names; + /** A map from identity digests routers in the set to (void*)1 */ + digestmap_t *digests; + /** An address policy for routers in the set. For implementation reasons, + * a router belongs to the set if it is _rejected_ by this policy. */ + smartlist_t *policies; + + /** A human-readable description of what this routerset is for. Used in + * log messages. */ + char *description; + + /** A list of the country codes in this set. */ + smartlist_t *country_names; + /** Total number of countries we knew about when we built <b>countries</b>.*/ + int n_countries; + /** Bit array mapping the return value of geoip_get_country() to 1 iff the + * country is a member of this routerset. Note that we MUST call + * routerset_refresh_countries() whenever the geoip country list is + * reloaded. */ + bitarray_t *countries; +}; + +/** Return a new empty routerset. */ +routerset_t * +routerset_new(void) +{ + routerset_t *result = tor_malloc_zero(sizeof(routerset_t)); + result->list = smartlist_new(); + result->names = strmap_new(); + result->digests = digestmap_new(); + result->policies = smartlist_new(); + result->country_names = smartlist_new(); + return result; +} + +/** If <b>c</b> is a country code in the form {cc}, return a newly allocated + * string holding the "cc" part. Else, return NULL. */ +static char * +routerset_get_countryname(const char *c) +{ + char *country; + + if (strlen(c) < 4 || c[0] !='{' || c[3] !='}') + return NULL; + + country = tor_strndup(c+1, 2); + tor_strlower(country); + return country; +} + +/** Update the routerset's <b>countries</b> bitarray_t. Called whenever + * the GeoIP IPv4 database is reloaded. + */ +void +routerset_refresh_countries(routerset_t *target) +{ + int cc; + bitarray_free(target->countries); + + if (!geoip_is_loaded(AF_INET)) { + target->countries = NULL; + target->n_countries = 0; + return; + } + target->n_countries = geoip_get_n_countries(); + target->countries = bitarray_init_zero(target->n_countries); + SMARTLIST_FOREACH_BEGIN(target->country_names, const char *, country) { + cc = geoip_get_country(country); + if (cc >= 0) { + tor_assert(cc < target->n_countries); + bitarray_set(target->countries, cc); + } else { + log_warn(LD_CONFIG, "Country code '%s' is not recognized.", + country); + } + } SMARTLIST_FOREACH_END(country); +} + +/** Parse the string <b>s</b> to create a set of routerset entries, and add + * them to <b>target</b>. In log messages, refer to the string as + * <b>description</b>. Return 0 on success, -1 on failure. + * + * Three kinds of elements are allowed in routersets: nicknames, IP address + * patterns, and fingerprints. They may be surrounded by optional space, and + * must be separated by commas. + */ +int +routerset_parse(routerset_t *target, const char *s, const char *description) +{ + int r = 0; + int added_countries = 0; + char *countryname; + smartlist_t *list = smartlist_new(); + smartlist_split_string(list, s, ",", + SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0); + SMARTLIST_FOREACH_BEGIN(list, char *, nick) { + addr_policy_t *p; + if (is_legal_hexdigest(nick)) { + char d[DIGEST_LEN]; + if (*nick == '$') + ++nick; + log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description); + base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN); + digestmap_set(target->digests, d, (void*)1); + } else if (is_legal_nickname(nick)) { + log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description); + strmap_set_lc(target->names, nick, (void*)1); + } else if ((countryname = routerset_get_countryname(nick)) != NULL) { + log_debug(LD_CONFIG, "Adding country %s to %s", nick, + description); + smartlist_add(target->country_names, countryname); + added_countries = 1; + } else if ((strchr(nick,'.') || strchr(nick, '*')) && + (p = router_parse_addr_policy_item_from_string( + nick, ADDR_POLICY_REJECT))) { + log_debug(LD_CONFIG, "Adding address %s to %s", nick, description); + smartlist_add(target->policies, p); + } else { + log_warn(LD_CONFIG, "Entry '%s' in %s is malformed.", nick, + description); + r = -1; + tor_free(nick); + SMARTLIST_DEL_CURRENT(list, nick); + } + } SMARTLIST_FOREACH_END(nick); + policy_expand_unspec(&target->policies); + smartlist_add_all(target->list, list); + smartlist_free(list); + if (added_countries) + routerset_refresh_countries(target); + return r; +} + +/** Add all members of the set <b>source</b> to <b>target</b>. */ +void +routerset_union(routerset_t *target, const routerset_t *source) +{ + char *s; + tor_assert(target); + if (!source || !source->list) + return; + s = routerset_to_string(source); + routerset_parse(target, s, "other routerset"); + tor_free(s); +} + +/** Return true iff <b>set</b> lists only nicknames and digests, and includes + * no IP ranges or countries. */ +int +routerset_is_list(const routerset_t *set) +{ + return smartlist_len(set->country_names) == 0 && + smartlist_len(set->policies) == 0; +} + +/** Return true iff we need a GeoIP IP-to-country database to make sense of + * <b>set</b>. */ +int +routerset_needs_geoip(const routerset_t *set) +{ + return set && smartlist_len(set->country_names); +} + +/** Return true iff there are no entries in <b>set</b>. */ +int +routerset_is_empty(const routerset_t *set) +{ + return !set || smartlist_len(set->list) == 0; +} + +/** Helper. Return true iff <b>set</b> contains a router based on the other + * provided fields. Return higher values for more specific subentries: a + * single router is more specific than an address range of routers, which is + * more specific in turn than a country code. + * + * (If country is -1, then we take the country + * from addr.) */ +static int +routerset_contains(const routerset_t *set, const tor_addr_t *addr, + uint16_t orport, + const char *nickname, const char *id_digest, + country_t country) +{ + if (!set || !set->list) + return 0; + if (nickname && strmap_get_lc(set->names, nickname)) + return 4; + if (id_digest && digestmap_get(set->digests, id_digest)) + return 4; + if (addr && compare_tor_addr_to_addr_policy(addr, orport, set->policies) + == ADDR_POLICY_REJECTED) + return 3; + if (set->countries) { + if (country < 0 && addr) + country = geoip_get_country_by_addr(addr); + + if (country >= 0 && country < set->n_countries && + bitarray_is_set(set->countries, country)) + return 2; + } + return 0; +} + +/** If *<b>setp</b> includes at least one country code, or if + * <b>only_some_cc_set</b> is 0, add the ?? and A1 country codes to + * *<b>setp</b>, creating it as needed. Return true iff *<b>setp</b> changed. + */ +int +routerset_add_unknown_ccs(routerset_t **setp, int only_if_some_cc_set) +{ + routerset_t *set; + int add_unknown, add_a1; + if (only_if_some_cc_set) { + if (!*setp || smartlist_len((*setp)->country_names) == 0) + return 0; + } + if (!*setp) + *setp = routerset_new(); + + set = *setp; + + add_unknown = ! smartlist_contains_string_case(set->country_names, "??") && + geoip_get_country("??") >= 0; + add_a1 = ! smartlist_contains_string_case(set->country_names, "a1") && + geoip_get_country("A1") >= 0; + + if (add_unknown) { + smartlist_add(set->country_names, tor_strdup("??")); + smartlist_add(set->list, tor_strdup("{??}")); + } + if (add_a1) { + smartlist_add(set->country_names, tor_strdup("a1")); + smartlist_add(set->list, tor_strdup("{a1}")); + } + + if (add_unknown || add_a1) { + routerset_refresh_countries(set); + return 1; + } + return 0; +} + +/** Return true iff we can tell that <b>ei</b> is a member of <b>set</b>. */ +int +routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei) +{ + return routerset_contains(set, + &ei->addr, + ei->port, + ei->nickname, + ei->identity_digest, + -1 /*country*/); +} + +/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we + * look up the country. */ +int +routerset_contains_router(const routerset_t *set, const routerinfo_t *ri, + country_t country) +{ + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, ri->addr); + return routerset_contains(set, + &addr, + ri->or_port, + ri->nickname, + ri->cache_info.identity_digest, + country); +} + +/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we + * look up the country. */ +int +routerset_contains_routerstatus(const routerset_t *set, + const routerstatus_t *rs, + country_t country) +{ + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, rs->addr); + return routerset_contains(set, + &addr, + rs->or_port, + rs->nickname, + rs->identity_digest, + country); +} + +/** Return true iff <b>node</b> is in <b>set</b>. */ +int +routerset_contains_node(const routerset_t *set, const node_t *node) +{ + if (node->rs) + return routerset_contains_routerstatus(set, node->rs, node->country); + else if (node->ri) + return routerset_contains_router(set, node->ri, node->country); + else + return 0; +} + +/** Add every known node_t that is a member of <b>routerset</b> to + * <b>out</b>, but never add any that are part of <b>excludeset</b>. + * If <b>running_only</b>, only add the running ones. */ +void +routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset, + const routerset_t *excludeset, int running_only) +{ + tor_assert(out); + if (!routerset || !routerset->list) + return; + + if (routerset_is_list(routerset)) { + /* No routers are specified by type; all are given by name or digest. + * we can do a lookup in O(len(routerset)). */ + SMARTLIST_FOREACH(routerset->list, const char *, name, { + const node_t *node = node_get_by_nickname(name, 1); + if (node) { + if (!running_only || node->is_running) + if (!routerset_contains_node(excludeset, node)) + smartlist_add(out, (void*)node); + } + }); + } else { + /* We need to iterate over the routerlist to get all the ones of the + * right kind. */ + smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, const node_t *, node, { + if (running_only && !node->is_running) + continue; + if (routerset_contains_node(routerset, node) && + !routerset_contains_node(excludeset, node)) + smartlist_add(out, (void*)node); + }); + } +} + +#if 0 +/** Add to <b>target</b> every node_t from <b>source</b> except: + * + * 1) Don't add it if <b>include</b> is non-empty and the relay isn't in + * <b>include</b>; and + * 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_node_disjunction(smartlist_t *target, + const smartlist_t *source, + const routerset_t *include, + const routerset_t *exclude, int running_only) +{ + SMARTLIST_FOREACH(source, const node_t *, node, { + int include_result; + if (running_only && !node->is_running) + continue; + if (!routerset_is_empty(include)) + include_result = routerset_contains_node(include, node); + else + include_result = 1; + + if (include_result) { + int exclude_result = routerset_contains_node(exclude, node); + if (include_result >= exclude_result) + smartlist_add(target, (void*)node); + } + }); +} +#endif + +/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */ +void +routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset) +{ + tor_assert(lst); + if (!routerset) + return; + SMARTLIST_FOREACH(lst, const node_t *, node, { + if (routerset_contains_node(routerset, node)) { + //log_debug(LD_DIR, "Subtracting %s",r->nickname); + SMARTLIST_DEL_CURRENT(lst, node); + } + }); +} + +/** Return a new string that when parsed by routerset_parse_string() will + * yield <b>set</b>. */ +char * +routerset_to_string(const routerset_t *set) +{ + if (!set || !set->list) + return tor_strdup(""); + return smartlist_join_strings(set->list, ",", 0, NULL); +} + +/** Helper: return true iff old and new are both NULL, or both non-NULL + * equal routersets. */ +int +routerset_equal(const routerset_t *old, const routerset_t *new) +{ + if (routerset_is_empty(old) && routerset_is_empty(new)) { + /* Two empty sets are equal */ + return 1; + } else if (routerset_is_empty(old) || routerset_is_empty(new)) { + /* An empty set is equal to nothing else. */ + return 0; + } + tor_assert(old != NULL); + tor_assert(new != NULL); + + if (smartlist_len(old->list) != smartlist_len(new->list)) + return 0; + + SMARTLIST_FOREACH(old->list, const char *, cp1, { + const char *cp2 = smartlist_get(new->list, cp1_sl_idx); + if (strcmp(cp1, cp2)) + return 0; + }); + + return 1; +} + +/** 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, + addr_policy_free(p)); + smartlist_free(routerset->policies); + SMARTLIST_FOREACH(routerset->country_names, char *, cp, tor_free(cp)); + smartlist_free(routerset->country_names); + + strmap_free(routerset->names, NULL); + digestmap_free(routerset->digests, NULL); + bitarray_free(routerset->countries); + tor_free(routerset); +} + diff --git a/src/or/routerset.h b/src/or/routerset.h new file mode 100644 index 0000000000..bfa0c59ac1 --- /dev/null +++ b/src/or/routerset.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file routerlist.h + * \brief Header file for routerset.c + **/ + +#ifndef TOR_ROUTERSET_H +#define TOR_ROUTERSET_H + +routerset_t *routerset_new(void); +void routerset_refresh_countries(routerset_t *rs); +int routerset_parse(routerset_t *target, const char *s, + const char *description); +void routerset_union(routerset_t *target, const routerset_t *source); +int routerset_is_list(const routerset_t *set); +int routerset_needs_geoip(const routerset_t *set); +int routerset_is_empty(const routerset_t *set); +int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri, + country_t country); +int routerset_contains_routerstatus(const routerset_t *set, + const routerstatus_t *rs, + country_t country); +int routerset_contains_extendinfo(const routerset_t *set, + const extend_info_t *ei); + +int routerset_contains_node(const routerset_t *set, const node_t *node); +void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset, + const routerset_t *excludeset, + int running_only); +int routerset_add_unknown_ccs(routerset_t **setp, int only_if_some_cc_set); +#if 0 +void routersets_get_node_disjunction(smartlist_t *target, + const smartlist_t *source, + const routerset_t *include, + const routerset_t *exclude, int running_only); +#endif +void routerset_subtract_nodes(smartlist_t *out, + const routerset_t *routerset); + +char *routerset_to_string(const routerset_t *routerset); +int routerset_equal(const routerset_t *old, const routerset_t *new); +void routerset_free(routerset_t *routerset); + +#endif + diff --git a/src/or/statefile.c b/src/or/statefile.c new file mode 100644 index 0000000000..bcb7b07417 --- /dev/null +++ b/src/or/statefile.c @@ -0,0 +1,616 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "circuitstats.h" +#include "config.h" +#include "confparse.h" +#include "entrynodes.h" +#include "hibernate.h" +#include "rephist.h" +#include "router.h" +#include "statefile.h" + +/** A list of state-file "abbreviations," for compatibility. */ +static config_abbrev_t state_abbrevs_[] = { + { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 }, + { "HelperNode", "EntryGuard", 0, 0 }, + { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 }, + { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 }, + { "EntryNode", "EntryGuard", 0, 0 }, + { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 }, + { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 }, + { NULL, NULL, 0, 0}, +}; + +/*XXXX these next two are duplicates or near-duplicates from config.c */ +#define VAR(name,conftype,member,initvalue) \ + { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), \ + initvalue } +/** As VAR, but the option name and member name are the same. */ +#define V(member,conftype,initvalue) \ + VAR(#member, conftype, member, initvalue) + +/** Array of "state" variables saved to the ~/.tor/state file. */ +static config_var_t state_vars_[] = { + /* Remember to document these in state-contents.txt ! */ + + V(AccountingBytesReadInInterval, MEMUNIT, NULL), + V(AccountingBytesWrittenInInterval, MEMUNIT, NULL), + 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), + VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL), + VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL), + VAR("EntryGuardPathBias", LINELIST_S, EntryGuards, NULL), + VAR("EntryGuardPathUseBias", LINELIST_S, EntryGuards, NULL), + V(EntryGuards, LINELIST_V, NULL), + + VAR("TransportProxy", LINELIST_S, TransportProxies, NULL), + V(TransportProxies, LINELIST_V, NULL), + + V(BWHistoryReadEnds, ISOTIME, NULL), + V(BWHistoryReadInterval, UINT, "900"), + V(BWHistoryReadValues, CSV, ""), + V(BWHistoryReadMaxima, CSV, ""), + V(BWHistoryWriteEnds, ISOTIME, NULL), + V(BWHistoryWriteInterval, UINT, "900"), + V(BWHistoryWriteValues, CSV, ""), + V(BWHistoryWriteMaxima, CSV, ""), + V(BWHistoryDirReadEnds, ISOTIME, NULL), + V(BWHistoryDirReadInterval, UINT, "900"), + V(BWHistoryDirReadValues, CSV, ""), + V(BWHistoryDirReadMaxima, CSV, ""), + V(BWHistoryDirWriteEnds, ISOTIME, NULL), + V(BWHistoryDirWriteInterval, UINT, "900"), + V(BWHistoryDirWriteValues, CSV, ""), + V(BWHistoryDirWriteMaxima, 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 } +}; + +#undef VAR +#undef V + +static int or_state_validate(or_state_t *old_options, or_state_t *options, + int from_setconf, char **msg); + +/** Magic value for or_state_t. */ +#define OR_STATE_MAGIC 0x57A73f57 + +/** "Extra" variable in the state that receives lines we can't parse. This + * lets us preserve options from versions of Tor newer than us. */ +static config_var_t state_extra_var = { + "__extra", CONFIG_TYPE_LINELIST, STRUCT_OFFSET(or_state_t, ExtraLines), NULL +}; + +/** Configuration format for or_state_t. */ +static const config_format_t state_format = { + sizeof(or_state_t), + OR_STATE_MAGIC, + STRUCT_OFFSET(or_state_t, magic_), + state_abbrevs_, + state_vars_, + (validate_fn_t)or_state_validate, + &state_extra_var, +}; + +/** Persistent serialized state. */ +static or_state_t *global_state = NULL; + +/** Return the persistent state struct for this Tor. */ +or_state_t * +get_or_state(void) +{ + tor_assert(global_state); + return global_state; +} + +/** Return true iff we have loaded the global state for this Tor */ +int +or_state_loaded(void) +{ + return global_state != NULL; +} + +/** Return true if <b>line</b> is a valid state TransportProxy line. + * Return false otherwise. */ +static int +state_transport_line_is_valid(const char *line) +{ + smartlist_t *items = NULL; + char *addrport=NULL; + tor_addr_t addr; + uint16_t port = 0; + int r; + + items = smartlist_new(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(items) != 2) { + log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line."); + goto err; + } + + addrport = smartlist_get(items, 1); + if (tor_addr_port_lookup(addrport, &addr, &port) < 0) { + log_warn(LD_CONFIG, "state: Could not parse addrport."); + goto err; + } + + if (!port) { + log_warn(LD_CONFIG, "state: Transport line did not contain port."); + goto err; + } + + r = 1; + goto done; + + err: + r = 0; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + return r; +} + +/** Return 0 if all TransportProxy lines in <b>state</b> are well + * formed. Otherwise, return -1. */ +static int +validate_transports_in_state(or_state_t *state) +{ + int broken = 0; + config_line_t *line; + + for (line = state->TransportProxies ; line ; line = line->next) { + tor_assert(!strcmp(line->key, "TransportProxy")); + if (!state_transport_line_is_valid(line->value)) + broken = 1; + } + + if (broken) + log_warn(LD_CONFIG, "state: State file seems to be broken."); + + return 0; +} + +/** Return 0 if every setting in <b>state</b> is reasonable, and a + * permissible transition from <b>old_state</b>. Else warn and return -1. + * Should have no side effects, except for normalizing the contents of + * <b>state</b>. + */ +/* XXX from_setconf is here because of bug 238 */ +static int +or_state_validate(or_state_t *old_state, or_state_t *state, + int from_setconf, char **msg) +{ + /* We don't use these; only options do. Still, we need to match that + * signature. */ + (void) from_setconf; + (void) old_state; + + if (entry_guards_parse_state(state, 0, msg)<0) + return -1; + + if (validate_transports_in_state(state)<0) + return -1; + + return 0; +} + +/** Replace the current persistent state with <b>new_state</b> */ +static int +or_state_set(or_state_t *new_state) +{ + char *err = NULL; + int ret = 0; + tor_assert(new_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; + char *fname2 = NULL; + for (i = 0; i < 100; ++i) { + tor_asprintf(&fname2, "%s.%d", fname, i); + status = file_status(fname2); + if (status == FN_NOENT) + break; + tor_free(fname2); + } + 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. + * Return 0 on success, less than 0 on failure. + */ +int +or_state_load(void) +{ + or_state_t *new_state = NULL; + char *contents = NULL, *fname; + char *errmsg = NULL; + int r = -1, badstate = 0; + + fname = get_datadir_fname("state"); + switch (file_status(fname)) { + case FN_FILE: + if (!(contents = read_file_to_str(fname, 0, NULL))) { + log_warn(LD_FS, "Unable to read state file \"%s\"", fname); + goto done; + } + break; + case FN_NOENT: + break; + case FN_ERROR: + case FN_DIR: + default: + log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname); + goto done; + } + new_state = tor_malloc_zero(sizeof(or_state_t)); + new_state->magic_ = OR_STATE_MAGIC; + config_init(&state_format, new_state); + if (contents) { + config_line_t *lines=NULL; + int assign_retval; + if (config_get_lines(contents, &lines, 0)<0) + goto done; + assign_retval = config_assign(&state_format, new_state, + lines, 0, 0, &errmsg); + config_free_lines(lines); + if (assign_retval<0) + badstate = 1; + if (errmsg) { + log_warn(LD_GENERAL, "%s", errmsg); + tor_free(errmsg); + } + } + + if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0) + badstate = 1; + + if (errmsg) { + log_warn(LD_GENERAL, "%s", errmsg); + tor_free(errmsg); + } + + if (badstate && !contents) { + log_warn(LD_BUG, "Uh oh. We couldn't even validate our own default state." + " This is a bug in Tor."); + goto done; + } else if (badstate && contents) { + or_state_save_broken(fname); + + tor_free(contents); + config_free(&state_format, new_state); + + new_state = tor_malloc_zero(sizeof(or_state_t)); + new_state->magic_ = OR_STATE_MAGIC; + config_init(&state_format, new_state); + } else if (contents) { + log_info(LD_GENERAL, "Loaded state from \"%s\"", fname); + } else { + log_info(LD_GENERAL, "Initialized state"); + } + if (or_state_set(new_state) == -1) { + or_state_save_broken(fname); + } + new_state = NULL; + if (!contents) { + global_state->next_write = 0; + or_state_save(time(NULL)); + } + r = 0; + + done: + tor_free(fname); + tor_free(contents); + if (new_state) + config_free(&state_format, new_state); + + return r; +} + +/** Did the last time we tried to write the state file fail? If so, we + * should consider disabling such features as preemptive circuit generation + * to compute circuit-build-time. */ +static int last_state_file_write_failed = 0; + +/** Return whether the state file failed to write last time we tried. */ +int +did_last_state_file_write_fail(void) +{ + return last_state_file_write_failed; +} + +/** If writing the state to disk fails, try again after this many seconds. */ +#define STATE_WRITE_RETRY_INTERVAL 3600 + +/** If we're a relay, how often should we checkpoint our state file even + * if nothing else dirties it? This will checkpoint ongoing stats like + * bandwidth used, per-country user stats, etc. */ +#define STATE_RELAY_CHECKPOINT_INTERVAL (12*60*60) + +/** Write the persistent state to disk. Return 0 for success, <0 on failure. */ +int +or_state_save(time_t now) +{ + char *state, *contents; + char tbuf[ISO_TIME_LEN+1]; + char *fname; + + tor_assert(global_state); + + if (global_state->next_write > now) + return 0; + + /* Call everything else that might dirty the state even more, in order + * 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 = now; + + tor_free(global_state->TorVersion); + tor_asprintf(&global_state->TorVersion, "Tor %s", get_version()); + + state = config_dump(&state_format, NULL, global_state, 1, 0); + format_local_iso_time(tbuf, now); + tor_asprintf(&contents, + "# Tor state file last generated on %s local time\n" + "# Other times below are in UTC\n" + "# You *do not* need to edit this file.\n\n%s", + tbuf, state); + tor_free(state); + 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\"; " + "will try again later", fname); + last_state_file_write_failed = 1; + tor_free(fname); + tor_free(contents); + /* Try again after STATE_WRITE_RETRY_INTERVAL (or sooner, if the state + * changes sooner). */ + global_state->next_write = now + STATE_WRITE_RETRY_INTERVAL; + return -1; + } + + last_state_file_write_failed = 0; + log_info(LD_GENERAL, "Saved state to \"%s\"", fname); + tor_free(fname); + tor_free(contents); + + if (server_mode(get_options())) + global_state->next_write = now + STATE_RELAY_CHECKPOINT_INTERVAL; + else + global_state->next_write = TIME_MAX; + + return 0; +} + +/** Return the config line for transport <b>transport</b> in the current state. + * Return NULL if there is no config line for <b>transport</b>. */ +static config_line_t * +get_transport_in_state_by_name(const char *transport) +{ + or_state_t *or_state = get_or_state(); + config_line_t *line; + config_line_t *ret = NULL; + smartlist_t *items = NULL; + + for (line = or_state->TransportProxies ; line ; line = line->next) { + tor_assert(!strcmp(line->key, "TransportProxy")); + + items = smartlist_new(); + smartlist_split_string(items, line->value, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + if (smartlist_len(items) != 2) /* broken state */ + goto done; + + if (!strcmp(smartlist_get(items, 0), transport)) { + ret = line; + goto done; + } + + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + items = NULL; + } + + done: + if (items) { + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + } + return ret; +} + +/** Return string containing the address:port part of the + * TransportProxy <b>line</b> for transport <b>transport</b>. + * If the line is corrupted, return NULL. */ +static const char * +get_transport_bindaddr(const char *line, const char *transport) +{ + char *line_tmp = NULL; + + if (strlen(line) < strlen(transport) + 2) { + goto broken_state; + } else { + /* line should start with the name of the transport and a space. + (for example, "obfs2 127.0.0.1:47245") */ + tor_asprintf(&line_tmp, "%s ", transport); + if (strcmpstart(line, line_tmp)) + goto broken_state; + + tor_free(line_tmp); + return (line+strlen(transport)+1); + } + + broken_state: + tor_free(line_tmp); + return NULL; +} + +/** Return a string containing the address:port that a proxy transport + * should bind on. The string is stored on the heap and must be freed + * by the caller of this function. */ +char * +get_stored_bindaddr_for_server_transport(const char *transport) +{ + char *default_addrport = NULL; + const char *stored_bindaddr = NULL; + config_line_t *line = NULL; + + { + /* See if the user explicitly asked for a specific listening + address for this transport. */ + char *conf_bindaddr = get_transport_bindaddr_from_config(transport); + if (conf_bindaddr) + return conf_bindaddr; + } + + line = get_transport_in_state_by_name(transport); + if (!line) /* Found no references in state for this transport. */ + goto no_bindaddr_found; + + stored_bindaddr = get_transport_bindaddr(line->value, transport); + if (stored_bindaddr) /* found stored bindaddr in state file. */ + return tor_strdup(stored_bindaddr); + + no_bindaddr_found: + /** If we didn't find references for this pluggable transport in the + state file, we should instruct the pluggable transport proxy to + listen on INADDR_ANY on a random ephemeral port. */ + tor_asprintf(&default_addrport, "%s:%s", fmt_addr32(INADDR_ANY), "0"); + return default_addrport; +} + +/** Save <b>transport</b> listening on <b>addr</b>:<b>port</b> to + state */ +void +save_transport_to_state(const char *transport, + const tor_addr_t *addr, uint16_t port) +{ + or_state_t *state = get_or_state(); + + char *transport_addrport=NULL; + + /** find where to write on the state */ + config_line_t **next, *line; + + /* see if this transport is already stored in state */ + config_line_t *transport_line = + get_transport_in_state_by_name(transport); + + if (transport_line) { /* if transport already exists in state... */ + const char *prev_bindaddr = /* get its addrport... */ + get_transport_bindaddr(transport_line->value, transport); + transport_addrport = tor_strdup(fmt_addrport(addr, port)); + + /* if transport in state has the same address as this one, life is good */ + if (!strcmp(prev_bindaddr, transport_addrport)) { + log_info(LD_CONFIG, "Transport seems to have spawned on its usual " + "address:port."); + goto done; + } else { /* if addrport in state is different than the one we got */ + log_info(LD_CONFIG, "Transport seems to have spawned on different " + "address:port. Let's update the state file with the new " + "address:port"); + tor_free(transport_line->value); /* free the old line */ + /* replace old addrport line with new line */ + tor_asprintf(&transport_line->value, "%s %s", transport, + fmt_addrport(addr, port)); + } + } else { /* never seen this one before; save it in state for next time */ + log_info(LD_CONFIG, "It's the first time we see this transport. " + "Let's save its address:port"); + next = &state->TransportProxies; + /* find the last TransportProxy line in the state and point 'next' + right after it */ + line = state->TransportProxies; + while (line) { + next = &(line->next); + line = line->next; + } + + /* allocate space for the new line and fill it in */ + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("TransportProxy"); + tor_asprintf(&line->value, "%s %s", transport, fmt_addrport(addr, port)); + + next = &(line->next); + } + + if (!get_options()->AvoidDiskWrites) + or_state_mark_dirty(state, 0); + + done: + tor_free(transport_addrport); +} + +void +or_state_free_all(void) +{ + config_free(&state_format, global_state); + global_state = NULL; +} + diff --git a/src/or/statefile.h b/src/or/statefile.h new file mode 100644 index 0000000000..dcdee6c604 --- /dev/null +++ b/src/or/statefile.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_STATEFILE_H +#define TOR_STATEFILE_H + +or_state_t *get_or_state(void); +int did_last_state_file_write_fail(void); +int or_state_save(time_t now); + +void save_transport_to_state(const char *transport_name, + const tor_addr_t *addr, uint16_t port); +char *get_stored_bindaddr_for_server_transport(const char *transport); +int or_state_load(void); +int or_state_loaded(void); +void or_state_free_all(void); + +#endif + diff --git a/src/or/status.c b/src/or/status.c index 04cd96eed5..69f92ed097 100644 --- a/src/or/status.c +++ b/src/or/status.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Tor Project, Inc. */ +/* Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -10,9 +10,12 @@ #include "config.h" #include "status.h" #include "nodelist.h" +#include "relay.h" #include "router.h" #include "circuitlist.h" #include "main.h" +#include "hibernate.h" +#include "rephist.h" /** Return the total number of circuits. */ static int @@ -21,7 +24,7 @@ count_circuits(void) circuit_t *circ; int nr=0; - for (circ = _circuit_get_global_list(); circ; circ = circ->next) + for (circ = circuit_get_global_list_(); circ; circ = circ->next) nr++; return nr; @@ -84,11 +87,13 @@ log_heartbeat(time_t now) char *bw_rcvd = NULL; char *uptime = NULL; const routerinfo_t *me; + double r = tls_get_write_overhead_ratio(); + const int hibernating = we_are_hibernating(); const or_options_t *options = get_options(); (void)now; - if (public_server_mode(options)) { + if (public_server_mode(options) && !hibernating) { /* Let's check if we are in the current cached consensus. */ if (!(me = router_get_my_routerinfo())) return -1; /* Something stinks, we won't even attempt this. */ @@ -103,8 +108,22 @@ log_heartbeat(time_t now) bw_sent = bytes_to_usage(get_bytes_written()); log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d " - "circuits open. I've sent %s and received %s.", - uptime, count_circuits(),bw_sent,bw_rcvd); + "circuits open. I've sent %s and received %s.%s", + uptime, count_circuits(),bw_sent,bw_rcvd, + hibernating?" We are currently hibernating.":""); + + if (stats_n_data_cells_packaged && !hibernating) + log_notice(LD_HEARTBEAT, "Average packaged cell fullness: %2.3f%%", + 100*(U64_TO_DBL(stats_n_data_bytes_packaged) / + U64_TO_DBL(stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) ); + + if (r > 1.0) { + double overhead = ( r - 1.0 ) * 100.0; + log_notice(LD_HEARTBEAT, "TLS write overhead: %.f%%", overhead); + } + + if (public_server_mode(options)) + rep_hist_log_circuit_handshake_stats(now); tor_free(uptime); tor_free(bw_sent); diff --git a/src/or/status.h b/src/or/status.h index 189ac789e1..7c3b969c86 100644 --- a/src/or/status.h +++ b/src/or/status.h @@ -1,8 +1,8 @@ -/* Copyright (c) 2010-2012, The Tor Project, Inc. */ +/* Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_STATUS_H -#define _TOR_STATUS_H +#ifndef TOR_STATUS_H +#define TOR_STATUS_H int log_heartbeat(time_t now); diff --git a/src/or/tor_main.c b/src/or/tor_main.c index 2f4922317d..05dc0bf0bf 100644 --- a/src/or/tor_main.c +++ b/src/or/tor_main.c @@ -1,11 +1,11 @@ /* Copyright 2001-2004 Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -/** String describing which Tor subversion repository version the source was - * built from. This string is generated by a bit of shell kludging int - * src/or/Makefile.am, and is usually right. +/** String describing which Tor Git repository version the source was + * built from. This string is generated by a bit of shell kludging in + * src/or/include.am, and is usually right. */ const char tor_git_revision[] = #ifndef _MSC_VER diff --git a/src/or/transports.c b/src/or/transports.c index 4ba239562a..3749d6bb21 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Tor Project, Inc. */ +/* Copyright (c) 2011-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -39,13 +39,17 @@ * transport_t structs. * * When the managed proxy stops spitting METHOD lines (signified by a - * '{S,C}METHODS DONE' message) we register all the transports - * collected to the circuitbuild.c subsystem. At this point, the - * pointers to transport_t can be transformed into dangling pointers - * at any point by the circuitbuild.c subsystem, and so we replace all - * transport_t pointers with strings describing the transport names. - * We can still go from a transport name to a transport_t using the - * fact that each transport name uniquely identifies a transport_t. + * '{S,C}METHODS DONE' message) we pass copies of its transports to + * the bridge subsystem. We keep copies of the 'transport_t's on the + * managed proxy to be able to associate the proxy with its + * transports, and we pass copies to the bridge subsystem so that + * transports can be associated with bridges. + * [ XXX We should try see whether the two copies are really needed + * and maybe cut it into a single copy of the 'transport_t' shared + * between the managed proxy and the bridge subsystem. Preliminary + * analysis shows that both copies are needed with the current code + * logic, because of race conditions that can cause dangling + * pointers. ] * * <b>In even more detail, this is what happens when a SIGHUP * occurs:</b> @@ -90,6 +94,7 @@ #include "transports.h" #include "util.h" #include "router.h" +#include "statefile.h" static process_environment_t * create_managed_proxy_environment(const managed_proxy_t *mp); @@ -100,7 +105,7 @@ static void managed_proxy_destroy(managed_proxy_t *mp, int also_terminate_process); static void handle_finished_proxy(managed_proxy_t *mp); -static void configure_proxy(managed_proxy_t *mp); +static int configure_proxy(managed_proxy_t *mp); static void parse_method_error(const char *line, int is_server_method); #define parse_server_method_error(l) parse_method_error(l, 1) @@ -119,14 +124,228 @@ static INLINE void free_execve_args(char **arg); #define PROTO_CMETHODS_DONE "CMETHODS DONE" #define PROTO_SMETHODS_DONE "SMETHODS DONE" -/** Number of environment variables for managed proxy clients/servers. */ -#define ENVIRON_SIZE_CLIENT 3 -#define ENVIRON_SIZE_SERVER 7 /* XXX known to be too high, but that's ok */ - /** The first and only supported - at the moment - configuration protocol version. */ #define PROTO_VERSION_ONE 1 +/** A list of pluggable transports found in torrc. */ +static smartlist_t *transport_list = NULL; + +/** Returns a transport_t struct for a transport proxy supporting the + protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using + SOCKS version <b>socks_ver</b>. */ +static transport_t * +transport_new(const tor_addr_t *addr, uint16_t port, + const char *name, int socks_ver) +{ + transport_t *t = tor_malloc_zero(sizeof(transport_t)); + + tor_addr_copy(&t->addr, addr); + t->port = port; + t->name = tor_strdup(name); + t->socks_version = socks_ver; + + return t; +} + +/** Free the pluggable transport struct <b>transport</b>. */ +void +transport_free(transport_t *transport) +{ + if (!transport) + return; + + tor_free(transport->name); + tor_free(transport); +} + +/** Mark every entry of the transport list to be removed on our next call to + * sweep_transport_list unless it has first been un-marked. */ +void +mark_transport_list(void) +{ + if (!transport_list) + transport_list = smartlist_new(); + SMARTLIST_FOREACH(transport_list, transport_t *, t, + t->marked_for_removal = 1); +} + +/** Remove every entry of the transport list that was marked with + * mark_transport_list if it has not subsequently been un-marked. */ +void +sweep_transport_list(void) +{ + if (!transport_list) + transport_list = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) { + if (t->marked_for_removal) { + SMARTLIST_DEL_CURRENT(transport_list, t); + transport_free(t); + } + } SMARTLIST_FOREACH_END(t); +} + +/** Initialize the pluggable transports list to empty, creating it if + * needed. */ +static void +clear_transport_list(void) +{ + if (!transport_list) + transport_list = smartlist_new(); + SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t)); + smartlist_clear(transport_list); +} + +/** Return a deep copy of <b>transport</b>. */ +static transport_t * +transport_copy(const transport_t *transport) +{ + transport_t *new_transport = NULL; + + tor_assert(transport); + + new_transport = tor_malloc_zero(sizeof(transport_t)); + + new_transport->socks_version = transport->socks_version; + new_transport->name = tor_strdup(transport->name); + tor_addr_copy(&new_transport->addr, &transport->addr); + new_transport->port = transport->port; + new_transport->marked_for_removal = transport->marked_for_removal; + + return new_transport; +} + +/** Returns the transport in our transport list that has the name <b>name</b>. + * Else returns NULL. */ +transport_t * +transport_get_by_name(const char *name) +{ + tor_assert(name); + + if (!transport_list) + return NULL; + + SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) { + if (!strcmp(transport->name, name)) + return transport; + } SMARTLIST_FOREACH_END(transport); + + return NULL; +} + +/** Resolve any conflicts that the insertion of transport <b>t</b> + * might cause. + * Return 0 if <b>t</b> is OK and should be registered, 1 if there is + * a transport identical to <b>t</b> already registered and -1 if + * <b>t</b> cannot be added due to conflicts. */ +static int +transport_resolve_conflicts(const transport_t *t) +{ + /* This is how we resolve transport conflicts: + + If there is already a transport with the same name and addrport, + we either have duplicate torrc lines OR we are here post-HUP and + this transport was here pre-HUP as well. In any case, mark the + old transport so that it doesn't get removed and ignore the new + one. Our caller has to free the new transport so we return '1' to + signify this. + + If there is already a transport with the same name but different + addrport: + * if it's marked for removal, it means that it either has a lower + priority than 't' in torrc (otherwise the mark would have been + cleared by the paragraph above), or it doesn't exist at all in + the post-HUP torrc. We destroy the old transport and register 't'. + * if it's *not* marked for removal, it means that it was newly + added in the post-HUP torrc or that it's of higher priority, in + this case we ignore 't'. */ + transport_t *t_tmp = transport_get_by_name(t->name); + if (t_tmp) { /* same name */ + if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) { + /* same name *and* addrport */ + t_tmp->marked_for_removal = 0; + return 1; + } else { /* same name but different addrport */ + char *new_transport_addrport = + tor_strdup(fmt_addrport(&t->addr, t->port)); + if (t_tmp->marked_for_removal) { /* marked for removal */ + log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s' " + "but there was already a transport marked for deletion at " + "'%s'. We deleted the old transport and registered the " + "new one.", t->name, new_transport_addrport, + fmt_addrport(&t_tmp->addr, t_tmp->port)); + smartlist_remove(transport_list, t_tmp); + transport_free(t_tmp); + tor_free(new_transport_addrport); + } else { /* *not* marked for removal */ + log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s' " + "but the same transport already exists at '%s'. " + "Skipping.", t->name, new_transport_addrport, + fmt_addrport(&t_tmp->addr, t_tmp->port)); + tor_free(new_transport_addrport); + return -1; + } + tor_free(new_transport_addrport); + } + } + + return 0; +} + +/** Add transport <b>t</b> to the internal list of pluggable + * transports. + * Returns 0 if the transport was added correctly, 1 if the same + * transport was already registered (in this case the caller must + * free the transport) and -1 if there was an error. */ +static int +transport_add(transport_t *t) +{ + int r; + tor_assert(t); + + r = transport_resolve_conflicts(t); + + switch (r) { + case 0: /* should register transport */ + if (!transport_list) + transport_list = smartlist_new(); + smartlist_add(transport_list, t); + return 0; + default: /* let our caller know the return code */ + return r; + } +} + +/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>. + * <b>name</b> is set to the name of the protocol this proxy uses. + * <b>socks_ver</b> is set to the SOCKS version of the proxy. */ +int +transport_add_from_config(const tor_addr_t *addr, uint16_t port, + const char *name, int socks_ver) +{ + transport_t *t = transport_new(addr, port, name, socks_ver); + + int r = transport_add(t); + + switch (r) { + case -1: + default: + log_notice(LD_GENERAL, "Could not add transport %s at %s. Skipping.", + t->name, fmt_addrport(&t->addr, t->port)); + transport_free(t); + return -1; + case 1: + log_info(LD_GENERAL, "Successfully registered transport %s at %s.", + t->name, fmt_addrport(&t->addr, t->port)); + transport_free(t); /* falling */ + return 0; + case 0: + log_info(LD_GENERAL, "Successfully registered transport %s at %s.", + t->name, fmt_addrport(&t->addr, t->port)); + return 0; + } +} + /** List of unconfigured managed proxies. */ static smartlist_t *managed_proxy_list = NULL; /** Number of still unconfigured proxies. */ @@ -205,7 +424,7 @@ static void add_transport_to_proxy(const char *transport, managed_proxy_t *mp) { tor_assert(mp->transports_to_launch); - if (!smartlist_string_isin(mp->transports_to_launch, transport)) + if (!smartlist_contains_string(mp->transports_to_launch, transport)) smartlist_add(mp->transports_to_launch, tor_strdup(transport)); } @@ -217,11 +436,11 @@ proxy_needs_restart(const managed_proxy_t *mp) { /* mp->transport_to_launch is populated with the names of the transports that must be launched *after* the SIGHUP. - mp->transports is populated with the names of the transports that - were launched *before* the SIGHUP. + mp->transports is populated with the transports that were + launched *before* the SIGHUP. - If the two lists contain the same strings, we don't need to - restart the proxy, since it already does what we want. */ + Check if all the transports that need to be launched are already + launched: */ tor_assert(smartlist_len(mp->transports_to_launch) > 0); tor_assert(mp->conf_state == PT_PROTO_COMPLETED); @@ -229,11 +448,11 @@ proxy_needs_restart(const managed_proxy_t *mp) if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports)) goto needs_restart; - SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) { - if (!smartlist_string_isin(mp->transports, t_t_l)) + SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) { + if (!smartlist_contains_string(mp->transports_to_launch, t->name)) goto needs_restart; - } SMARTLIST_FOREACH_END(t_t_l); + } SMARTLIST_FOREACH_END(t); return 0; @@ -245,6 +464,7 @@ proxy_needs_restart(const managed_proxy_t *mp) * preparations and then flag its state so that it will be relaunched * in the next tick. */ static void + proxy_prepare_for_restart(managed_proxy_t *mp) { transport_t *t_tmp = NULL; @@ -255,16 +475,17 @@ proxy_prepare_for_restart(managed_proxy_t *mp) tor_process_handle_destroy(mp->process_handle, 1); mp->process_handle = NULL; - /* destroy all its old transports. we no longer use them. */ - SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) { - t_tmp = transport_get_by_name(t_name); + /* destroy all its registered transports, since we will no longer + use them. */ + SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) { + t_tmp = transport_get_by_name(t->name); if (t_tmp) t_tmp->marked_for_removal = 1; - } SMARTLIST_FOREACH_END(t_name); + } SMARTLIST_FOREACH_END(t); sweep_transport_list(); - /* free the transport names in mp->transports */ - SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name)); + /* free the transport in mp->transports */ + SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); smartlist_clear(mp->transports); /* flag it as an infant proxy so that it gets launched on next tick */ @@ -315,6 +536,7 @@ launch_managed_proxy(managed_proxy_t *mp) void pt_configure_remaining_proxies(void) { + int at_least_a_proxy_config_finished = 0; smartlist_t *tmp = smartlist_new(); log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!", @@ -350,24 +572,29 @@ pt_configure_remaining_proxies(void) /* If the proxy is not fully configured, try to configure it futher. */ if (!proxy_configuration_finished(mp)) - configure_proxy(mp); + if (configure_proxy(mp) == 1) + at_least_a_proxy_config_finished = 1; } SMARTLIST_FOREACH_END(mp); smartlist_free(tmp); check_if_restarts_needed = 0; assert_unconfigured_count_ok(); -} -#ifdef _WIN32 + if (at_least_a_proxy_config_finished) + mark_my_descriptor_dirty("configured managed proxies"); +} -/** Attempt to continue configuring managed proxy <b>mp</b>. */ -static void +/** Attempt to continue configuring managed proxy <b>mp</b>. + * Return 1 if the transport configuration finished, and return 0 + * otherwise (if we still have more configuring to do for this + * proxy). */ +static int configure_proxy(managed_proxy_t *mp) { - int pos; - char stdout_buf[200]; - smartlist_t *lines = NULL; + int configuration_finished = 0; + smartlist_t *proxy_output = NULL; + enum stream_status stream_status = 0; /* if we haven't launched the proxy yet, do it now */ if (mp->conf_state == PT_PROTO_INFANT) { @@ -375,34 +602,31 @@ configure_proxy(managed_proxy_t *mp) mp->conf_state = PT_PROTO_FAILED_LAUNCH; handle_finished_proxy(mp); } - return; + return 0; } tor_assert(mp->conf_state != PT_PROTO_INFANT); tor_assert(mp->process_handle); - pos = tor_read_all_handle(tor_process_get_stdout_pipe(mp->process_handle), - stdout_buf, sizeof(stdout_buf) - 1, NULL); - if (pos < 0) { - log_notice(LD_GENERAL, "Failed to read data from managed proxy '%s'.", - mp->argv[0]); - mp->conf_state = PT_PROTO_BROKEN; + proxy_output = + tor_get_lines_from_handle(tor_process_get_stdout_pipe(mp->process_handle), + &stream_status); + if (!proxy_output) { /* failed to get input from proxy */ + if (stream_status != IO_STREAM_EAGAIN) { /* bad stream status! */ + mp->conf_state = PT_PROTO_BROKEN; + log_warn(LD_GENERAL, "The communication stream of managed proxy '%s' " + "is '%s'. Most probably the managed proxy stopped running. " + "This might be a bug of the managed proxy, a bug of Tor, or " + "a misconfiguration. Please enable logging on your managed " + "proxy and check the logs for errors.", + mp->argv[0], stream_status_to_string(stream_status)); + } + goto done; } - if (pos == 0) /* proxy has nothing interesting to say. */ - return; - - /* End with a null even if there isn't a \r\n at the end */ - /* TODO: What if this is a partial line? */ - stdout_buf[pos] = '\0'; - - /* Split up the buffer */ - lines = smartlist_new(); - tor_split_lines(lines, stdout_buf, pos); - /* Handle lines. */ - SMARTLIST_FOREACH_BEGIN(lines, const char *, line) { + SMARTLIST_FOREACH_BEGIN(proxy_output, const char *, line) { handle_proxy_line(line, mp); if (proxy_configuration_finished(mp)) goto done; @@ -410,126 +634,63 @@ configure_proxy(managed_proxy_t *mp) done: /* if the proxy finished configuring, exit the loop. */ - if (proxy_configuration_finished(mp)) + if (proxy_configuration_finished(mp)) { handle_finished_proxy(mp); - - if (lines) - smartlist_free(lines); -} - -#else /* _WIN32 */ - -/** Attempt to continue configuring managed proxy <b>mp</b>. */ -static void -configure_proxy(managed_proxy_t *mp) -{ - enum stream_status r; - char stdout_buf[200]; - - /* if we haven't launched the proxy yet, do it now */ - if (mp->conf_state == PT_PROTO_INFANT) { - if (launch_managed_proxy(mp) < 0) { /* launch fail */ - mp->conf_state = PT_PROTO_FAILED_LAUNCH; - handle_finished_proxy(mp); - } - return; + configuration_finished = 1; } - tor_assert(mp->conf_state != PT_PROTO_INFANT); - tor_assert(mp->process_handle); - - while (1) { - r = get_string_from_pipe(tor_process_get_stdout_pipe(mp->process_handle), - stdout_buf, sizeof(stdout_buf) - 1); - - if (r == IO_STREAM_OKAY) { /* got a line; handle it! */ - handle_proxy_line((const char *)stdout_buf, mp); - } else if (r == IO_STREAM_EAGAIN) { /* check back later */ - return; - } else if (r == IO_STREAM_CLOSED || r == IO_STREAM_TERM) { /* snap! */ - log_warn(LD_GENERAL, "Our communication channel with the managed proxy " - "'%s' closed. Most probably application stopped running.", - mp->argv[0]); - mp->conf_state = PT_PROTO_BROKEN; - } else { /* unknown stream status */ - log_warn(LD_BUG, "Unknown stream status '%d' while configuring managed " - "proxy '%s'.", (int)r, mp->argv[0]); - } - - /* if the proxy finished configuring, exit the loop. */ - if (proxy_configuration_finished(mp)) { - handle_finished_proxy(mp); - return; - } + if (proxy_output) { + SMARTLIST_FOREACH(proxy_output, char *, cp, tor_free(cp)); + smartlist_free(proxy_output); } -} -#endif /* _WIN32 */ + return configuration_finished; +} /** Register server managed proxy <b>mp</b> transports to state */ static void -register_server_proxy(managed_proxy_t *mp) +register_server_proxy(const managed_proxy_t *mp) { - /* After we register this proxy's transports, we switch its - mp->transports to a list containing strings of its transport - names. (See transports.h) */ - smartlist_t *sm_tmp = smartlist_new(); - tor_assert(mp->conf_state != PT_PROTO_COMPLETED); + SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) { save_transport_to_state(t->name, &t->addr, t->port); - log_notice(LD_GENERAL, "Registered server transport '%s' at '%s:%d'", - t->name, fmt_addr(&t->addr), (int)t->port); - smartlist_add(sm_tmp, tor_strdup(t->name)); + log_notice(LD_GENERAL, "Registered server transport '%s' at '%s'", + t->name, fmt_addrport(&t->addr, t->port)); } SMARTLIST_FOREACH_END(t); - - /* Since server proxies don't register their transports in the - circuitbuild.c subsystem, it's our duty to free them when we - switch mp->transports to strings. */ - SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); - smartlist_free(mp->transports); - - mp->transports = sm_tmp; } /** Register all the transports supported by client managed proxy * <b>mp</b> to the bridge subsystem. */ static void -register_client_proxy(managed_proxy_t *mp) +register_client_proxy(const managed_proxy_t *mp) { int r; - /* After we register this proxy's transports, we switch its - mp->transports to a list containing strings of its transport - names. (See transports.h) */ - smartlist_t *sm_tmp = smartlist_new(); tor_assert(mp->conf_state != PT_PROTO_COMPLETED); + SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) { - r = transport_add(t); + transport_t *transport_tmp = transport_copy(t); + r = transport_add(transport_tmp); switch (r) { case -1: log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name); - transport_free(t); + transport_free(transport_tmp); break; case 0: - log_info(LD_GENERAL, "Succesfully registered transport %s", t->name); - smartlist_add(sm_tmp, tor_strdup(t->name)); + log_info(LD_GENERAL, "Successfully registered transport %s", t->name); break; case 1: - log_info(LD_GENERAL, "Succesfully registered transport %s", t->name); - smartlist_add(sm_tmp, tor_strdup(t->name)); - transport_free(t); + log_info(LD_GENERAL, "Successfully registered transport %s", t->name); + transport_free(transport_tmp); break; } } SMARTLIST_FOREACH_END(t); - - smartlist_free(mp->transports); - mp->transports = sm_tmp; } /** Register the transports of managed proxy <b>mp</b>. */ static INLINE void -register_proxy(managed_proxy_t *mp) +register_proxy(const managed_proxy_t *mp) { if (mp->is_server) register_server_proxy(mp); @@ -542,10 +703,7 @@ static void managed_proxy_destroy(managed_proxy_t *mp, int also_terminate_process) { - if (mp->conf_state != PT_PROTO_COMPLETED) - SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); - else - SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name)); + SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); /* free the transports smartlist */ smartlist_free(mp->transports); @@ -815,7 +973,7 @@ parse_smethod_line(const char *line, managed_proxy_t *mp) } addrport = smartlist_get(items, 2); - if (tor_addr_port_split(LOG_PROTOCOL_WARN, addrport, &address, &port)<0) { + if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) { log_warn(LD_CONFIG, "Error parsing transport " "address '%s'", addrport); goto err; @@ -907,7 +1065,7 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp) } addrport = smartlist_get(items, 3); - if (tor_addr_port_split(LOG_PROTOCOL_WARN, addrport, &address, &port)<0) { + if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) { log_warn(LD_CONFIG, "Error parsing transport " "address '%s'", addrport); goto err; @@ -1039,7 +1197,7 @@ create_managed_proxy_environment(const managed_proxy_t *mp) SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) { set_environment_variable_in_smartlist(merged_env_vars, env_var, - _tor_free, 1); + tor_free_, 1); } SMARTLIST_FOREACH_END(env_var); env = process_environment_make(merged_env_vars); @@ -1143,7 +1301,7 @@ free_execve_args(char **arg) char **tmp = arg; while (*tmp) /* use the fact that the last element of the array is a NULL pointer to know when to stop freeing */ - _tor_free(*tmp++); + tor_free_(*tmp++); tor_free(arg); } @@ -1181,6 +1339,93 @@ pt_prepare_proxy_list_for_config_read(void) tor_assert(unconfigured_proxies_n == 0); } +/** Return a smartlist containing the ports where our pluggable + * transports are listening. */ +smartlist_t * +get_transport_proxy_ports(void) +{ + smartlist_t *sl = NULL; + + if (!managed_proxy_list) + return NULL; + + /** XXX assume that external proxy ports have been forwarded + manually */ + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) { + if (!mp->is_server || mp->conf_state != PT_PROTO_COMPLETED) + continue; + + if (!sl) sl = smartlist_new(); + + tor_assert(mp->transports); + SMARTLIST_FOREACH(mp->transports, const transport_t *, t, + smartlist_add_asprintf(sl, "%u:%u", t->port, t->port)); + + } SMARTLIST_FOREACH_END(mp); + + return sl; +} + +/** Return the pluggable transport string that we should display in + * our extra-info descriptor. If we shouldn't display such a string, + * or we have nothing to display, return NULL. The string is + * allocated on the heap and it's the responsibility of the caller to + * free it. */ +char * +pt_get_extra_info_descriptor_string(void) +{ + char *the_string = NULL; + smartlist_t *string_chunks = NULL; + + if (!managed_proxy_list) + return NULL; + + string_chunks = smartlist_new(); + + /* For each managed proxy, add its transports to the chunks list. */ + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) { + if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED)) + continue; + + tor_assert(mp->transports); + + SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) { + /* If the transport proxy returned "0.0.0.0" as its address, and + * we know our external IP address, use it. Otherwise, use the + * returned address. */ + const char *addrport = NULL; + uint32_t external_ip_address = 0; + if (tor_addr_is_null(&t->addr) && + router_pick_published_address(get_options(), + &external_ip_address) >= 0) { + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, external_ip_address); + addrport = fmt_addrport(&addr, t->port); + } else { + addrport = fmt_addrport(&t->addr, t->port); + } + + smartlist_add_asprintf(string_chunks, + "transport %s %s", + t->name, addrport); + } SMARTLIST_FOREACH_END(t); + + } SMARTLIST_FOREACH_END(mp); + + if (smartlist_len(string_chunks) == 0) { + smartlist_free(string_chunks); + return NULL; + } + + /* Join all the chunks into the final string. */ + the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL); + + SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s)); + smartlist_free(string_chunks); + + return the_string; +} + /** The tor config was read. * Destroy all managed proxies that were marked by a previous call to * prepare_proxy_list_for_config_read() and are not used by the new @@ -1204,6 +1449,12 @@ sweep_proxy_list(void) void pt_free_all(void) { + if (transport_list) { + clear_transport_list(); + smartlist_free(transport_list); + transport_list = NULL; + } + if (managed_proxy_list) { /* If the proxy is in PT_PROTO_COMPLETED, it has registered its transports and it's the duty of the circuitbuild.c subsystem to diff --git a/src/or/transports.h b/src/or/transports.h index 02f159a5d6..6ee82f4556 100644 --- a/src/or/transports.h +++ b/src/or/transports.h @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,6 +11,30 @@ #ifndef TOR_TRANSPORTS_H #define TOR_TRANSPORTS_H +/** Represents a pluggable transport used by a bridge. */ +typedef struct transport_t { + /** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */ + int socks_version; + /** Name of pluggable transport protocol */ + char *name; + /** The IP address where the transport bound and is waiting for + * connections. */ + tor_addr_t addr; + /** Port of proxy */ + uint16_t port; + /** Boolean: We are re-parsing our transport list, and we are going to remove + * this one if we don't find it in the list of configured transports. */ + unsigned marked_for_removal : 1; +} transport_t; + +void mark_transport_list(void); +void sweep_transport_list(void); +int transport_add_from_config(const tor_addr_t *addr, uint16_t port, + const char *name, int socks_ver); +void transport_free(transport_t *transport); + +transport_t *transport_get_by_name(const char *name); + void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv, int is_server); @@ -23,11 +47,15 @@ void pt_configure_remaining_proxies(void); int pt_proxies_configuration_pending(void); +char *pt_get_extra_info_descriptor_string(void); + void pt_free_all(void); void pt_prepare_proxy_list_for_config_read(void); void sweep_proxy_list(void); +smartlist_t *get_transport_proxy_ports(void); + #ifdef PT_PRIVATE /** State of the managed proxy configuration protocol. */ enum pt_proto_state { @@ -68,28 +96,7 @@ typedef struct { smartlist_t *transports_to_launch; /* The 'transports' list contains all the transports this proxy has - launched. - - Before a managed_proxy_t reaches the PT_PROTO_COMPLETED phase, - this smartlist contains a 'transport_t' for every transport it - has launched. - - When the managed_proxy_t reaches the PT_PROTO_COMPLETED phase, it - registers all its transports to the circuitbuild.c subsystem. At - that point the 'transport_t's are owned by the circuitbuild.c - subsystem. - - To avoid carrying dangling 'transport_t's in this smartlist, - right before the managed_proxy_t reaches the PT_PROTO_COMPLETED - phase we replace all 'transport_t's with strings of their - transport names. - - So, tl;dr: - When (conf_state != PT_PROTO_COMPLETED) this list carries - (transport_t *). - When (conf_state == PT_PROTO_COMPLETED) this list carries - (char *). - */ + launched. */ smartlist_t *transports; } managed_proxy_t; diff --git a/src/test/Makefile.am b/src/test/Makefile.am deleted file mode 100644 index 31a464ee7a..0000000000 --- a/src/test/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -TESTS = test - -noinst_PROGRAMS = test test-child bench - -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.c \ - test_addr.c \ - test_containers.c \ - test_crypto.c \ - test_data.c \ - test_dir.c \ - test_microdesc.c \ - test_pt.c \ - test_util.c \ - test_config.c \ - tinytest.c - -bench_SOURCES = \ - bench.c - -test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ - @TOR_LDFLAGS_libevent@ -test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ - ../common/libor-event.a \ - @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ - -bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ - @TOR_LDFLAGS_libevent@ -bench_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ - ../common/libor-event.a \ - @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @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/Makefile.nmake b/src/test/Makefile.nmake index aec477cf99..562c8df8b5 100644 --- a/src/test/Makefile.nmake +++ b/src/test/Makefile.nmake @@ -1,20 +1,32 @@ -all: test.exe +all: test.exe test-child.exe bench.exe -CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common /I ..\or +CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common /I ..\or \ + /I ..\ext LIBS = ..\..\..\build-alpha\lib\libevent.lib \ ..\..\..\build-alpha\lib\libcrypto.lib \ ..\..\..\build-alpha\lib\libssl.lib \ ..\..\..\build-alpha\lib\libz.lib \ ..\or\libtor.lib \ - ws2_32.lib advapi32.lib shell32.lib + ws2_32.lib advapi32.lib shell32.lib \ + crypt32.lib gdi32.lib user32.lib TEST_OBJECTS = test.obj test_addr.obj test_containers.obj \ test_crypto.obj test_data.obj test_dir.obj test_microdesc.obj \ - test_pt.obj test_util.obj test_config.obj tinytest.obj + test_pt.obj test_util.obj test_config.obj test_cell_formats.obj \ + test_replay.obj test_introduce.obj tinytest.obj + +tinytest.obj: ..\ext\tinytest.c + $(CC) $(CFLAGS) /D snprintf=_snprintf /c ..\ext\tinytest.c test.exe: $(TEST_OBJECTS) - $(CC) $(CFLAGS) $(LIBS) ..\common\*.lib $(TEST_OBJECTS) + $(CC) $(CFLAGS) $(LIBS) ..\common\*.lib $(TEST_OBJECTS) /Fe$@ + +bench.exe: bench.obj + $(CC) $(CFLAGS) bench.obj $(LIBS) ..\common\*.lib /Fe$@ + +test-child.exe: test-child.obj + $(CC) $(CFLAGS) test-child.obj /Fe$@ clean: - del $(TEST_OBJECTS) *.lib test.exe + del *.obj *.lib test.exe bench.exe test-child.exe diff --git a/src/test/bench.c b/src/test/bench.c index 3eae532d30..706b8bc7fb 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Ordinarily defined in tor_main.c; this bit is just here to provide one @@ -15,9 +15,24 @@ const char tor_git_revision[] = ""; #include "orconfig.h" #define RELAY_PRIVATE +#define CONFIG_PRIVATE #include "or.h" +#include "onion_tap.h" #include "relay.h" +#include <openssl/opensslv.h> +#include <openssl/evp.h> +#ifndef OPENSSL_NO_EC +#include <openssl/ec.h> +#include <openssl/ecdh.h> +#include <openssl/obj_mac.h> +#endif + +#include "config.h" +#ifdef CURVE25519_ENABLED +#include "crypto_curve25519.h" +#include "onion_ntor.h" +#endif #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) static uint64_t nanostart; @@ -97,6 +112,131 @@ bench_aes(void) } static void +bench_onion_TAP(void) +{ + const int iters = 1<<9; + int i; + crypto_pk_t *key, *key2; + uint64_t start, end; + char os[TAP_ONIONSKIN_CHALLENGE_LEN]; + char or[TAP_ONIONSKIN_REPLY_LEN]; + crypto_dh_t *dh_out; + + key = crypto_pk_new(); + key2 = crypto_pk_new(); + if (crypto_pk_generate_key_with_bits(key, 1024) < 0) + goto done; + if (crypto_pk_generate_key_with_bits(key2, 1024) < 0) + goto done; + + reset_perftime(); + start = perftime(); + for (i = 0; i < iters; ++i) { + onion_skin_TAP_create(key, &dh_out, os); + crypto_dh_free(dh_out); + } + end = perftime(); + printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3); + + onion_skin_TAP_create(key, &dh_out, os); + start = perftime(); + for (i = 0; i < iters; ++i) { + char key_out[CPATH_KEY_MATERIAL_LEN]; + onion_skin_TAP_server_handshake(os, key, NULL, or, + key_out, sizeof(key_out)); + } + end = perftime(); + printf("Server-side, key guessed right: %f usec\n", + NANOCOUNT(start, end, iters)/1e3); + + start = perftime(); + for (i = 0; i < iters; ++i) { + char key_out[CPATH_KEY_MATERIAL_LEN]; + onion_skin_TAP_server_handshake(os, key2, key, or, + key_out, sizeof(key_out)); + } + end = perftime(); + printf("Server-side, key guessed wrong: %f usec.\n", + NANOCOUNT(start, end, iters)/1e3); + + start = perftime(); + for (i = 0; i < iters; ++i) { + crypto_dh_t *dh; + char key_out[CPATH_KEY_MATERIAL_LEN]; + int s; + dh = crypto_dh_dup(dh_out); + s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out)); + crypto_dh_free(dh); + tor_assert(s == 0); + } + end = perftime(); + printf("Client-side, part 2: %f usec.\n", + NANOCOUNT(start, end, iters)/1e3); + + done: + crypto_pk_free(key); + crypto_pk_free(key2); +} + +#ifdef CURVE25519_ENABLED +static void +bench_onion_ntor(void) +{ + const int iters = 1<<10; + int i; + curve25519_keypair_t keypair1, keypair2; + uint64_t start, end; + uint8_t os[NTOR_ONIONSKIN_LEN]; + uint8_t or[NTOR_REPLY_LEN]; + ntor_handshake_state_t *state = NULL; + uint8_t nodeid[DIGEST_LEN]; + di_digest256_map_t *keymap = NULL; + + curve25519_secret_key_generate(&keypair1.seckey, 0); + curve25519_public_key_generate(&keypair1.pubkey, &keypair1.seckey); + curve25519_secret_key_generate(&keypair2.seckey, 0); + curve25519_public_key_generate(&keypair2.pubkey, &keypair2.seckey); + dimap_add_entry(&keymap, keypair1.pubkey.public_key, &keypair1); + dimap_add_entry(&keymap, keypair2.pubkey.public_key, &keypair2); + + reset_perftime(); + start = perftime(); + for (i = 0; i < iters; ++i) { + onion_skin_ntor_create(nodeid, &keypair1.pubkey, &state, os); + ntor_handshake_state_free(state); + } + end = perftime(); + printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3); + + state = NULL; + onion_skin_ntor_create(nodeid, &keypair1.pubkey, &state, os); + start = perftime(); + for (i = 0; i < iters; ++i) { + uint8_t key_out[CPATH_KEY_MATERIAL_LEN]; + onion_skin_ntor_server_handshake(os, keymap, NULL, nodeid, or, + key_out, sizeof(key_out)); + } + end = perftime(); + printf("Server-side: %f usec\n", + NANOCOUNT(start, end, iters)/1e3); + + start = perftime(); + for (i = 0; i < iters; ++i) { + uint8_t key_out[CPATH_KEY_MATERIAL_LEN]; + int s; + s = onion_skin_ntor_client_handshake(state, or, key_out, sizeof(key_out)); + tor_assert(s == 0); + } + end = perftime(); + printf("Client-side, part 2: %f usec.\n", + NANOCOUNT(start, end, iters)/1e3); + + ntor_handshake_state_free(state); + dimap_free(keymap, NULL); +} +#endif + +static void bench_cell_aes(void) { uint64_t start, end; @@ -175,18 +315,18 @@ bench_dmap(void) NANOCOUNT(pt3, pt4, iters*elts)); for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); - SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); + SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_contains(ds, cp)); + SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_contains(ds, cp)); } end = perftime(); - printf("digestset_isin: %.2f ns per element.\n", + printf("digestset_contains: %.2f ns per element.\n", NANOCOUNT(pt4, end, iters*elts*2)); /* We need to use this, or else the whole loop gets optimized out. */ printf("Hits == %d\n", n); for (i = 0; i < fpostests; ++i) { crypto_rand(d, 20); - if (digestset_isin(ds, d)) ++fp; + if (digestset_contains(ds, d)) ++fp; } printf("False positive rate on digestset: %.2f%%\n", (fp/(double)fpostests)*100); @@ -214,8 +354,8 @@ bench_cell_ops(void) crypto_rand((char*)cell->payload, sizeof(cell->payload)); /* Mock-up or_circuit_t */ - or_circ->_base.magic = OR_CIRCUIT_MAGIC; - or_circ->_base.purpose = CIRCUIT_PURPOSE_OR; + or_circ->base_.magic = OR_CIRCUIT_MAGIC; + or_circ->base_.purpose = CIRCUIT_PURPOSE_OR; /* Initialize crypto */ or_circ->p_crypto = crypto_cipher_new(NULL); @@ -248,6 +388,95 @@ bench_cell_ops(void) tor_free(cell); } +static void +bench_dh(void) +{ + const int iters = 1<<10; + int i; + uint64_t start, end; + + reset_perftime(); + start = perftime(); + for (i = 0; i < iters; ++i) { + char dh_pubkey_a[DH_BYTES], dh_pubkey_b[DH_BYTES]; + char secret_a[DH_BYTES], secret_b[DH_BYTES]; + ssize_t slen_a, slen_b; + crypto_dh_t *dh_a = crypto_dh_new(DH_TYPE_TLS); + crypto_dh_t *dh_b = crypto_dh_new(DH_TYPE_TLS); + crypto_dh_generate_public(dh_a); + crypto_dh_generate_public(dh_b); + crypto_dh_get_public(dh_a, dh_pubkey_a, sizeof(dh_pubkey_a)); + crypto_dh_get_public(dh_b, dh_pubkey_b, sizeof(dh_pubkey_b)); + slen_a = crypto_dh_compute_secret(LOG_NOTICE, + dh_a, dh_pubkey_b, sizeof(dh_pubkey_b), + secret_a, sizeof(secret_a)); + slen_b = crypto_dh_compute_secret(LOG_NOTICE, + dh_b, dh_pubkey_a, sizeof(dh_pubkey_a), + secret_b, sizeof(secret_b)); + tor_assert(slen_a == slen_b); + tor_assert(!memcmp(secret_a, secret_b, slen_a)); + crypto_dh_free(dh_a); + crypto_dh_free(dh_b); + } + end = perftime(); + printf("Complete DH handshakes (1024 bit, public and private ops):\n" + " %f millisec each.\n", NANOCOUNT(start, end, iters)/1e6); +} + +#if (!defined(OPENSSL_NO_EC) \ + && OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0)) +#define HAVE_EC_BENCHMARKS +static void +bench_ecdh_impl(int nid, const char *name) +{ + const int iters = 1<<10; + int i; + uint64_t start, end; + + reset_perftime(); + start = perftime(); + for (i = 0; i < iters; ++i) { + char secret_a[DH_BYTES], secret_b[DH_BYTES]; + ssize_t slen_a, slen_b; + EC_KEY *dh_a = EC_KEY_new_by_curve_name(nid); + EC_KEY *dh_b = EC_KEY_new_by_curve_name(nid); + if (!dh_a || !dh_b) { + puts("Skipping. (No implementation?)"); + return; + } + + EC_KEY_generate_key(dh_a); + EC_KEY_generate_key(dh_b); + slen_a = ECDH_compute_key(secret_a, DH_BYTES, + EC_KEY_get0_public_key(dh_b), dh_a, + NULL); + slen_b = ECDH_compute_key(secret_b, DH_BYTES, + EC_KEY_get0_public_key(dh_a), dh_b, + NULL); + + tor_assert(slen_a == slen_b); + tor_assert(!memcmp(secret_a, secret_b, slen_a)); + EC_KEY_free(dh_a); + EC_KEY_free(dh_b); + } + end = perftime(); + printf("Complete ECDH %s handshakes (2 public and 2 private ops):\n" + " %f millisec each.\n", name, NANOCOUNT(start, end, iters)/1e6); +} + +static void +bench_ecdh_p256(void) +{ + bench_ecdh_impl(NID_X9_62_prime256v1, "P-256"); +} + +static void +bench_ecdh_p224(void) +{ + bench_ecdh_impl(NID_secp224r1, "P-224"); +} +#endif + typedef void (*bench_fn)(void); typedef struct benchmark_t { @@ -261,8 +490,17 @@ typedef struct benchmark_t { static struct benchmark_t benchmarks[] = { ENT(dmap), ENT(aes), + ENT(onion_TAP), +#ifdef CURVE25519_ENABLED + ENT(onion_ntor), +#endif ENT(cell_aes), ENT(cell_ops), + ENT(dh), +#ifdef HAVE_EC_BENCHMARKS + ENT(ecdh_p256), + ENT(ecdh_p224), +#endif {NULL,NULL,0} }; @@ -286,6 +524,8 @@ main(int argc, const char **argv) int i; int list=0, n_enabled=0; benchmark_t *b; + char *errmsg; + or_options_t *options; tor_threads_init(); @@ -306,6 +546,16 @@ main(int argc, const char **argv) reset_perftime(); crypto_seed_rng(1); + options = options_new(); + init_logging(); + options->command = CMD_RUN_UNITTESTS; + options->DataDirectory = tor_strdup(""); + options_init(options); + if (set_options(options, &errmsg) < 0) { + printf("Failed to set initial options: %s\n", errmsg); + tor_free(errmsg); + return 1; + } for (b = benchmarks; b->name; ++b) { if (b->enabled || n_enabled == 0) { diff --git a/src/test/include.am b/src/test/include.am new file mode 100644 index 0000000000..112d1a79d8 --- /dev/null +++ b/src/test/include.am @@ -0,0 +1,68 @@ +TESTS+= src/test/test + +noinst_PROGRAMS+= src/test/test src/test/test-child src/test/bench + +src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ + -DLOCALSTATEDIR="\"$(localstatedir)\"" \ + -DBINDIR="\"$(bindir)\"" \ + -I"$(top_srcdir)/src/or" -I"$(top_srcdir)/src/ext" + +# -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. + +src_test_test_SOURCES = \ + src/test/test.c \ + src/test/test_addr.c \ + src/test/test_cell_formats.c \ + src/test/test_containers.c \ + src/test/test_crypto.c \ + src/test/test_data.c \ + src/test/test_dir.c \ + src/test/test_introduce.c \ + src/test/test_microdesc.c \ + src/test/test_pt.c \ + src/test/test_replay.c \ + src/test/test_util.c \ + src/test/test_config.c \ + src/ext/tinytest.c + +src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) + +src_test_bench_SOURCES = \ + src/test/bench.c + +src_test_bench_CPPFLAGS= $(src_test_AM_CPPFLAGS) + +src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ + @TOR_LDFLAGS_libevent@ +src_test_test_LDADD = src/or/libtor.a src/common/libor.a \ + src/common/libor-crypto.a $(LIBDONNA) \ + src/common/libor-event.a \ + @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + +src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ + @TOR_LDFLAGS_libevent@ +src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ + src/common/libor-crypto.a $(LIBDONNA) \ + src/common/libor-event.a \ + @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + +noinst_HEADERS+= \ + src/test/test.h + +if CURVE25519_ENABLED +noinst_PROGRAMS+= src/test/test-ntor-cl +src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c +src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ +src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \ + src/common/libor-crypto.a $(LIBDONNA) \ + @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ +src_test_test_ntor_cl_AM_CPPFLAGS = \ + -I"$(top_srcdir)/src/or" + +endif + diff --git a/src/test/ntor_ref.py b/src/test/ntor_ref.py new file mode 100644 index 0000000000..ade468da7d --- /dev/null +++ b/src/test/ntor_ref.py @@ -0,0 +1,387 @@ +# Copyright 2012-2013, The Tor Project, Inc +# See LICENSE for licensing information + +""" +ntor_ref.py + + +This module is a reference implementation for the "ntor" protocol +s proposed by Goldberg, Stebila, and Ustaoglu and as instantiated in +Tor Proposal 216. + +It's meant to be used to validate Tor's ntor implementation. It +requirs the curve25519 python module from the curve25519-donna +package. + + *** DO NOT USE THIS IN PRODUCTION. *** + +commands: + + gen_kdf_vectors: Print out some test vectors for the RFC5869 KDF. + timing: Print a little timing information about this implementation's + handshake. + self-test: Try handshaking with ourself; make sure we can. + test-tor: Handshake with tor's ntor implementation via the program + src/test/test-ntor-cl; make sure we can. + +""" + +import binascii +import curve25519 +import hashlib +import hmac +import subprocess + +# ********************************************************************** +# Helpers and constants + +def HMAC(key,msg): + "Return the HMAC-SHA256 of 'msg' using the key 'key'." + H = hmac.new(key, "", hashlib.sha256) + H.update(msg) + return H.digest() + +def H(msg,tweak): + """Return the hash of 'msg' using tweak 'tweak'. (In this version of ntor, + the tweaked hash is just HMAC with the tweak as the key.)""" + return HMAC(key=tweak, + msg=msg) + +def keyid(k): + """Return the 32-byte key ID of a public key 'k'. (Since we're + using curve25519, we let k be its own keyid.) + """ + return k.serialize() + +NODE_ID_LENGTH = 20 +KEYID_LENGTH = 32 +G_LENGTH = 32 +H_LENGTH = 32 + +PROTOID = b"ntor-curve25519-sha256-1" +M_EXPAND = PROTOID + ":key_expand" +T_MAC = PROTOID + ":mac" +T_KEY = PROTOID + ":key_extract" +T_VERIFY = PROTOID + ":verify" + +def H_mac(msg): return H(msg, tweak=T_MAC) +def H_verify(msg): return H(msg, tweak=T_VERIFY) + +class PrivateKey(curve25519.keys.Private): + """As curve25519.keys.Private, but doesn't regenerate its public key + every time you ask for it. + """ + def __init__(self): + curve25519.keys.Private.__init__(self) + self._memo_public = None + + def get_public(self): + if self._memo_public is None: + self._memo_public = curve25519.keys.Private.get_public(self) + + return self._memo_public + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +def kdf_rfc5869(key, salt, info, n): + + prk = HMAC(key=salt, msg=key) + + out = b"" + last = b"" + i = 1 + while len(out) < n: + m = last + info + chr(i) + last = h = HMAC(key=prk, msg=m) + out += h + i = i + 1 + return out[:n] + +def kdf_ntor(key, n): + return kdf_rfc5869(key, T_KEY, M_EXPAND, n) + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +def client_part1(node_id, pubkey_B): + """Initial handshake, client side. + + From the specification: + + <<To send a create cell, the client generates a keypair x,X = + KEYGEN(), and sends a CREATE cell with contents: + + NODEID: ID -- ID_LENGTH bytes + KEYID: KEYID(B) -- H_LENGTH bytes + CLIENT_PK: X -- G_LENGTH bytes + >> + + Takes node_id -- a digest of the server's identity key, + pubkey_B -- a public key for the server. + Returns a tuple of (client secret key x, client->server message)""" + + assert len(node_id) == NODE_ID_LENGTH + + key_id = keyid(pubkey_B) + seckey_x = PrivateKey() + pubkey_X = seckey_x.get_public().serialize() + + message = node_id + key_id + pubkey_X + + assert len(message) == NODE_ID_LENGTH + H_LENGTH + H_LENGTH + return seckey_x , message + +def hash_nil(x): + """Identity function: if we don't pass a hash function that does nothing, + the curve25519 python lib will try to sha256 it for us.""" + return x + +def bad_result(r): + """Helper: given a result of multiplying a public key by a private key, + return True iff one of the inputs was broken""" + assert len(r) == 32 + return r == '\x00'*32 + +def server(seckey_b, my_node_id, message, keyBytes=72): + """Handshake step 2, server side. + + From the spec: + + << + The server generates a keypair of y,Y = KEYGEN(), and computes + + secret_input = EXP(X,y) | EXP(X,b) | ID | B | X | Y | PROTOID + KEY_SEED = H(secret_input, t_key) + verify = H(secret_input, t_verify) + auth_input = verify | ID | B | Y | X | PROTOID | "Server" + + The server sends a CREATED cell containing: + + SERVER_PK: Y -- G_LENGTH bytes + AUTH: H(auth_input, t_mac) -- H_LENGTH byets + >> + + Takes seckey_b -- the server's secret key + my_node_id -- the servers's public key digest, + message -- a message from a client + keybytes -- amount of key material to generate + + Returns a tuple of (key material, sever->client reply), or None on + error. + """ + + assert len(message) == NODE_ID_LENGTH + H_LENGTH + H_LENGTH + + if my_node_id != message[:NODE_ID_LENGTH]: + return None + + badness = (keyid(seckey_b.get_public()) != + message[NODE_ID_LENGTH:NODE_ID_LENGTH+H_LENGTH]) + + pubkey_X = curve25519.keys.Public(message[NODE_ID_LENGTH+H_LENGTH:]) + seckey_y = PrivateKey() + pubkey_Y = seckey_y.get_public() + pubkey_B = seckey_b.get_public() + xy = seckey_y.get_shared_key(pubkey_X, hash_nil) + xb = seckey_b.get_shared_key(pubkey_X, hash_nil) + + # secret_input = EXP(X,y) | EXP(X,b) | ID | B | X | Y | PROTOID + secret_input = (xy + xb + my_node_id + + pubkey_B.serialize() + + pubkey_X.serialize() + + pubkey_Y.serialize() + + PROTOID) + + verify = H_verify(secret_input) + + # auth_input = verify | ID | B | Y | X | PROTOID | "Server" + auth_input = (verify + + my_node_id + + pubkey_B.serialize() + + pubkey_Y.serialize() + + pubkey_X.serialize() + + PROTOID + + "Server") + + msg = pubkey_Y.serialize() + H_mac(auth_input) + + badness += bad_result(xb) + badness += bad_result(xy) + + if badness: + return None + + keys = kdf_ntor(secret_input, keyBytes) + + return keys, msg + +def client_part2(seckey_x, msg, node_id, pubkey_B, keyBytes=72): + """Handshake step 3: client side again. + + From the spec: + + << + The client then checks Y is in G^* [see NOTE below], and computes + + secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID + KEY_SEED = H(secret_input, t_key) + verify = H(secret_input, t_verify) + auth_input = verify | ID | B | Y | X | PROTOID | "Server" + + The client verifies that AUTH == H(auth_input, t_mac). + >> + + Takes seckey_x -- the secret key we generated in step 1. + msg -- the message from the server. + node_id -- the node_id we used in step 1. + server_key -- the same public key we used in step 1. + keyBytes -- the number of bytes we want to generate + Returns key material, or None on error + + """ + assert len(msg) == G_LENGTH + H_LENGTH + + pubkey_Y = curve25519.keys.Public(msg[:G_LENGTH]) + their_auth = msg[G_LENGTH:] + + pubkey_X = seckey_x.get_public() + + yx = seckey_x.get_shared_key(pubkey_Y, hash_nil) + bx = seckey_x.get_shared_key(pubkey_B, hash_nil) + + + # secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID + secret_input = (yx + bx + node_id + + pubkey_B.serialize() + + pubkey_X.serialize() + + pubkey_Y.serialize() + PROTOID) + + verify = H_verify(secret_input) + + # auth_input = verify | ID | B | Y | X | PROTOID | "Server" + auth_input = (verify + node_id + + pubkey_B.serialize() + + pubkey_Y.serialize() + + pubkey_X.serialize() + PROTOID + + "Server") + + my_auth = H_mac(auth_input) + + badness = my_auth != their_auth + badness = bad_result(yx) + bad_result(bx) + + if badness: + return None + + return kdf_ntor(secret_input, keyBytes) + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +def demo(node_id="iToldYouAboutStairs.", server_key=PrivateKey()): + """ + Try to handshake with ourself. + """ + x, create = client_part1(node_id, server_key.get_public()) + skeys, created = server(server_key, node_id, create) + ckeys = client_part2(x, created, node_id, server_key.get_public()) + assert len(skeys) == 72 + assert len(ckeys) == 72 + assert skeys == ckeys + +# ====================================================================== +def timing(): + """ + Use Python's timeit module to see how fast this nonsense is + """ + import timeit + t = timeit.Timer(stmt="ntor_ref.demo(N,SK)", + setup="import ntor_ref,curve25519;N='ABCD'*5;SK=ntor_ref.PrivateKey()") + print t.timeit(number=1000) + +# ====================================================================== + +def kdf_vectors(): + """ + Generate some vectors to check our KDF. + """ + import binascii + def kdf_vec(inp): + k = kdf(inp, T_KEY, M_EXPAND, 100) + print repr(inp), "\n\""+ binascii.b2a_hex(k)+ "\"" + kdf_vec("") + kdf_vec("Tor") + kdf_vec("AN ALARMING ITEM TO FIND ON YOUR CREDIT-RATING STATEMENT") + +# ====================================================================== + + +def test_tor(): + """ + Call the test-ntor-cl command-line program to make sure we can + interoperate with Tor's ntor program + """ + enhex=binascii.b2a_hex + dehex=lambda s: binascii.a2b_hex(s.strip()) + + PROG = "./src/test/test-ntor-cl" + def tor_client1(node_id, pubkey_B): + " returns (msg, state) " + p = subprocess.Popen([PROG, "client1", enhex(node_id), + enhex(pubkey_B.serialize())], + stdout=subprocess.PIPE) + return map(dehex, p.stdout.readlines()) + def tor_server1(seckey_b, node_id, msg, n): + " returns (msg, keys) " + p = subprocess.Popen([PROG, "server1", enhex(seckey_b.serialize()), + enhex(node_id), enhex(msg), str(n)], + stdout=subprocess.PIPE) + return map(dehex, p.stdout.readlines()) + def tor_client2(state, msg, n): + " returns (keys,) " + p = subprocess.Popen([PROG, "client2", enhex(state), + enhex(msg), str(n)], + stdout=subprocess.PIPE) + return map(dehex, p.stdout.readlines()) + + + node_id = "thisisatornodeid$#%^" + seckey_b = PrivateKey() + pubkey_B = seckey_b.get_public() + + # Do a pure-Tor handshake + c2s_msg, c_state = tor_client1(node_id, pubkey_B) + s2c_msg, s_keys = tor_server1(seckey_b, node_id, c2s_msg, 90) + c_keys, = tor_client2(c_state, s2c_msg, 90) + assert c_keys == s_keys + assert len(c_keys) == 90 + + # Try a mixed handshake with Tor as the client + c2s_msg, c_state = tor_client1(node_id, pubkey_B) + s_keys, s2c_msg = server(seckey_b, node_id, c2s_msg, 90) + c_keys, = tor_client2(c_state, s2c_msg, 90) + assert c_keys == s_keys + assert len(c_keys) == 90 + + # Now do a mixed handshake with Tor as the server + c_x, c2s_msg = client_part1(node_id, pubkey_B) + s2c_msg, s_keys = tor_server1(seckey_b, node_id, c2s_msg, 90) + c_keys = client_part2(c_x, s2c_msg, node_id, pubkey_B, 90) + assert c_keys == s_keys + assert len(c_keys) == 90 + + print "We just interoperated." + +# ====================================================================== + +if __name__ == '__main__': + import sys + if sys.argv[1] == 'gen_kdf_vectors': + kdf_vectors() + elif sys.argv[1] == 'timing': + timing() + elif sys.argv[1] == 'self-test': + demo() + elif sys.argv[1] == 'test-tor': + test_tor() + + else: + print __doc__ diff --git a/src/test/test-child.c b/src/test/test-child.c index c5725f1c5a..ef10fbb922 100644 --- a/src/test/test-child.c +++ b/src/test/test-child.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Tor Project, Inc. */ +/* Copyright (c) 2011-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include <stdio.h> diff --git a/src/test/test.c b/src/test/test.c index ae423948ec..c2911d842c 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Ordinarily defined in tor_main.c; this bit is just here to provide one @@ -32,7 +32,7 @@ const char tor_git_revision[] = ""; #define CONFIG_PRIVATE #define GEOIP_PRIVATE #define ROUTER_PRIVATE -#define CIRCUIT_PRIVATE +#define CIRCUITSTATS_PRIVATE /* * Linux doesn't provide lround in math.h by default, but mac os does... @@ -44,7 +44,8 @@ double fabs(double x); #include "or.h" #include "buffers.h" -#include "circuitbuild.h" +#include "circuitlist.h" +#include "circuitstats.h" #include "config.h" #include "connection_edge.h" #include "geoip.h" @@ -54,9 +55,14 @@ double fabs(double x); #include "mempool.h" #include "memarea.h" #include "onion.h" +#include "onion_tap.h" +#include "onion_ntor.h" #include "policies.h" #include "rephist.h" #include "routerparse.h" +#ifdef CURVE25519_ENABLED +#include "crypto_curve25519.h" +#endif #ifdef USE_DMALLOC #include <dmalloc.h> @@ -84,8 +90,14 @@ setup_directory(void) { static int is_setup = 0; int r; + char rnd[256], rnd32[256]; if (is_setup) return; +/* Due to base32 limitation needs to be a multiple of 5. */ +#define RAND_PATH_BYTES 5 + crypto_rand(rnd, RAND_PATH_BYTES); + base32_encode(rnd32, sizeof(rnd32), rnd, RAND_PATH_BYTES); + #ifdef _WIN32 { char buf[MAX_PATH]; @@ -94,11 +106,12 @@ setup_directory(void) if (!GetTempPathA(sizeof(buf),buf)) tmp = "c:\\windows\\temp"; tor_snprintf(temp_dir, sizeof(temp_dir), - "%s\\tor_test_%d", tmp, (int)getpid()); + "%s\\tor_test_%d_%s", tmp, (int)getpid(), rnd32); r = mkdir(temp_dir); } #else - tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d", (int) getpid()); + tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d_%s", + (int) getpid(), rnd32); r = mkdir(temp_dir, 0700); #endif if (r) { @@ -352,7 +365,7 @@ test_socks_5_unsupported_commands(void *ptr) test_eq(5, socks->socks_version); test_eq(2, socks->replylen); test_eq(5, socks->reply[0]); - test_eq(0, socks->reply[1]); + test_eq(2, socks->reply[1]); ADD_DATA(buf, "\x05\x03\x00\x01\x02\x02\x02\x01\x01\x01"); test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, get_options()->SafeSocks), -1); @@ -457,7 +470,7 @@ test_socks_5_no_authenticate(void *ptr) get_options()->SafeSocks)); test_eq(5, socks->socks_version); test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); + test_eq(1, socks->reply[0]); test_eq(0, socks->reply[1]); test_eq(2, socks->usernamelen); @@ -496,7 +509,7 @@ test_socks_5_authenticate(void *ptr) get_options()->SafeSocks)); test_eq(5, socks->socks_version); test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); + test_eq(1, socks->reply[0]); test_eq(0, socks->reply[1]); test_eq(2, socks->usernamelen); @@ -536,7 +549,7 @@ test_socks_5_authenticate_with_data(void *ptr) get_options()->SafeSocks) == 1); test_eq(5, socks->socks_version); test_eq(2, socks->replylen); - test_eq(5, socks->reply[0]); + test_eq(1, socks->reply[0]); test_eq(0, socks->reply[1]); test_streq("2.2.2.2", socks->address); @@ -827,11 +840,11 @@ test_onion_handshake(void) { /* client-side */ crypto_dh_t *c_dh = NULL; - char c_buf[ONIONSKIN_CHALLENGE_LEN]; + char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; char c_keys[40]; /* server-side */ - char s_buf[ONIONSKIN_REPLY_LEN]; + char s_buf[TAP_ONIONSKIN_REPLY_LEN]; char s_keys[40]; /* shared */ @@ -840,18 +853,18 @@ test_onion_handshake(void) pk = pk_generate(0); /* client handshake 1. */ - memset(c_buf, 0, ONIONSKIN_CHALLENGE_LEN); - test_assert(! onion_skin_create(pk, &c_dh, c_buf)); + memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); + test_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); /* server handshake */ - memset(s_buf, 0, ONIONSKIN_REPLY_LEN); + memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN); memset(s_keys, 0, 40); - test_assert(! onion_skin_server_handshake(c_buf, pk, NULL, + test_assert(! onion_skin_TAP_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)); + test_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40)); if (memcmp(c_keys, s_keys, 40)) { puts("Aiiiie"); @@ -868,6 +881,103 @@ test_onion_handshake(void) crypto_pk_free(pk); } +#ifdef CURVE25519_ENABLED +static void +test_ntor_handshake(void *arg) +{ + /* client-side */ + ntor_handshake_state_t *c_state = NULL; + uint8_t c_buf[NTOR_ONIONSKIN_LEN]; + uint8_t c_keys[400]; + + /* server-side */ + di_digest256_map_t *s_keymap=NULL; + curve25519_keypair_t s_keypair; + uint8_t s_buf[NTOR_REPLY_LEN]; + uint8_t s_keys[400]; + + /* shared */ + const curve25519_public_key_t *server_pubkey; + uint8_t node_id[20] = "abcdefghijklmnopqrst"; + + (void) arg; + + /* Make the server some keys */ + curve25519_secret_key_generate(&s_keypair.seckey, 0); + curve25519_public_key_generate(&s_keypair.pubkey, &s_keypair.seckey); + dimap_add_entry(&s_keymap, s_keypair.pubkey.public_key, &s_keypair); + server_pubkey = &s_keypair.pubkey; + + /* client handshake 1. */ + memset(c_buf, 0, NTOR_ONIONSKIN_LEN); + tt_int_op(0, ==, onion_skin_ntor_create(node_id, server_pubkey, + &c_state, c_buf)); + + /* server handshake */ + memset(s_buf, 0, NTOR_REPLY_LEN); + memset(s_keys, 0, 40); + tt_int_op(0, ==, onion_skin_ntor_server_handshake(c_buf, s_keymap, NULL, + node_id, + s_buf, s_keys, 400)); + + /* client handshake 2 */ + memset(c_keys, 0, 40); + tt_int_op(0, ==, onion_skin_ntor_client_handshake(c_state, s_buf, + c_keys, 400)); + + test_memeq(c_keys, s_keys, 400); + memset(s_buf, 0, 40); + test_memneq(c_keys, s_buf, 40); + + done: + ntor_handshake_state_free(c_state); + dimap_free(s_keymap, NULL); +} +#endif + +/** Run unit tests for the onion queues. */ +static void +test_onion_queues(void) +{ + uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; + uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0}; + + or_circuit_t *circ1 = or_circuit_new(0, NULL); + or_circuit_t *circ2 = or_circuit_new(0, NULL); + + create_cell_t *onionskin = NULL; + create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); + create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); + + create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, + TAP_ONIONSKIN_CHALLENGE_LEN, buf1); + create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, + NTOR_ONIONSKIN_LEN, buf2); + + test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + test_eq(0, onion_pending_add(circ1, create1)); + test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + + test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + test_eq(0, onion_pending_add(circ2, create2)); + test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + + test_eq_ptr(circ2, onion_next_task(&onionskin)); + test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + + clear_pending_onions(); + test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + + done: + ; +// circuit_free(circ1); +// circuit_free(circ2); + /* and free create1 and create2 */ + /* XXX leaks everything here */ +} + static void test_circuit_timeout(void) { @@ -1056,9 +1166,9 @@ test_policy_summary_helper(const char *policy_str, line.value = (char *)policy_str; line.next = NULL; - r = policies_parse_exit_policy(&line, &policy, 0, NULL, 1); + r = policies_parse_exit_policy(&line, &policy, 1, 0, NULL, 1); test_eq(r, 0); - summary = policy_summarize(policy); + summary = policy_summarize(policy, AF_INET); test_assert(summary != NULL); test_streq(summary, expected_summary); @@ -1113,7 +1223,7 @@ test_policies(void) test_assert(ADDR_POLICY_REJECTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); - test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, NULL, 1)); + test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, 1, NULL, 1)); test_assert(policy2); policy3 = smartlist_new(); @@ -1188,9 +1298,9 @@ test_policies(void) 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)); + test_assert(!policy_is_reject_star(policy2, AF_INET)); + test_assert(policy_is_reject_star(policy, AF_INET)); + test_assert(policy_is_reject_star(NULL, AF_INET)); addr_policy_list_free(policy); policy = NULL; @@ -1200,11 +1310,11 @@ test_policies(void) 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(0 == policies_parse_exit_policy(&line, &policy, 1, 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_eq(smartlist_len(policy), 4); /* test policy summaries */ /* check if we properly ignore private IP addresses */ @@ -1366,11 +1476,20 @@ test_rend_fns(void) char address2[] = "aaaaaaaaaaaaaaaa.onion"; char address3[] = "fooaddress.exit"; char address4[] = "www.torproject.org"; + char address5[] = "foo.abcdefghijklmnop.onion"; + char address6[] = "foo.bar.abcdefghijklmnop.onion"; + char address7[] = ".abcdefghijklmnop.onion"; test_assert(BAD_HOSTNAME == parse_extended_hostname(address1)); test_assert(ONION_HOSTNAME == parse_extended_hostname(address2)); + test_streq(address2, "aaaaaaaaaaaaaaaa"); test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3)); test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4)); + test_assert(ONION_HOSTNAME == parse_extended_hostname(address5)); + test_streq(address5, "abcdefghijklmnop"); + test_assert(ONION_HOSTNAME == parse_extended_hostname(address6)); + test_streq(address6, "abcdefghijklmnop"); + test_assert(BAD_HOSTNAME == parse_extended_hostname(address7)); pk1 = pk_generate(0); pk2 = pk_generate(1); @@ -1466,66 +1585,43 @@ test_geoip(void) { int i, j; time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ - char *s = NULL; + char *s = NULL, *v = NULL; const char *bridge_stats_1 = "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "bridge-ips zz=24,xy=8\n", + "bridge-ips zz=24,xy=8\n" + "bridge-ip-versions v4=16,v6=16\n", *dirreq_stats_1 = "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips ab=8\n" - "dirreq-v2-ips \n" "dirreq-v3-reqs ab=8\n" - "dirreq-v2-reqs \n" "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" - "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," - "busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n" - "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", *dirreq_stats_2 = "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips \n" - "dirreq-v2-ips \n" "dirreq-v3-reqs \n" - "dirreq-v2-reqs \n" "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" - "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," - "busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n" - "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", *dirreq_stats_3 = "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips \n" - "dirreq-v2-ips \n" "dirreq-v3-reqs \n" - "dirreq-v2-reqs \n" "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" - "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," - "busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n" - "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", *dirreq_stats_4 = "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips \n" - "dirreq-v2-ips \n" "dirreq-v3-reqs \n" - "dirreq-v2-reqs \n" "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" - "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," - "busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" - "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n" - "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n", *entry_stats_1 = "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" "entry-ips ab=8\n", @@ -1533,61 +1629,109 @@ test_geoip(void) "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" "entry-ips \n"; tor_addr_t addr; + struct in6_addr in6; /* 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\"")); + test_eq(0, geoip_parse_entry("10,50,AB", AF_INET)); + test_eq(0, geoip_parse_entry("52,90,XY", AF_INET)); + test_eq(0, geoip_parse_entry("95,100,AB", AF_INET)); + test_eq(0, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET)); + test_eq(0, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET)); + test_eq(0, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET)); + + /* Populate the IPv6 DB equivalently with fake IPs in the same range */ + test_eq(0, geoip_parse_entry("::a,::32,AB", AF_INET6)); + test_eq(0, geoip_parse_entry("::34,::5a,XY", AF_INET6)); + test_eq(0, geoip_parse_entry("::5f,::64,AB", AF_INET6)); + test_eq(0, geoip_parse_entry("::69,::8c,ZZ", AF_INET6)); + test_eq(0, geoip_parse_entry("::96,::be,XY", AF_INET6)); + test_eq(0, geoip_parse_entry("::c8,::fa,AB", AF_INET6)); /* We should have 4 countries: ??, ab, xy, zz. */ test_eq(4, geoip_get_n_countries()); + memset(&in6, 0, sizeof(in6)); + /* 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 +#define SET_TEST_IPV6(i) \ + do { \ + set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i))); \ + } while (0) +#define CHECK_COUNTRY(country, val) do { \ + /* test ipv4 country lookup */ \ + test_streq(country, \ + geoip_get_country_name(geoip_get_country_by_ipv4(val))); \ + /* test ipv6 country lookup */ \ + SET_TEST_IPV6(val); \ + test_streq(country, \ + geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \ + } while (0) + + CHECK_COUNTRY("??", 3); + CHECK_COUNTRY("ab", 32); + CHECK_COUNTRY("??", 5); + CHECK_COUNTRY("??", 51); + CHECK_COUNTRY("xy", 150); + CHECK_COUNTRY("xy", 190); + CHECK_COUNTRY("??", 2000); + + test_eq(0, geoip_get_country_by_ipv4(3)); + SET_TEST_IPV6(3); + test_eq(0, geoip_get_country_by_ipv6(&in6)); + +#undef CHECK_COUNTRY + + /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs + * using ipv4. Since our fake geoip database is the same between + * ipv4 and ipv6, we should get the same result no matter which + * address family we pick for each IP. */ +#define SET_TEST_ADDRESS(i) do { \ + if ((i) & 1) { \ + SET_TEST_IPV6(i); \ + tor_addr_from_in6(&addr, &in6); \ + } else { \ + tor_addr_from_ipv4h(&addr, (uint32_t) i); \ + } \ + } while (0) get_options_mutable()->BridgeRelay = 1; get_options_mutable()->BridgeRecordUsageByCountry = 1; /* Put 9 observations in AB... */ for (i=32; i < 40; ++i) { - tor_addr_from_ipv4h(&addr, (uint32_t) i); + SET_TEST_ADDRESS(i); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-7200); } - tor_addr_from_ipv4h(&addr, (uint32_t) 225); + SET_TEST_ADDRESS(225); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-7200); /* and 3 observations in XY, several times. */ for (j=0; j < 10; ++j) for (i=52; i < 55; ++i) { - tor_addr_from_ipv4h(&addr, (uint32_t) i); + SET_TEST_ADDRESS(i); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now-3600); } /* and 17 observations in ZZ... */ for (i=110; i < 127; ++i) { - tor_addr_from_ipv4h(&addr, (uint32_t) i); + SET_TEST_ADDRESS(i); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now); } - s = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); test_assert(s); + test_assert(v); test_streq("zz=24,ab=16,xy=8", s); + test_streq("v4=16,v6=16", v); tor_free(s); + tor_free(v); /* Now clear out all the AB observations. */ geoip_remove_old_clients(now-6000); - s = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v); test_assert(s); + test_assert(v); test_streq("zz=24,xy=8", s); + test_streq("v4=16,v6=16", v); + tor_free(s); + tor_free(v); /* Start testing bridge statistics by making sure that we don't output * bridge stats without initializing them. */ @@ -1598,6 +1742,7 @@ test_geoip(void) * the connecting clients added above. */ geoip_bridge_stats_init(now); s = geoip_format_bridge_stats(now + 86400); + test_assert(s); test_streq(bridge_stats_1, s); tor_free(s); @@ -1616,7 +1761,7 @@ test_geoip(void) /* Start testing dirreq statistics by making sure that we don't collect * dirreq stats without initializing them. */ - tor_addr_from_ipv4h(&addr, (uint32_t) 100); + SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, now); s = geoip_format_dirreq_stats(now + 86400); test_assert(!s); @@ -1624,7 +1769,7 @@ test_geoip(void) /* Initialize stats, note one connecting client, and generate the * dirreq-stats history string. */ geoip_dirreq_stats_init(now); - tor_addr_from_ipv4h(&addr, (uint32_t) 100); + SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, now); s = geoip_format_dirreq_stats(now + 86400); test_streq(dirreq_stats_1, s); @@ -1633,7 +1778,7 @@ test_geoip(void) /* Stop collecting stats, add another connecting client, and ensure we * don't generate a history string. */ geoip_dirreq_stats_term(); - tor_addr_from_ipv4h(&addr, (uint32_t) 101); + SET_TEST_ADDRESS(101); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, now); s = geoip_format_dirreq_stats(now + 86400); test_assert(!s); @@ -1641,7 +1786,7 @@ test_geoip(void) /* Re-start stats, add a connecting client, reset stats, and make sure * that we get an all empty history string. */ geoip_dirreq_stats_init(now); - tor_addr_from_ipv4h(&addr, (uint32_t) 100); + SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, now); geoip_reset_dirreq_stats(now); s = geoip_format_dirreq_stats(now + 86400); @@ -1650,14 +1795,13 @@ test_geoip(void) /* Note a successful network status response and make sure that it * appears in the history string. */ - geoip_note_ns_response(GEOIP_CLIENT_NETWORKSTATUS, GEOIP_SUCCESS); + geoip_note_ns_response(GEOIP_SUCCESS); s = geoip_format_dirreq_stats(now + 86400); test_streq(dirreq_stats_3, s); tor_free(s); /* Start a tunneled directory request. */ - geoip_start_dirreq((uint64_t) 1, 1024, GEOIP_CLIENT_NETWORKSTATUS, - DIRREQ_TUNNELED); + geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED); s = geoip_format_dirreq_stats(now + 86400); test_streq(dirreq_stats_4, s); @@ -1669,7 +1813,7 @@ test_geoip(void) /* Start testing entry statistics by making sure that we don't collect * anything without initializing entry stats. */ - tor_addr_from_ipv4h(&addr, (uint32_t) 100); + SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now); s = geoip_format_entry_stats(now + 86400); test_assert(!s); @@ -1677,7 +1821,7 @@ test_geoip(void) /* Initialize stats, note one connecting client, and generate the * entry-stats history string. */ geoip_entry_stats_init(now); - tor_addr_from_ipv4h(&addr, (uint32_t) 100); + SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now); s = geoip_format_entry_stats(now + 86400); test_streq(entry_stats_1, s); @@ -1686,7 +1830,7 @@ test_geoip(void) /* Stop collecting stats, add another connecting client, and ensure we * don't generate a history string. */ geoip_entry_stats_term(); - tor_addr_from_ipv4h(&addr, (uint32_t) 101); + SET_TEST_ADDRESS(101); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now); s = geoip_format_entry_stats(now + 86400); test_assert(!s); @@ -1694,19 +1838,23 @@ test_geoip(void) /* Re-start stats, add a connecting client, reset stats, and make sure * that we get an all empty history string. */ geoip_entry_stats_init(now); - tor_addr_from_ipv4h(&addr, (uint32_t) 100); + SET_TEST_ADDRESS(100); geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now); geoip_reset_entry_stats(now); s = geoip_format_entry_stats(now + 86400); test_streq(entry_stats_2, s); tor_free(s); +#undef SET_TEST_ADDRESS +#undef SET_TEST_IPV6 + /* Stop collecting entry statistics. */ geoip_entry_stats_term(); get_options_mutable()->EntryStatistics = 0; done: tor_free(s); + tor_free(v); } /** Run unit tests for stats code. */ @@ -1895,11 +2043,6 @@ const struct testcase_setup_t legacy_setup = { #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, test_ ## name } #define FORK(name) \ { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_ ## name } @@ -1907,6 +2050,10 @@ static struct testcase_t test_array[] = { ENT(buffers), { "buffer_copy", test_buffer_copy, 0, NULL, NULL }, ENT(onion_handshake), + ENT(onion_queues), +#ifdef CURVE25519_ENABLED + { "ntor_handshake", test_ntor_handshake, 0, NULL, NULL }, +#endif ENT(circuit_timeout), ENT(policies), ENT(rend_fns), @@ -1941,6 +2088,9 @@ extern struct testcase_t dir_tests[]; extern struct testcase_t microdesc_tests[]; extern struct testcase_t pt_tests[]; extern struct testcase_t config_tests[]; +extern struct testcase_t introduce_tests[]; +extern struct testcase_t replaycache_tests[]; +extern struct testcase_t cell_format_tests[]; static struct testgroup_t testgroups[] = { { "", test_array }, @@ -1949,10 +2099,13 @@ static struct testgroup_t testgroups[] = { { "crypto/", crypto_tests }, { "container/", container_tests }, { "util/", util_tests }, + { "cellfmt/", cell_format_tests }, { "dir/", dir_tests }, { "dir/md/", microdesc_tests }, { "pt/", pt_tests }, { "config/", config_tests }, + { "replaycache/", replaycache_tests }, + { "introduce/", introduce_tests }, END_OF_GROUPS }; @@ -1968,7 +2121,7 @@ main(int c, const char **v) #ifdef USE_DMALLOC { - int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc, _tor_free); + int r = CRYPTO_set_mem_ex_functions(tor_malloc_, tor_realloc_, tor_free_); tor_assert(r); } #endif @@ -2006,6 +2159,7 @@ main(int c, const char **v) return 1; } crypto_set_tls_dh_prime(NULL); + crypto_seed_rng(1); rep_hist_init(); network_init(); setup_directory(); @@ -2018,8 +2172,6 @@ main(int c, const char **v) return 1; } - crypto_seed_rng(1); - atexit(remove_directory); have_failed = (tinytest_main(c, v, testgroups) != 0); diff --git a/src/test/test.h b/src/test/test.h index 0b6e6c60cb..a89b558e5a 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -1,10 +1,10 @@ /* Copyright (c) 2001-2003, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#ifndef _TOR_TEST_H -#define _TOR_TEST_H +#ifndef TOR_TEST_H +#define TOR_TEST_H /** * \file test.h @@ -65,6 +65,10 @@ #define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, ==, hex) +#define tt_double_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%f", \ + TT_EXIT_TEST_FUNCTION) + const char *get_fname(const char *name); crypto_pk_t *pk_generate(int idx); diff --git a/src/test/test_addr.c b/src/test/test_addr.c index e3f38073ec..fec85a4696 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -1,11 +1,13 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#define ADDRESSMAP_PRIVATE #include "orconfig.h" #include "or.h" #include "test.h" +#include "addressmap.h" static void test_addr_basic(void) @@ -38,7 +40,7 @@ test_addr_basic(void) tor_free(cp); u32 = 3; test_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16)); - test_eq(cp, NULL); + test_eq_ptr(cp, NULL); test_eq(u32, 0x7f000001u); test_eq(u16, 0); tor_free(cp); @@ -70,7 +72,7 @@ test_addr_basic(void) ; } -#define _test_op_ip6(a,op,b,e1,e2) \ +#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), \ @@ -93,7 +95,7 @@ test_addr_basic(void) #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); \ + test_op_ip6_(&a1,==,&a2,#a,#b); \ STMT_END /** Helper: Assert that <b>a</b> is recognized as a bad IPv6 address by @@ -108,7 +110,7 @@ test_addr_basic(void) 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); \ + test_op_ip6_(&a1, ==, &a2, a, b); \ STMT_END /** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that @@ -159,7 +161,8 @@ test_addr_basic(void) * 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); \ + test_eq(tor_addr_parse_mask_ports(xx, 0, &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]); \ @@ -401,11 +404,11 @@ test_addr_ip6_helpers(void) 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); + tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", 0, &t1, NULL, NULL, NULL); + tor_addr_parse_mask_ports("2.3.4.5", 0, &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); + tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", 0, &t1, NULL, NULL, NULL); + tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL); test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0); /* test compare_masked */ @@ -568,6 +571,7 @@ test_addr_ip6_helpers(void) test_streq(rbuf, addr_PTR); } + /* XXXX turn this into a separate function; it's not all IPv6. */ /* test tor_addr_parse_mask_ports */ test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6, 0, 0, 0, 0x0000000f, 17, 47, 95); @@ -581,27 +585,123 @@ test_addr_ip6_helpers(void) 0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000); test_streq(p1, "abcd:2::44a:0"); - r=tor_addr_parse_mask_ports("[fefef::]/112", &t1, NULL, NULL, NULL); + /* Try some long addresses. */ + r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111]", + 0, &t1, NULL, NULL, NULL); + test_assert(r == AF_INET6); + r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:11111]", + 0, &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111:1]", + 0, &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports( + "[ffff:1111:1111:1111:1111:1111:1111:ffff:" + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:" + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:" + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]", + 0, &t1, NULL, NULL, NULL); + test_assert(r == -1); + /* Try some failing cases. */ + r=tor_addr_parse_mask_ports("[fefef::]/112", 0, &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[fefe::/112", 0, &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[fefe::", 0, &t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[fefe::X]", 0, &t1, NULL, NULL, NULL); test_assert(r == -1); - r=tor_addr_parse_mask_ports("efef::/112", &t1, NULL, NULL, NULL); + r=tor_addr_parse_mask_ports("efef::/112", 0, &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); + r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]",0,&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); + r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]",0,&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); + r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/fred",0,&t1,&mask, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/255.255.0.0", + 0,&t1, NULL, NULL, NULL); + test_assert(r == -1); + /* This one will get rejected because it isn't a pure prefix. */ + r=tor_addr_parse_mask_ports("1.1.2.3/255.255.64.0",0,&t1, &mask,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); + r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]",0,&t1, &mask, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("1.1.2.2/33",0,&t1, &mask, NULL, NULL); + test_assert(r == -1); + /* Try extended wildcard addresses with out TAPMP_EXTENDED_STAR*/ + r=tor_addr_parse_mask_ports("*4",0,&t1, &mask, NULL, NULL); + test_assert(r == -1); + r=tor_addr_parse_mask_ports("*6",0,&t1, &mask, NULL, NULL); + test_assert(r == -1); +#if 0 + /* Try a mask with a wildcard. */ + r=tor_addr_parse_mask_ports("*/16",0,&t1, &mask, NULL, NULL); test_assert(r == -1); - r=tor_addr_parse_mask_ports("1.1.2.2/33", &t1, &mask, NULL, NULL); + r=tor_addr_parse_mask_ports("*4/16",TAPMP_EXTENDED_STAR, + &t1, &mask, NULL, NULL); test_assert(r == -1); - r=tor_addr_parse_mask_ports("1.1.2.2/31", &t1, &mask, NULL, NULL); + r=tor_addr_parse_mask_ports("*6/30",TAPMP_EXTENDED_STAR, + &t1, &mask, NULL, NULL); + test_assert(r == -1); +#endif + /* Basic mask tests*/ + r=tor_addr_parse_mask_ports("1.1.2.2/31",0,&t1, &mask, NULL, NULL); + test_assert(r == AF_INET); + tt_int_op(mask,==,31); + tt_int_op(tor_addr_family(&t1),==,AF_INET); + tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010202); + r=tor_addr_parse_mask_ports("3.4.16.032:1-2",0,&t1, &mask, &port1, &port2); + test_assert(r == AF_INET); + tt_int_op(mask,==,32); + tt_int_op(tor_addr_family(&t1),==,AF_INET); + tt_int_op(tor_addr_to_ipv4h(&t1),==,0x03041020); + test_assert(port1 == 1); + test_assert(port2 == 2); + r=tor_addr_parse_mask_ports("1.1.2.3/255.255.128.0",0,&t1, &mask,NULL,NULL); test_assert(r == AF_INET); - r=tor_addr_parse_mask_ports("[efef::]/112", &t1, &mask, &port1, &port2); + tt_int_op(mask,==,17); + tt_int_op(tor_addr_family(&t1),==,AF_INET); + tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010203); + r=tor_addr_parse_mask_ports("[efef::]/112",0,&t1, &mask, &port1, &port2); test_assert(r == AF_INET6); test_assert(port1 == 1); test_assert(port2 == 65535); + /* Try regular wildcard behavior without TAPMP_EXTENDED_STAR */ + r=tor_addr_parse_mask_ports("*:80-443",0,&t1,&mask,&port1,&port2); + tt_int_op(r,==,AF_INET); /* Old users of this always get inet */ + tt_int_op(tor_addr_family(&t1),==,AF_INET); + tt_int_op(tor_addr_to_ipv4h(&t1),==,0); + tt_int_op(mask,==,0); + tt_int_op(port1,==,80); + tt_int_op(port2,==,443); + /* Now try wildcards *with* TAPMP_EXTENDED_STAR */ + r=tor_addr_parse_mask_ports("*:8000-9000",TAPMP_EXTENDED_STAR, + &t1,&mask,&port1,&port2); + tt_int_op(r,==,AF_UNSPEC); + tt_int_op(tor_addr_family(&t1),==,AF_UNSPEC); + tt_int_op(mask,==,0); + tt_int_op(port1,==,8000); + tt_int_op(port2,==,9000); + r=tor_addr_parse_mask_ports("*4:6667",TAPMP_EXTENDED_STAR, + &t1,&mask,&port1,&port2); + tt_int_op(r,==,AF_INET); + tt_int_op(tor_addr_family(&t1),==,AF_INET); + tt_int_op(tor_addr_to_ipv4h(&t1),==,0); + tt_int_op(mask,==,0); + tt_int_op(port1,==,6667); + tt_int_op(port2,==,6667); + r=tor_addr_parse_mask_ports("*6",TAPMP_EXTENDED_STAR, + &t1,&mask,&port1,&port2); + tt_int_op(r,==,AF_INET6); + tt_int_op(tor_addr_family(&t1),==,AF_INET6); + tt_assert(tor_mem_is_zero((const char*)tor_addr_to_in6_addr32(&t1), 16)); + tt_int_op(mask,==,0); + tt_int_op(port1,==,1); + tt_int_op(port2,==,65535); /* make sure inet address lengths >= max */ test_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255")); @@ -623,6 +723,126 @@ test_addr_ip6_helpers(void) ; } +/** Test tor_addr_port_parse(). */ +static void +test_addr_parse(void) +{ + int r; + tor_addr_t addr; + char buf[TOR_ADDR_BUF_LEN]; + uint16_t port = 0; + + /* Correct call. */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2.1:1234", + &addr, &port); + test_assert(r == 0); + tor_addr_to_str(buf, &addr, sizeof(buf), 0); + test_streq(buf, "192.0.2.1"); + test_eq(port, 1234); + + /* Domain name. */ + r= tor_addr_port_parse(LOG_DEBUG, + "torproject.org:1234", + &addr, &port); + test_assert(r == -1); + + /* Only IP. */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2.2", + &addr, &port); + test_assert(r == -1); + + /* Bad port. */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2.2:66666", + &addr, &port); + test_assert(r == -1); + + /* Only domain name */ + r= tor_addr_port_parse(LOG_DEBUG, + "torproject.org", + &addr, &port); + test_assert(r == -1); + + /* Bad IP address */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2:1234", + &addr, &port); + test_assert(r == -1); + + done: + ; +} + +static void +update_difference(int ipv6, uint8_t *d, + const tor_addr_t *a, const tor_addr_t *b) +{ + const int n_bytes = ipv6 ? 16 : 4; + uint8_t a_tmp[4], b_tmp[4]; + const uint8_t *ba, *bb; + int i; + + if (ipv6) { + ba = tor_addr_to_in6_addr8(a); + bb = tor_addr_to_in6_addr8(b); + } else { + set_uint32(a_tmp, tor_addr_to_ipv4n(a)); + set_uint32(b_tmp, tor_addr_to_ipv4n(b)); + ba = a_tmp; bb = b_tmp; + } + + for (i = 0; i < n_bytes; ++i) { + d[i] |= ba[i] ^ bb[i]; + } +} + +static void +test_virtaddrmap(void *data) +{ + /* Let's start with a bunch of random addresses. */ + int ipv6, bits, iter, b; + virtual_addr_conf_t cfg[2]; + uint8_t bytes[16]; + + (void)data; + + tor_addr_parse(&cfg[0].addr, "64.65.0.0"); + tor_addr_parse(&cfg[1].addr, "3491:c0c0::"); + + for (ipv6 = 0; ipv6 <= 1; ++ipv6) { + for (bits = 0; bits < 18; ++bits) { + tor_addr_t last_a; + cfg[ipv6].bits = bits; + memset(bytes, 0, sizeof(bytes)); + tor_addr_copy(&last_a, &cfg[ipv6].addr); + /* Generate 128 addresses with each addr/bits combination. */ + for (iter = 0; iter < 128; ++iter) { + tor_addr_t a; + + get_random_virtual_addr(&cfg[ipv6], &a); + //printf("%s\n", fmt_addr(&a)); + /* Make sure that the first b bits match the configured network */ + tt_int_op(0, ==, tor_addr_compare_masked(&a, &cfg[ipv6].addr, + bits, CMP_EXACT)); + + /* And track which bits have been different between pairs of + * addresses */ + update_difference(ipv6, bytes, &last_a, &a); + } + + /* Now make sure all but the first 'bits' bits of bytes are true */ + for (b = bits+1; b < (ipv6?128:32); ++b) { + tt_assert(1 & (bytes[b/8] >> (7-(b&7)))); + } + } + } + + done: + ; +} + static void test_addr_is_loopback(void *data) { @@ -664,6 +884,8 @@ test_addr_is_loopback(void *data) struct testcase_t addr_tests[] = { ADDR_LEGACY(basic), ADDR_LEGACY(ip6_helpers), + ADDR_LEGACY(parse), + { "virtaddr", test_virtaddrmap, 0, NULL, NULL }, { "is_loopback", test_addr_is_loopback, 0, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c new file mode 100644 index 0000000000..55d8d0f00f --- /dev/null +++ b/src/test/test_cell_formats.c @@ -0,0 +1,888 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define CONNECTION_EDGE_PRIVATE +#define RELAY_PRIVATE +#include "or.h" +#include "connection_edge.h" +#include "onion.h" +#include "onion_tap.h" +#include "onion_fast.h" +#include "onion_ntor.h" +#include "relay.h" +#include "test.h" + +#include <stdlib.h> +#include <string.h> + +static void +test_cfmt_relay_header(void *arg) +{ + relay_header_t rh; + const uint8_t hdr_1[RELAY_HEADER_SIZE] = + "\x03" "\x00\x00" "\x21\x22" "ABCD" "\x01\x03"; + uint8_t hdr_out[RELAY_HEADER_SIZE]; + (void)arg; + + tt_int_op(sizeof(hdr_1), ==, RELAY_HEADER_SIZE); + relay_header_unpack(&rh, hdr_1); + tt_int_op(rh.command, ==, 3); + tt_int_op(rh.recognized, ==, 0); + tt_int_op(rh.stream_id, ==, 0x2122); + test_mem_op(rh.integrity, ==, "ABCD", 4); + tt_int_op(rh.length, ==, 0x103); + + relay_header_pack(hdr_out, &rh); + test_mem_op(hdr_out, ==, hdr_1, RELAY_HEADER_SIZE); + + done: + ; +} + +static void +make_relay_cell(cell_t *out, uint8_t command, + const void *body, size_t bodylen) +{ + relay_header_t rh; + + memset(&rh, 0, sizeof(rh)); + rh.stream_id = 5; + rh.command = command; + rh.length = bodylen; + + out->command = CELL_RELAY; + out->circ_id = 10; + relay_header_pack(out->payload, &rh); + + memcpy(out->payload + RELAY_HEADER_SIZE, body, bodylen); +} + +static void +test_cfmt_begin_cells(void *arg) +{ + cell_t cell; + begin_cell_t bcell; + uint8_t end_reason; + (void)arg; + + /* Try begindir. */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "", 0); + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_ptr_op(NULL, ==, bcell.address); + tt_int_op(0, ==, bcell.flags); + tt_int_op(0, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(1, ==, bcell.is_begindir); + + /* A Begindir with extra stuff. */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "12345", 5); + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_ptr_op(NULL, ==, bcell.address); + tt_int_op(0, ==, bcell.flags); + tt_int_op(0, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(1, ==, bcell.is_begindir); + + /* A short but valid begin cell */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:9", 6); + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_str_op("a.b", ==, bcell.address); + tt_int_op(0, ==, bcell.flags); + tt_int_op(9, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(0, ==, bcell.is_begindir); + tor_free(bcell.address); + + /* A significantly loner begin cell */ + memset(&bcell, 0x7f, sizeof(bcell)); + { + const char c[] = "here-is-a-nice-long.hostname.com:65535"; + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, strlen(c)+1); + } + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_str_op("here-is-a-nice-long.hostname.com", ==, bcell.address); + tt_int_op(0, ==, bcell.flags); + tt_int_op(65535, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(0, ==, bcell.is_begindir); + tor_free(bcell.address); + + /* An IPv4 begin cell. */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "18.9.22.169:80", 15); + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_str_op("18.9.22.169", ==, bcell.address); + tt_int_op(0, ==, bcell.flags); + tt_int_op(80, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(0, ==, bcell.is_begindir); + tor_free(bcell.address); + + /* An IPv6 begin cell. Let's make sure we handle colons*/ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, + "[2620::6b0:b:1a1a:0:26e5:480e]:80", 34); + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_str_op("[2620::6b0:b:1a1a:0:26e5:480e]", ==, bcell.address); + tt_int_op(0, ==, bcell.flags); + tt_int_op(80, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(0, ==, bcell.is_begindir); + tor_free(bcell.address); + + /* a begin cell with extra junk but not enough for flags. */ + memset(&bcell, 0x7f, sizeof(bcell)); + { + const char c[] = "another.example.com:80\x00\x01\x02"; + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + } + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_str_op("another.example.com", ==, bcell.address); + tt_int_op(0, ==, bcell.flags); + tt_int_op(80, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(0, ==, bcell.is_begindir); + tor_free(bcell.address); + + /* a begin cell with flags. */ + memset(&bcell, 0x7f, sizeof(bcell)); + { + const char c[] = "another.example.com:443\x00\x01\x02\x03\x04"; + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + } + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_str_op("another.example.com", ==, bcell.address); + tt_int_op(0x1020304, ==, bcell.flags); + tt_int_op(443, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(0, ==, bcell.is_begindir); + tor_free(bcell.address); + + /* a begin cell with flags and even more cruft after that. */ + memset(&bcell, 0x7f, sizeof(bcell)); + { + const char c[] = "a-further.example.com:22\x00\xee\xaa\x00\xffHi mom"; + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + } + tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_str_op("a-further.example.com", ==, bcell.address); + tt_int_op(0xeeaa00ff, ==, bcell.flags); + tt_int_op(22, ==, bcell.port); + tt_int_op(5, ==, bcell.stream_id); + tt_int_op(0, ==, bcell.is_begindir); + tor_free(bcell.address); + + /* bad begin cell: impossible length. */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 7); + cell.payload[9] = 0x01; /* Set length to 510 */ + cell.payload[10] = 0xfe; + { + relay_header_t rh; + relay_header_unpack(&rh, cell.payload); + tt_int_op(rh.length, ==, 510); + } + tt_int_op(-2, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + + /* Bad begin cell: no body. */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0); + tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + + /* bad begin cell: no body. */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0); + tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + + /* bad begin cell: no colon */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b", 4); + tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + + /* bad begin cell: no ports */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:", 5); + tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + + /* bad begin cell: bad port */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:xyz", 8); + tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:100000", 11); + tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + + /* bad begin cell: no nul */ + memset(&bcell, 0x7f, sizeof(bcell)); + make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 6); + tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason)); + + done: + tor_free(bcell.address); +} + +static void +test_cfmt_connected_cells(void *arg) +{ + relay_header_t rh; + cell_t cell; + tor_addr_t addr; + int ttl, r; + char *mem_op_hex_tmp = NULL; + (void)arg; + + /* Let's try an oldschool one with nothing in it. */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "", 0); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_UNSPEC); + tt_int_op(ttl, ==, -1); + + /* A slightly less oldschool one: only an IPv4 address */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x20\x30\x40\x50", 4); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET); + tt_str_op(fmt_addr(&addr), ==, "32.48.64.80"); + tt_int_op(ttl, ==, -1); + + /* Bogus but understandable: truncated TTL */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x11\x12\x13\x14\x15", 5); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET); + tt_str_op(fmt_addr(&addr), ==, "17.18.19.20"); + tt_int_op(ttl, ==, -1); + + /* Regular IPv4 one: address and TTL */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + "\x02\x03\x04\x05\x00\x00\x0e\x10", 8); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET); + tt_str_op(fmt_addr(&addr), ==, "2.3.4.5"); + tt_int_op(ttl, ==, 3600); + + /* IPv4 with too-big TTL */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + "\x02\x03\x04\x05\xf0\x00\x00\x00", 8); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET); + tt_str_op(fmt_addr(&addr), ==, "2.3.4.5"); + tt_int_op(ttl, ==, -1); + + /* IPv6 (ttl is mandatory) */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + "\x00\x00\x00\x00\x06" + "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" + "\x00\x00\x00\x00\x00\x00\x00\x68" + "\x00\x00\x02\x58", 25); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET6); + tt_str_op(fmt_addr(&addr), ==, "2607:f8b0:400c:c02::68"); + tt_int_op(ttl, ==, 600); + + /* IPv6 (ttl too big) */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + "\x00\x00\x00\x00\x06" + "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" + "\x00\x00\x00\x00\x00\x00\x00\x68" + "\x90\x00\x02\x58", 25); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET6); + tt_str_op(fmt_addr(&addr), ==, "2607:f8b0:400c:c02::68"); + tt_int_op(ttl, ==, -1); + + /* Bogus size: 3. */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + "\x00\x01\x02", 3); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, -1); + + /* Bogus family: 7. */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + "\x00\x00\x00\x00\x07" + "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" + "\x00\x00\x00\x00\x00\x00\x00\x68" + "\x90\x00\x02\x58", 25); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, -1); + + /* Truncated IPv6. */ + make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + "\x00\x00\x00\x00\x06" + "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" + "\x00\x00\x00\x00\x00\x00\x00\x68" + "\x00\x00\x02", 24); + relay_header_unpack(&rh, cell.payload); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, -1); + + /* Now make sure we can generate connected cells correctly. */ + /* Try an IPv4 address */ + memset(&rh, 0, sizeof(rh)); + memset(&cell, 0, sizeof(cell)); + tor_addr_parse(&addr, "30.40.50.60"); + rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, + &addr, 128); + tt_int_op(rh.length, ==, 8); + test_memeq_hex(cell.payload+RELAY_HEADER_SIZE, "1e28323c" "00000080"); + + /* Try parsing it. */ + tor_addr_make_unspec(&addr); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET); + tt_str_op(fmt_addr(&addr), ==, "30.40.50.60"); + tt_int_op(ttl, ==, 128); + + /* Try an IPv6 address */ + memset(&rh, 0, sizeof(rh)); + memset(&cell, 0, sizeof(cell)); + tor_addr_parse(&addr, "2620::6b0:b:1a1a:0:26e5:480e"); + rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, + &addr, 3600); + tt_int_op(rh.length, ==, 25); + test_memeq_hex(cell.payload + RELAY_HEADER_SIZE, + "00000000" "06" + "2620000006b0000b1a1a000026e5480e" "00000e10"); + + /* Try parsing it. */ + tor_addr_make_unspec(&addr); + r = connected_cell_parse(&rh, &cell, &addr, &ttl); + tt_int_op(r, ==, 0); + tt_int_op(tor_addr_family(&addr), ==, AF_INET6); + tt_str_op(fmt_addr(&addr), ==, "2620:0:6b0:b:1a1a:0:26e5:480e"); + tt_int_op(ttl, ==, 3600); + + done: + tor_free(mem_op_hex_tmp); +} + +static void +test_cfmt_create_cells(void *arg) +{ + uint8_t b[MAX_ONIONSKIN_CHALLENGE_LEN]; + create_cell_t cc; + cell_t cell; + cell_t cell2; + + (void)arg; + + /* === Let's try parsing some good cells! */ + + /* A valid create cell. */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); + cell.command = CELL_CREATE; + memcpy(cell.payload, b, TAP_ONIONSKIN_CHALLENGE_LEN); + tt_int_op(0, ==, create_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATE, ==, cc.cell_type); + tt_int_op(ONION_HANDSHAKE_TYPE_TAP, ==, cc.handshake_type); + tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, ==, cc.handshake_len); + test_memeq(cc.onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); + tt_int_op(0, ==, create_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + + /* A valid create_fast cell. */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, CREATE_FAST_LEN); + cell.command = CELL_CREATE_FAST; + memcpy(cell.payload, b, CREATE_FAST_LEN); + tt_int_op(0, ==, create_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATE_FAST, ==, cc.cell_type); + tt_int_op(ONION_HANDSHAKE_TYPE_FAST, ==, cc.handshake_type); + tt_int_op(CREATE_FAST_LEN, ==, cc.handshake_len); + test_memeq(cc.onionskin, b, CREATE_FAST_LEN + 10); + tt_int_op(0, ==, create_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + + /* A valid create2 cell with a TAP payload */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); + cell.command = CELL_CREATE2; + memcpy(cell.payload, "\x00\x00\x00\xBA", 4); /* TAP, 186 bytes long */ + memcpy(cell.payload+4, b, TAP_ONIONSKIN_CHALLENGE_LEN); + tt_int_op(0, ==, create_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATE2, ==, cc.cell_type); + tt_int_op(ONION_HANDSHAKE_TYPE_TAP, ==, cc.handshake_type); + tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, ==, cc.handshake_len); + test_memeq(cc.onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); + tt_int_op(0, ==, create_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + + /* A valid create2 cell with an ntor payload */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); + cell.command = CELL_CREATE2; + memcpy(cell.payload, "\x00\x02\x00\x54", 4); /* ntor, 84 bytes long */ + memcpy(cell.payload+4, b, NTOR_ONIONSKIN_LEN); +#ifdef CURVE25519_ENABLED + tt_int_op(0, ==, create_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATE2, ==, cc.cell_type); + tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, ==, cc.handshake_type); + tt_int_op(NTOR_ONIONSKIN_LEN, ==, cc.handshake_len); + test_memeq(cc.onionskin, b, NTOR_ONIONSKIN_LEN + 10); + tt_int_op(0, ==, create_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); +#else + tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); +#endif + + /* A valid create cell with an ntor payload, in legacy format. */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); + cell.command = CELL_CREATE; + memcpy(cell.payload, "ntorNTORntorNTOR", 16); + memcpy(cell.payload+16, b, NTOR_ONIONSKIN_LEN); +#ifdef CURVE25519_ENABLED + tt_int_op(0, ==, create_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATE, ==, cc.cell_type); + tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, ==, cc.handshake_type); + tt_int_op(NTOR_ONIONSKIN_LEN, ==, cc.handshake_len); + test_memeq(cc.onionskin, b, NTOR_ONIONSKIN_LEN + 10); + tt_int_op(0, ==, create_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); +#else + tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); +#endif + + /* == Okay, now let's try to parse some impossible stuff. */ + + /* It has to be some kind of a create cell! */ + cell.command = CELL_CREATED; + tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); + + /* You can't acutally make an unparseable CREATE or CREATE_FAST cell. */ + + /* Try some CREATE2 cells. First with a bad type. */ + cell.command = CELL_CREATE2; + memcpy(cell.payload, "\x00\x50\x00\x99", 4); /* Type 0x50???? */ + tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); + /* Now a good type with an incorrect length. */ + memcpy(cell.payload, "\x00\x00\x00\xBC", 4); /* TAP, 187 bytes.*/ + tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); + /* Now a good type with a ridiculous length. */ + memcpy(cell.payload, "\x00\x00\x02\x00", 4); /* TAP, 512 bytes.*/ + tt_int_op(-1, ==, create_cell_parse(&cc, &cell)); + + /* == Time to try formatting bad cells. The important thing is that + we reject big lengths, so just check that for now. */ + cc.handshake_len = 512; + tt_int_op(-1, ==, create_cell_format(&cell2, &cc)); + + /* == Try formatting a create2 cell we don't understand. XXXX */ + + done: + ; +} + +static void +test_cfmt_created_cells(void *arg) +{ + uint8_t b[512]; + created_cell_t cc; + cell_t cell; + cell_t cell2; + + (void)arg; + + /* A good CREATED cell */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN); + cell.command = CELL_CREATED; + memcpy(cell.payload, b, TAP_ONIONSKIN_REPLY_LEN); + tt_int_op(0, ==, created_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATED, ==, cc.cell_type); + tt_int_op(TAP_ONIONSKIN_REPLY_LEN, ==, cc.handshake_len); + test_memeq(cc.reply, b, TAP_ONIONSKIN_REPLY_LEN + 10); + tt_int_op(0, ==, created_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + + /* A good CREATED_FAST cell */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, CREATED_FAST_LEN); + cell.command = CELL_CREATED_FAST; + memcpy(cell.payload, b, CREATED_FAST_LEN); + tt_int_op(0, ==, created_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATED_FAST, ==, cc.cell_type); + tt_int_op(CREATED_FAST_LEN, ==, cc.handshake_len); + test_memeq(cc.reply, b, CREATED_FAST_LEN + 10); + tt_int_op(0, ==, created_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + + /* A good CREATED2 cell with short reply */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, 64); + cell.command = CELL_CREATED2; + memcpy(cell.payload, "\x00\x40", 2); + memcpy(cell.payload+2, b, 64); + tt_int_op(0, ==, created_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATED2, ==, cc.cell_type); + tt_int_op(64, ==, cc.handshake_len); + test_memeq(cc.reply, b, 80); + tt_int_op(0, ==, created_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + + /* A good CREATED2 cell with maximal reply */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, 496); + cell.command = CELL_CREATED2; + memcpy(cell.payload, "\x01\xF0", 2); + memcpy(cell.payload+2, b, 496); + tt_int_op(0, ==, created_cell_parse(&cc, &cell)); + tt_int_op(CELL_CREATED2, ==, cc.cell_type); + tt_int_op(496, ==, cc.handshake_len); + test_memeq(cc.reply, b, 496); + tt_int_op(0, ==, created_cell_format(&cell2, &cc)); + tt_int_op(cell.command, ==, cell2.command); + test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE); + + /* Bogus CREATED2 cell: too long! */ + memset(&cell, 0, sizeof(cell)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, 496); + cell.command = CELL_CREATED2; + memcpy(cell.payload, "\x01\xF1", 2); + tt_int_op(-1, ==, created_cell_parse(&cc, &cell)); + + /* Unformattable CREATED2 cell: too long! */ + cc.handshake_len = 497; + tt_int_op(-1, ==, created_cell_format(&cell2, &cc)); + + done: + ; +} + +static void +test_cfmt_extend_cells(void *arg) +{ + cell_t cell; + uint8_t b[512]; + extend_cell_t ec; + create_cell_t *cc = &ec.create_cell; + uint8_t p[RELAY_PAYLOAD_SIZE]; + uint8_t p2[RELAY_PAYLOAD_SIZE]; + uint8_t p2_cmd; + uint16_t p2_len; + char *mem_op_hex_tmp = NULL; + + (void) arg; + + /* Let's start with a simple EXTEND cell. */ + memset(p, 0, sizeof(p)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); + memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */ + memcpy(p+6,b,TAP_ONIONSKIN_CHALLENGE_LEN); + memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20); + tt_int_op(0, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND, + p, 26+TAP_ONIONSKIN_CHALLENGE_LEN)); + tt_int_op(RELAY_COMMAND_EXTEND, ==, ec.cell_type); + tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr)); + tt_int_op(258, ==, ec.orport_ipv4.port); + tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr)); + test_memeq(ec.node_id, "electroencephalogram", 20); + tt_int_op(cc->cell_type, ==, CELL_CREATE); + tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_TAP); + tt_int_op(cc->handshake_len, ==, TAP_ONIONSKIN_CHALLENGE_LEN); + test_memeq(cc->onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN+20); + tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); + tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND); + tt_int_op(p2_len, ==, 26+TAP_ONIONSKIN_CHALLENGE_LEN); + test_memeq(p2, p, RELAY_PAYLOAD_SIZE); + + /* Let's do an ntor stuffed in a legacy EXTEND cell */ + memset(p, 0, sizeof(p)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); + memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */ + memcpy(p+6,"ntorNTORntorNTOR", 16); + memcpy(p+22, b, NTOR_ONIONSKIN_LEN); + memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20); + tt_int_op(0, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND, + p, 26+TAP_ONIONSKIN_CHALLENGE_LEN)); + tt_int_op(RELAY_COMMAND_EXTEND, ==, ec.cell_type); + tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr)); + tt_int_op(258, ==, ec.orport_ipv4.port); + tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr)); + test_memeq(ec.node_id, "electroencephalogram", 20); + tt_int_op(cc->cell_type, ==, CELL_CREATE2); + tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_NTOR); + tt_int_op(cc->handshake_len, ==, NTOR_ONIONSKIN_LEN); + test_memeq(cc->onionskin, b, NTOR_ONIONSKIN_LEN+20); + tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); + tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND); + tt_int_op(p2_len, ==, 26+TAP_ONIONSKIN_CHALLENGE_LEN); + test_memeq(p2, p, RELAY_PAYLOAD_SIZE); + tt_int_op(0, ==, create_cell_format_relayed(&cell, cc)); + + /* Now let's do a minimal ntor EXTEND2 cell. */ + memset(&ec, 0xff, sizeof(ec)); + memset(p, 0, sizeof(p)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); + /* 2 items; one 18.244.0.1:61681 */ + memcpy(p, "\x02\x00\x06\x12\xf4\x00\x01\xf0\xf1", 9); + /* The other is a digest. */ + memcpy(p+9, "\x02\x14" "anarchoindividualist", 22); + /* Prep for the handshake: type and length */ + memcpy(p+31, "\x00\x02\x00\x54", 4); + memcpy(p+35, b, NTOR_ONIONSKIN_LEN); + tt_int_op(0, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, 35+NTOR_ONIONSKIN_LEN)); + tt_int_op(RELAY_COMMAND_EXTEND2, ==, ec.cell_type); + tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr)); + tt_int_op(61681, ==, ec.orport_ipv4.port); + tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr)); + test_memeq(ec.node_id, "anarchoindividualist", 20); + tt_int_op(cc->cell_type, ==, CELL_CREATE2); + tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_NTOR); + tt_int_op(cc->handshake_len, ==, NTOR_ONIONSKIN_LEN); + test_memeq(cc->onionskin, b, NTOR_ONIONSKIN_LEN+20); + tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); + tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND2); + tt_int_op(p2_len, ==, 35+NTOR_ONIONSKIN_LEN); + test_memeq(p2, p, RELAY_PAYLOAD_SIZE); + + /* Now let's do a fanciful EXTEND2 cell. */ + memset(&ec, 0xff, sizeof(ec)); + memset(p, 0, sizeof(p)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, 99); + /* 4 items; one 18 244 0 1 61681 */ + memcpy(p, "\x04\x00\x06\x12\xf4\x00\x01\xf0\xf1", 9); + /* One is a digest. */ + memcpy(p+9, "\x02\x14" "anthropomorphization", 22); + /* One is an ipv6 address */ + memcpy(p+31, "\x01\x12\x20\x02\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\xf0\xc5\x1e\x11\x12", 20); + /* One is the Konami code. */ + memcpy(p+51, "\xf0\x20upupdowndownleftrightleftrightba", 34); + /* Prep for the handshake: weird type and length */ + memcpy(p+85, "\x01\x05\x00\x63", 4); + memcpy(p+89, b, 99); + tt_int_op(0, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, p, 89+99)); + tt_int_op(RELAY_COMMAND_EXTEND2, ==, ec.cell_type); + tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr)); + tt_int_op(61681, ==, ec.orport_ipv4.port); + tt_str_op("2002::f0:c51e", ==, fmt_addr(&ec.orport_ipv6.addr)); + tt_int_op(4370, ==, ec.orport_ipv6.port); + test_memeq(ec.node_id, "anthropomorphization", 20); + tt_int_op(cc->cell_type, ==, CELL_CREATE2); + tt_int_op(cc->handshake_type, ==, 0x105); + tt_int_op(cc->handshake_len, ==, 99); + test_memeq(cc->onionskin, b, 99+20); + tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); + tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND2); + /* We'll generate it minus the IPv6 address and minus the konami code */ + tt_int_op(p2_len, ==, 89+99-34-20); + test_memeq_hex(p2, + /* Two items: one that same darn IP address. */ + "02000612F40001F0F1" + /* The next is a digest : anthropomorphization */ + "0214616e7468726f706f6d6f727068697a6174696f6e" + /* Now the handshake prologue */ + "01050063"); + test_memeq(p2+1+8+22+4, b, 99+20); + tt_int_op(0, ==, create_cell_format_relayed(&cell, cc)); + + /* == Now try parsing some junk */ + + /* Try a too-long handshake */ + memset(p, 0, sizeof(p)); + memcpy(p, "\x02\x00\x06\x12\xf4\x00\x01\xf0\xf1", 9); + memcpy(p+9, "\x02\x14" "anarchoindividualist", 22); + memcpy(p+31, "\xff\xff\x01\xd0", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + + /* Try two identities. */ + memset(p, 0, sizeof(p)); + memcpy(p, "\x03\x00\x06\x12\xf4\x00\x01\xf0\xf1", 9); + memcpy(p+9, "\x02\x14" "anarchoindividualist", 22); + memcpy(p+31, "\x02\x14" "autodepolymerization", 22); + memcpy(p+53, "\xff\xff\x00\x10", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + + /* No identities. */ + memset(p, 0, sizeof(p)); + memcpy(p, "\x01\x00\x06\x12\xf4\x00\x01\xf0\xf1", 9); + memcpy(p+53, "\xff\xff\x00\x10", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + + /* Try a bad IPv4 address (too long, too short)*/ + memset(p, 0, sizeof(p)); + memcpy(p, "\x02\x00\x07\x12\xf4\x00\x01\xf0\xf1\xff", 10); + memcpy(p+10, "\x02\x14" "anarchoindividualist", 22); + memcpy(p+32, "\xff\xff\x00\x10", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + memset(p, 0, sizeof(p)); + memcpy(p, "\x02\x00\x05\x12\xf4\x00\x01\xf0", 8); + memcpy(p+8, "\x02\x14" "anarchoindividualist", 22); + memcpy(p+30, "\xff\xff\x00\x10", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + + /* IPv6 address (too long, too short, no IPv4)*/ + memset(p, 0, sizeof(p)); + memcpy(p, "\x03\x00\x06\x12\xf4\x00\x01\xf0\xf1", 9); + memcpy(p+9, "\x02\x14" "anarchoindividualist", 22); + memcpy(p+31, "\x01\x13" "xxxxxxxxxxxxxxxxYYZ", 19); + memcpy(p+50, "\xff\xff\x00\x20", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + memset(p, 0, sizeof(p)); + memcpy(p, "\x03\x00\x06\x12\xf4\x00\x01\xf0\xf1", 9); + memcpy(p+9, "\x02\x14" "anarchoindividualist", 22); + memcpy(p+31, "\x01\x11" "xxxxxxxxxxxxxxxxY", 17); + memcpy(p+48, "\xff\xff\x00\x20", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + memset(p, 0, sizeof(p)); + memcpy(p, "\x02", 1); + memcpy(p+1, "\x02\x14" "anarchoindividualist", 22); + memcpy(p+23, "\x01\x12" "xxxxxxxxxxxxxxxxYY", 18); + memcpy(p+41, "\xff\xff\x00\x20", 4); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + + /* Running out of space in specifiers */ + memset(p,0,sizeof(p)); + memcpy(p, "\x05\x0a\xff", 3); + memcpy(p+3+255, "\x0a\xff", 2); + tt_int_op(-1, ==, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, + p, sizeof(p))); + + /* Fuzz, because why not. */ + memset(&ec, 0xff, sizeof(ec)); + { + int i; + memset(p, 0, sizeof(p)); + for (i = 0; i < 10000; ++i) { + int n = crypto_rand_int(sizeof(p)); + crypto_rand((char *)p, n); + extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2, p, n); + } + } + + done: + tor_free(mem_op_hex_tmp); +} + +static void +test_cfmt_extended_cells(void *arg) +{ + uint8_t b[512]; + extended_cell_t ec; + created_cell_t *cc = &ec.created_cell; + uint8_t p[RELAY_PAYLOAD_SIZE]; + uint8_t p2[RELAY_PAYLOAD_SIZE]; + uint8_t p2_cmd; + uint16_t p2_len; + char *mem_op_hex_tmp = NULL; + + (void) arg; + + /* Try a regular EXTENDED cell. */ + memset(&ec, 0xff, sizeof(ec)); + memset(p, 0, sizeof(p)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN); + memcpy(p,b,TAP_ONIONSKIN_REPLY_LEN); + tt_int_op(0, ==, extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED, p, + TAP_ONIONSKIN_REPLY_LEN)); + tt_int_op(RELAY_COMMAND_EXTENDED, ==, ec.cell_type); + tt_int_op(cc->cell_type, ==, CELL_CREATED); + tt_int_op(cc->handshake_len, ==, TAP_ONIONSKIN_REPLY_LEN); + test_memeq(cc->reply, b, TAP_ONIONSKIN_REPLY_LEN); + tt_int_op(0, ==, extended_cell_format(&p2_cmd, &p2_len, p2, &ec)); + tt_int_op(RELAY_COMMAND_EXTENDED, ==, p2_cmd); + tt_int_op(TAP_ONIONSKIN_REPLY_LEN, ==, p2_len); + test_memeq(p2, p, sizeof(p2)); + + /* Try an EXTENDED2 cell */ + memset(&ec, 0xff, sizeof(ec)); + memset(p, 0, sizeof(p)); + memset(b, 0, sizeof(b)); + crypto_rand((char*)b, 42); + memcpy(p,"\x00\x2a",2); + memcpy(p+2,b,42); + tt_int_op(0, ==, extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED2, p, 2+42)); + tt_int_op(RELAY_COMMAND_EXTENDED2, ==, ec.cell_type); + tt_int_op(cc->cell_type, ==, CELL_CREATED2); + tt_int_op(cc->handshake_len, ==, 42); + test_memeq(cc->reply, b, 42+10); + tt_int_op(0, ==, extended_cell_format(&p2_cmd, &p2_len, p2, &ec)); + tt_int_op(RELAY_COMMAND_EXTENDED2, ==, p2_cmd); + tt_int_op(2+42, ==, p2_len); + test_memeq(p2, p, sizeof(p2)); + + /* Try an almost-too-long EXTENDED2 cell */ + memcpy(p, "\x01\xf0", 2); + tt_int_op(0, ==, + extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED2, p, sizeof(p))); + + /* Now try a too-long extended2 cell. That's the only misparse I can think + * of. */ + memcpy(p, "\x01\xf1", 2); + tt_int_op(-1, ==, + extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED2, p, sizeof(p))); + + done: + tor_free(mem_op_hex_tmp); +} + +#define TEST(name, flags) \ + { #name, test_cfmt_ ## name, flags, 0, NULL } + +struct testcase_t cell_format_tests[] = { + TEST(relay_header, 0), + TEST(begin_cells, 0), + TEST(connected_cells, 0), + TEST(create_cells, 0), + TEST(created_cells, 0), + TEST(extend_cells, 0), + TEST(extended_cells, 0), + END_OF_TESTCASES +}; + diff --git a/src/test/test_config.c b/src/test/test_config.c index ff251a24d8..e20fe73295 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -1,11 +1,13 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #include "or.h" +#include "addressmap.h" #include "config.h" +#include "confparse.h" #include "connection_edge.h" #include "test.h" @@ -40,6 +42,11 @@ test_config_addressmap(void *arg) config_get_lines(buf, &(get_options_mutable()->AddressMap), 0); config_register_addressmaps(get_options()); +/* Use old interface for now, so we don't need to rewrite the unit tests */ +#define addressmap_rewrite(a,s,eo,ao) \ + addressmap_rewrite((a),(s),AMR_FLAG_USE_IPV4_DNS|AMR_FLAG_USE_IPV6_DNS, \ + (eo),(ao)) + /* MapAddress .invalidwildcard.com .torserver.exit - no match */ strlcpy(address, "www.invalidwildcard.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); @@ -156,6 +163,8 @@ test_config_addressmap(void *arg) strlcpy(address, "www.torproject.org", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); +#undef addressmap_rewrite + done: ; } diff --git a/src/test/test_containers.c b/src/test/test_containers.c index 45898df4eb..005e102e25 100644 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@ -1,16 +1,17 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #include "or.h" +#include "fp_pair.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) +compare_strs_(const void **a, const void **b) { const char *s1 = *a, *s2 = *b; return strcmp(s1, s2); @@ -28,7 +29,7 @@ compare_strs_for_bsearch_(const void *a, const void **b) /** 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) +compare_without_first_ch_(const void *a, const void **b) { const char *s1 = a, *s2 = *b; return strcasecmp(s1+1, s2); @@ -66,8 +67,8 @@ test_container_smartlist_basic(void) test_eq(4, smartlist_len(sl)); /* test isin. */ - test_assert(smartlist_isin(sl, (void*)3)); - test_assert(!smartlist_isin(sl, (void*)99)); + test_assert(smartlist_contains(sl, (void*)3)); + test_assert(!smartlist_contains(sl, (void*)99)); done: smartlist_free(sl); @@ -185,7 +186,7 @@ test_container_smartlist_strings(void) /* 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); + 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); @@ -195,37 +196,37 @@ test_container_smartlist_strings(void) 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_assert(smartlist_contains_string(sl, "and")); + test_assert(smartlist_contains_string(sl, "router")); + test_assert(smartlist_contains_string(sl, "by")); + test_assert(smartlist_contains_string(sl, "nickm")); + test_assert(smartlist_contains_string(sl, "onion")); + test_assert(smartlist_contains_string(sl, "arma")); + test_assert(smartlist_contains_string(sl, "the")); /* Test bsearch. */ - smartlist_sort(sl, _compare_strs); + 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)); + 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; smartlist_t *tmp = NULL; - test_eq(0, smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&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(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(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(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(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(7, smartlist_bsearch_idx(sl," zzzz",compare_without_first_ch_,&f)); test_eq(f, 0); /* Test trivial cases for list of length 0 or 1 */ @@ -266,25 +267,25 @@ test_container_smartlist_strings(void) SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); cp_alloc = smartlist_pop_last(sl); - test_eq(cp_alloc, NULL); + test_eq_ptr(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); + 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 contains_string, contains_string_case and contains_int_as_string */ + test_assert(smartlist_contains_string(sl, "noon")); + test_assert(!smartlist_contains_string(sl, "noonoon")); + test_assert(smartlist_contains_string_case(sl, "nOOn")); + test_assert(!smartlist_contains_string_case(sl, "nooNooN")); + test_assert(smartlist_contains_int_as_string(sl, 50)); + test_assert(!smartlist_contains_int_as_string(sl, 60)); /* Test smartlist_choose */ { @@ -292,12 +293,12 @@ test_container_smartlist_strings(void) int allsame = 1; int allin = 1; void *first = smartlist_choose(sl); - test_assert(smartlist_isin(sl, first)); + test_assert(smartlist_contains(sl, first)); for (i = 0; i < 100; ++i) { void *second = smartlist_choose(sl); if (second != first) allsame = 0; - if (!smartlist_isin(sl, second)) + if (!smartlist_contains(sl, second)) allin = 0; } test_assert(!allsame); @@ -365,15 +366,15 @@ test_container_smartlist_overlap(void) 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)); + test_assert(smartlist_contains(sl, (void*)3)); + test_assert(smartlist_contains(sl, (void*)5)); + test_assert(smartlist_contains(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)); + test_assert(smartlist_contains(sl, (void*)2)); done: smartlist_free(odds); @@ -389,14 +390,14 @@ test_container_smartlist_digests(void) { smartlist_t *sl = smartlist_new(); - /* digest_isin. */ + /* contains_digest */ 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")); + test_eq(0, smartlist_contains_digest(NULL, "AAAAAAAAAAAAAAAAAAAA")); + test_assert(smartlist_contains_digest(sl, "AAAAAAAAAAAAAAAAAAAA")); + test_assert(smartlist_contains_digest(sl, "\00090AAB2AAAAaasdAAAAA")); + test_eq(0, smartlist_contains_digest(sl, "\00090AAB2AAABaasdAAAAA")); /* sort digests */ smartlist_sort_digests(sl); @@ -445,11 +446,11 @@ test_container_smartlist_join(void) } SMARTLIST_FOREACH_JOIN_END(cp1, cp2); SMARTLIST_FOREACH(sl3, const char *, cp, - test_assert(smartlist_isin(sl2, cp) && - !smartlist_string_isin(sl, cp))); + test_assert(smartlist_contains(sl2, cp) && + !smartlist_contains_string(sl, cp))); SMARTLIST_FOREACH(sl4, const char *, cp, - test_assert(smartlist_isin(sl, cp) && - smartlist_string_isin(sl2, cp))); + test_assert(smartlist_contains(sl, cp) && + smartlist_contains_string(sl2, cp))); joined = smartlist_join_strings(sl3, ",", 0, NULL); test_streq(joined, "Anemias,Anemias,Crossbowmen,Work"); tor_free(joined); @@ -528,18 +529,18 @@ test_container_digestset(void) } set = digestset_new(1000); SMARTLIST_FOREACH(included, const char *, cp, - if (digestset_isin(set, cp)) + if (digestset_contains(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)) + if (!digestset_contains(set, cp)) ok = 0); test_assert(ok); for (i = 0; i < 1000; ++i) { crypto_rand(d, DIGEST_LEN); - if (digestset_isin(set, d)) + if (digestset_contains(set, d)) ++false_positives; } test_assert(false_positives < 50); /* Should be far lower. */ @@ -558,7 +559,7 @@ typedef struct 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) +compare_strings_for_pqueue_(const void *p1, const void *p2) { const pq_entry_t *e1=p1, *e2=p2; return strcmp(e1->val, e2->val); @@ -588,7 +589,7 @@ test_container_pqueue(void) #define OK() smartlist_pqueue_assert_ok(sl, cmp, offset) - cmp = _compare_strings_for_pqueue; + 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); @@ -677,12 +678,12 @@ test_container_strmap(void) test_eq(strmap_size(map), 0); test_assert(strmap_isempty(map)); v = strmap_set(map, "K1", (void*)99); - test_eq(v, NULL); + test_eq_ptr(v, NULL); test_assert(!strmap_isempty(map)); v = strmap_set(map, "K2", (void*)101); - test_eq(v, NULL); + test_eq_ptr(v, NULL); v = strmap_set(map, "K1", (void*)100); - test_eq(v, (void*)99); + test_eq_ptr(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); @@ -782,6 +783,132 @@ test_container_order_functions(void) ; } +static void +test_di_map(void *arg) +{ + di_digest256_map_t *map = NULL; + const uint8_t key1[] = "In view of the fact that it was "; + const uint8_t key2[] = "superficially convincing, being "; + const uint8_t key3[] = "properly enciphered in a one-tim"; + const uint8_t key4[] = "e cipher scheduled for use today"; + char *v1 = tor_strdup(", it came close to causing a disaster..."); + char *v2 = tor_strdup("I regret to have to advise you that the mission"); + char *v3 = tor_strdup("was actually initiated..."); + /* -- John Brunner, _The Shockwave Rider_ */ + + (void)arg; + + /* Try searching on an empty map. */ + tt_ptr_op(NULL, ==, dimap_search(map, key1, NULL)); + tt_ptr_op(NULL, ==, dimap_search(map, key2, NULL)); + tt_ptr_op(v3, ==, dimap_search(map, key2, v3)); + dimap_free(map, NULL); + map = NULL; + + /* Add a single entry. */ + dimap_add_entry(&map, key1, v1); + tt_ptr_op(NULL, ==, dimap_search(map, key2, NULL)); + tt_ptr_op(v3, ==, dimap_search(map, key2, v3)); + tt_ptr_op(v1, ==, dimap_search(map, key1, NULL)); + + /* Now try it with three entries in the map. */ + dimap_add_entry(&map, key2, v2); + dimap_add_entry(&map, key3, v3); + tt_ptr_op(v1, ==, dimap_search(map, key1, NULL)); + tt_ptr_op(v2, ==, dimap_search(map, key2, NULL)); + tt_ptr_op(v3, ==, dimap_search(map, key3, NULL)); + tt_ptr_op(NULL, ==, dimap_search(map, key4, NULL)); + tt_ptr_op(v1, ==, dimap_search(map, key4, v1)); + + done: + tor_free(v1); + tor_free(v2); + tor_free(v3); + dimap_free(map, NULL); +} + +/** Run unit tests for fp_pair-to-void* map functions */ +static void +test_container_fp_pair_map(void) +{ + fp_pair_map_t *map; + fp_pair_t fp1, fp2, fp3, fp4, fp5, fp6; + void *v; + fp_pair_map_iter_t *iter; + fp_pair_t k; + + map = fp_pair_map_new(); + test_assert(map); + test_eq(fp_pair_map_size(map), 0); + test_assert(fp_pair_map_isempty(map)); + + memset(fp1.first, 0x11, DIGEST_LEN); + memset(fp1.second, 0x12, DIGEST_LEN); + memset(fp2.first, 0x21, DIGEST_LEN); + memset(fp2.second, 0x22, DIGEST_LEN); + memset(fp3.first, 0x31, DIGEST_LEN); + memset(fp3.second, 0x32, DIGEST_LEN); + memset(fp4.first, 0x41, DIGEST_LEN); + memset(fp4.second, 0x42, DIGEST_LEN); + memset(fp5.first, 0x51, DIGEST_LEN); + memset(fp5.second, 0x52, DIGEST_LEN); + memset(fp6.first, 0x61, DIGEST_LEN); + memset(fp6.second, 0x62, DIGEST_LEN); + + v = fp_pair_map_set(map, &fp1, (void*)99); + test_eq(v, NULL); + test_assert(!fp_pair_map_isempty(map)); + v = fp_pair_map_set(map, &fp2, (void*)101); + test_eq(v, NULL); + v = fp_pair_map_set(map, &fp1, (void*)100); + test_eq(v, (void*)99); + test_eq_ptr(fp_pair_map_get(map, &fp1), (void*)100); + test_eq_ptr(fp_pair_map_get(map, &fp2), (void*)101); + test_eq_ptr(fp_pair_map_get(map, &fp3), NULL); + fp_pair_map_assert_ok(map); + + v = fp_pair_map_remove(map, &fp2); + fp_pair_map_assert_ok(map); + test_eq_ptr(v, (void*)101); + test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); + test_eq_ptr(fp_pair_map_remove(map, &fp2), NULL); + + fp_pair_map_set(map, &fp2, (void*)101); + fp_pair_map_set(map, &fp3, (void*)102); + fp_pair_map_set(map, &fp4, (void*)103); + test_eq(fp_pair_map_size(map), 4); + fp_pair_map_assert_ok(map); + fp_pair_map_set(map, &fp5, (void*)104); + fp_pair_map_set(map, &fp6, (void*)105); + fp_pair_map_assert_ok(map); + + /* Test iterator. */ + iter = fp_pair_map_iter_init(map); + while (!fp_pair_map_iter_done(iter)) { + fp_pair_map_iter_get(iter, &k, &v); + test_eq_ptr(v, fp_pair_map_get(map, &k)); + + if (tor_memeq(&fp2, &k, sizeof(fp2))) { + iter = fp_pair_map_iter_next_rmv(map, iter); + } else { + iter = fp_pair_map_iter_next(map, iter); + } + } + + /* Make sure we removed fp2, but not the others. */ + test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); + test_eq_ptr(fp_pair_map_get(map, &fp5), (void*)104); + + fp_pair_map_assert_ok(map); + /* Clean up after ourselves. */ + fp_pair_map_free(map, NULL); + map = NULL; + + done: + if (map) + fp_pair_map_free(map, NULL); +} + #define CONTAINER_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_container_ ## name } @@ -796,6 +923,8 @@ struct testcase_t container_tests[] = { CONTAINER_LEGACY(strmap), CONTAINER_LEGACY(pqueue), CONTAINER_LEGACY(order_functions), + { "di_map", test_di_map, 0, NULL, NULL }, + CONTAINER_LEGACY(fp_pair_map), END_OF_TESTCASES }; diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 7f4347a41c..f92bfd673e 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -1,13 +1,18 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define CRYPTO_PRIVATE +#define CRYPTO_CURVE25519_PRIVATE #include "or.h" #include "test.h" #include "aes.h" +#include "util.h" +#ifdef CURVE25519_ENABLED +#include "crypto_curve25519.h" +#endif /** Run unit tests for Diffie-Hellman functionality. */ static void @@ -119,9 +124,9 @@ test_crypto_aes(void *arg) memset(data2, 0, 1024); memset(data3, 0, 1024); env1 = crypto_cipher_new(NULL); - test_neq(env1, 0); + test_neq_ptr(env1, 0); env2 = crypto_cipher_new(crypto_cipher_get_key(env1)); - test_neq(env2, 0); + test_neq_ptr(env2, 0); /* Try encrypting 512 chars. */ crypto_cipher_encrypt(env1, data2, data1, 512); @@ -152,7 +157,7 @@ test_crypto_aes(void *arg) memset(data3, 0, 1024); env2 = crypto_cipher_new(crypto_cipher_get_key(env1)); - test_neq(env2, 0); + test_neq_ptr(env2, NULL); for (j = 0; j < 1024-16; j += 17) { crypto_cipher_encrypt(env2, data3+j, data1+j, 17); } @@ -427,6 +432,11 @@ test_crypto_pk(void) test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size)); test_eq(0, crypto_pk_cmp_keys(pk1, pk2)); + /* comparison between keys and NULL */ + tt_int_op(crypto_pk_cmp_keys(NULL, pk1), <, 0); + tt_int_op(crypto_pk_cmp_keys(NULL, NULL), ==, 0); + tt_int_op(crypto_pk_cmp_keys(pk1, NULL), >, 0); + test_eq(128, crypto_pk_keysize(pk1)); test_eq(1024, crypto_pk_num_bits(pk1)); test_eq(128, crypto_pk_keysize(pk2)); @@ -626,22 +636,6 @@ test_crypto_formats(void) 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); @@ -736,7 +730,7 @@ test_crypto_aes_iv(void *arg) /* Decrypt with the wrong key. */ decrypted_size = crypto_cipher_decrypt_with_iv(key2, decrypted2, 4095, encrypted1, encrypted_size); - test_memneq(plain, decrypted2, encrypted_size); + test_memneq(plain, decrypted2, decrypted_size); /* Alter the initialization vector. */ encrypted1[0] += 42; decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 4095, @@ -827,6 +821,293 @@ test_crypto_base32_decode(void) ; } +static void +test_crypto_kdf_TAP(void *arg) +{ + uint8_t key_material[100]; + int r; + char *mem_op_hex_tmp = NULL; + + (void)arg; +#define EXPAND(s) \ + r = crypto_expand_key_material_TAP( \ + (const uint8_t*)(s), strlen(s), \ + key_material, 100) + + /* Test vectors generated with a little python script; feel free to write + * your own. */ + memset(key_material, 0, sizeof(key_material)); + EXPAND(""); + tt_int_op(r, ==, 0); + test_memeq_hex(key_material, + "5ba93c9db0cff93f52b521d7420e43f6eda2784fbf8b4530d8" + "d246dd74ac53a13471bba17941dff7c4ea21bb365bbeeaf5f2" + "c654883e56d11e43c44e9842926af7ca0a8cca12604f945414" + "f07b01e13da42c6cf1de3abfdea9b95f34687cbbe92b9a7383"); + + EXPAND("Tor"); + tt_int_op(r, ==, 0); + test_memeq_hex(key_material, + "776c6214fc647aaa5f683c737ee66ec44f03d0372e1cce6922" + "7950f236ddf1e329a7ce7c227903303f525a8c6662426e8034" + "870642a6dabbd41b5d97ec9bf2312ea729992f48f8ea2d0ba8" + "3f45dfda1a80bdc8b80de01b23e3e0ffae099b3e4ccf28dc28"); + + EXPAND("AN ALARMING ITEM TO FIND ON A MONTHLY AUTO-DEBIT NOTICE"); + tt_int_op(r, ==, 0); + test_memeq_hex(key_material, + "a340b5d126086c3ab29c2af4179196dbf95e1c72431419d331" + "4844bf8f6afb6098db952b95581fb6c33625709d6f4400b8e7" + "ace18a70579fad83c0982ef73f89395bcc39493ad53a685854" + "daf2ba9b78733b805d9a6824c907ee1dba5ac27a1e466d4d10"); + + done: + tor_free(mem_op_hex_tmp); + +#undef EXPAND +} + +static void +test_crypto_hkdf_sha256(void *arg) +{ + uint8_t key_material[100]; + const uint8_t salt[] = "ntor-curve25519-sha256-1:key_extract"; + const size_t salt_len = strlen((char*)salt); + const uint8_t m_expand[] = "ntor-curve25519-sha256-1:key_expand"; + const size_t m_expand_len = strlen((char*)m_expand); + int r; + char *mem_op_hex_tmp = NULL; + + (void)arg; + +#define EXPAND(s) \ + r = crypto_expand_key_material_rfc5869_sha256( \ + (const uint8_t*)(s), strlen(s), \ + salt, salt_len, \ + m_expand, m_expand_len, \ + key_material, 100) + + /* Test vectors generated with ntor_ref.py */ + memset(key_material, 0, sizeof(key_material)); + EXPAND(""); + tt_int_op(r, ==, 0); + test_memeq_hex(key_material, + "d3490ed48b12a48f9547861583573fe3f19aafe3f81dc7fc75" + "eeed96d741b3290f941576c1f9f0b2d463d1ec7ab2c6bf71cd" + "d7f826c6298c00dbfe6711635d7005f0269493edf6046cc7e7" + "dcf6abe0d20c77cf363e8ffe358927817a3d3e73712cee28d8"); + + EXPAND("Tor"); + tt_int_op(r, ==, 0); + test_memeq_hex(key_material, + "5521492a85139a8d9107a2d5c0d9c91610d0f95989975ebee6" + "c02a4f8d622a6cfdf9b7c7edd3832e2760ded1eac309b76f8d" + "66c4a3c4d6225429b3a016e3c3d45911152fc87bc2de9630c3" + "961be9fdb9f93197ea8e5977180801926d3321fa21513e59ac"); + + EXPAND("AN ALARMING ITEM TO FIND ON YOUR CREDIT-RATING STATEMENT"); + tt_int_op(r, ==, 0); + test_memeq_hex(key_material, + "a2aa9b50da7e481d30463adb8f233ff06e9571a0ca6ab6df0f" + "b206fa34e5bc78d063fc291501beec53b36e5a0e434561200c" + "5f8bd13e0f88b3459600b4dc21d69363e2895321c06184879d" + "94b18f078411be70b767c7fc40679a9440a0c95ea83a23efbf"); + + done: + tor_free(mem_op_hex_tmp); +#undef EXPAND +} + +#ifdef CURVE25519_ENABLED +static void +test_crypto_curve25519_impl(void *arg) +{ + /* adapted from curve25519_donna, which adapted it from test-curve25519 + version 20050915, by D. J. Bernstein, Public domain. */ + + const int randomize_high_bit = (arg != NULL); + +#ifdef SLOW_CURVE25519_TEST + const int loop_max=10000; + const char e1_expected[] = "4faf81190869fd742a33691b0e0824d5" + "7e0329f4dd2819f5f32d130f1296b500"; + const char e2k_expected[] = "05aec13f92286f3a781ccae98995a3b9" + "e0544770bc7de853b38f9100489e3e79"; + const char e1e2k_expected[] = "cd6e8269104eb5aaee886bd2071fba88" + "bd13861475516bc2cd2b6e005e805064"; +#else + const int loop_max=200; + const char e1_expected[] = "bc7112cde03f97ef7008cad1bdc56be3" + "c6a1037d74cceb3712e9206871dcf654"; + const char e2k_expected[] = "dd8fa254fb60bdb5142fe05b1f5de44d" + "8e3ee1a63c7d14274ea5d4c67f065467"; + const char e1e2k_expected[] = "7ddb98bd89025d2347776b33901b3e7e" + "c0ee98cb2257a4545c0cfb2ca3e1812b"; +#endif + + unsigned char e1k[32]; + unsigned char e2k[32]; + unsigned char e1e2k[32]; + unsigned char e2e1k[32]; + unsigned char e1[32] = {3}; + unsigned char e2[32] = {5}; + unsigned char k[32] = {9}; + int loop, i; + + char *mem_op_hex_tmp = NULL; + + for (loop = 0; loop < loop_max; ++loop) { + curve25519_impl(e1k,e1,k); + curve25519_impl(e2e1k,e2,e1k); + curve25519_impl(e2k,e2,k); + if (randomize_high_bit) { + /* We require that the high bit of the public key be ignored. So if + * we're doing this variant test, we randomize the high bit of e2k, and + * make sure that the handshake still works out the same as it would + * otherwise. */ + uint8_t byte; + crypto_rand((char*)&byte, 1); + e2k[31] |= (byte & 0x80); + } + curve25519_impl(e1e2k,e1,e2k); + test_memeq(e1e2k, e2e1k, 32); + if (loop == loop_max-1) { + break; + } + for (i = 0;i < 32;++i) e1[i] ^= e2k[i]; + for (i = 0;i < 32;++i) e2[i] ^= e1k[i]; + for (i = 0;i < 32;++i) k[i] ^= e1e2k[i]; + } + + test_memeq_hex(e1, e1_expected); + test_memeq_hex(e2k, e2k_expected); + test_memeq_hex(e1e2k, e1e2k_expected); + + done: + tor_free(mem_op_hex_tmp); +} + +static void +test_crypto_curve25519_wrappers(void *arg) +{ + curve25519_public_key_t pubkey1, pubkey2; + curve25519_secret_key_t seckey1, seckey2; + + uint8_t output1[CURVE25519_OUTPUT_LEN]; + uint8_t output2[CURVE25519_OUTPUT_LEN]; + (void)arg; + + /* Test a simple handshake, serializing and deserializing some stuff. */ + curve25519_secret_key_generate(&seckey1, 0); + curve25519_secret_key_generate(&seckey2, 1); + curve25519_public_key_generate(&pubkey1, &seckey1); + curve25519_public_key_generate(&pubkey2, &seckey2); + test_assert(curve25519_public_key_is_ok(&pubkey1)); + test_assert(curve25519_public_key_is_ok(&pubkey2)); + curve25519_handshake(output1, &seckey1, &pubkey2); + curve25519_handshake(output2, &seckey2, &pubkey1); + test_memeq(output1, output2, sizeof(output1)); + + done: + ; +} + +static void +test_crypto_curve25519_encode(void *arg) +{ + curve25519_secret_key_t seckey; + curve25519_public_key_t key1, key2, key3; + char buf[64]; + + (void)arg; + + curve25519_secret_key_generate(&seckey, 0); + curve25519_public_key_generate(&key1, &seckey); + tt_int_op(0, ==, curve25519_public_to_base64(buf, &key1)); + tt_int_op(CURVE25519_BASE64_PADDED_LEN, ==, strlen(buf)); + + tt_int_op(0, ==, curve25519_public_from_base64(&key2, buf)); + test_memeq(key1.public_key, key2.public_key, CURVE25519_PUBKEY_LEN); + + buf[CURVE25519_BASE64_PADDED_LEN - 1] = '\0'; + tt_int_op(CURVE25519_BASE64_PADDED_LEN-1, ==, strlen(buf)); + tt_int_op(0, ==, curve25519_public_from_base64(&key3, buf)); + test_memeq(key1.public_key, key3.public_key, CURVE25519_PUBKEY_LEN); + + /* Now try bogus parses. */ + strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$=", sizeof(buf)); + tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf)); + + strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", sizeof(buf)); + tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf)); + + strlcpy(buf, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", sizeof(buf)); + tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf)); + + done: + ; +} + +static void +test_crypto_curve25519_persist(void *arg) +{ + curve25519_keypair_t keypair, keypair2; + char *fname = tor_strdup(get_fname("curve25519_keypair")); + char *tag = NULL; + char *content = NULL; + const char *cp; + struct stat st; + size_t taglen; + + (void)arg; + + tt_int_op(0,==,curve25519_keypair_generate(&keypair, 0)); + + tt_int_op(0,==,curve25519_keypair_write_to_file(&keypair, fname, "testing")); + tt_int_op(0,==,curve25519_keypair_read_from_file(&keypair2, &tag, fname)); + tt_str_op(tag,==,"testing"); + tor_free(tag); + + test_memeq(keypair.pubkey.public_key, + keypair2.pubkey.public_key, + CURVE25519_PUBKEY_LEN); + test_memeq(keypair.seckey.secret_key, + keypair2.seckey.secret_key, + CURVE25519_SECKEY_LEN); + + content = read_file_to_str(fname, RFTS_BIN, &st); + tt_assert(content); + taglen = strlen("== c25519v1: testing =="); + tt_int_op(st.st_size, ==, 32+CURVE25519_PUBKEY_LEN+CURVE25519_SECKEY_LEN); + tt_assert(fast_memeq(content, "== c25519v1: testing ==", taglen)); + tt_assert(tor_mem_is_zero(content+taglen, 32-taglen)); + cp = content + 32; + test_memeq(keypair.seckey.secret_key, + cp, + CURVE25519_SECKEY_LEN); + cp += CURVE25519_SECKEY_LEN; + test_memeq(keypair.pubkey.public_key, + cp, + CURVE25519_SECKEY_LEN); + + tor_free(fname); + fname = tor_strdup(get_fname("bogus_keypair")); + + tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname)); + tor_free(tag); + + content[69] ^= 0xff; + tt_int_op(0, ==, write_bytes_to_file(fname, content, (size_t)st.st_size, 1)); + tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname)); + + done: + tor_free(fname); + tor_free(content); + tor_free(tag); +} + +#endif + static void * pass_data_setup_fn(const struct testcase_t *testcase) { @@ -858,6 +1139,15 @@ struct testcase_t crypto_tests[] = { { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"aes" }, { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"evp" }, CRYPTO_LEGACY(base32_decode), + { "kdf_TAP", test_crypto_kdf_TAP, 0, NULL, NULL }, + { "hkdf_sha256", test_crypto_hkdf_sha256, 0, NULL, NULL }, +#ifdef CURVE25519_ENABLED + { "curve25519_impl", test_crypto_curve25519_impl, 0, NULL, NULL }, + { "curve25519_impl_hibit", test_crypto_curve25519_impl, 0, NULL, (void*)"y"}, + { "curve25519_wrappers", test_crypto_curve25519_wrappers, 0, NULL, NULL }, + { "curve25519_encode", test_crypto_curve25519_encode, 0, NULL, NULL }, + { "curve25519_persist", test_crypto_curve25519_persist, 0, NULL, NULL }, +#endif END_OF_TESTCASES }; diff --git a/src/test/test_data.c b/src/test/test_data.c index de2f9f58eb..5f0f7cba01 100644 --- a/src/test/test_data.c +++ b/src/test/test_data.c @@ -1,6 +1,6 @@ /* Copyright 2001-2004 Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** First of 3 example authority certificates for unit testing. */ diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 83c612045b..56ac3b34c7 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -1,14 +1,18 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" +#include <math.h> + #define DIRSERV_PRIVATE #define DIRVOTE_PRIVATE #define ROUTER_PRIVATE +#define ROUTERLIST_PRIVATE #define HIBERNATE_PRIVATE #include "or.h" +#include "config.h" #include "directory.h" #include "dirserv.h" #include "dirvote.h" @@ -70,22 +74,24 @@ test_dir_nicknames(void) static void test_dir_formats(void) { - char buf[8192], buf2[8192]; + char *buf = NULL; + char 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; + char *pk1_str = NULL, *pk2_str = NULL, *cp; + size_t pk1_str_len, pk2_str_len; routerinfo_t *r1=NULL, *r2=NULL; - crypto_pk_t *pk1 = NULL, *pk2 = NULL, *pk3 = NULL; - routerinfo_t *rp1 = NULL; + crypto_pk_t *pk1 = NULL, *pk2 = NULL; + routerinfo_t *rp1 = NULL, *rp2 = NULL; addr_policy_t *ex1, *ex2; routerlist_t *dir1 = NULL, *dir2 = NULL; + or_options_t *options = get_options_mutable(); + const addr_policy_t *p; pk1 = pk_generate(0); pk2 = pk_generate(1); - pk3 = pk_generate(2); - test_assert(pk1 && pk2 && pk3); + test_assert(pk1 && pk2); hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE); @@ -125,31 +131,36 @@ test_dir_formats(void) r2->or_port = 9005; r2->dir_port = 0; r2->onion_pkey = crypto_pk_dup_key(pk2); + r2->onion_curve25519_pkey = tor_malloc_zero(sizeof(curve25519_public_key_t)); + curve25519_public_from_base64(r2->onion_curve25519_pkey, + "skyinAnvardNostarsNomoonNowindormistsorsnow"); r2->identity_pkey = crypto_pk_dup_key(pk1); r2->bandwidthrate = r2->bandwidthburst = r2->bandwidthcapacity = 3000; r2->exit_policy = smartlist_new(); - smartlist_add(r2->exit_policy, ex2); smartlist_add(r2->exit_policy, ex1); + smartlist_add(r2->exit_policy, ex2); 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); + /* XXXX025 router_dump_to_string should really take this from ri.*/ + options->ContactInfo = tor_strdup("Magri White " + "<magri@elsewhere.example.com>"); + buf = router_dump_router_to_string(r1, pk2); + tor_free(options->ContactInfo); + test_assert(buf); strlcpy(buf2, "router Magri 18.244.0.1 9000 0 9003\n" "or-address [1:2:3:4::]:9999\n" "platform Tor "VERSION" on ", sizeof(buf2)); strlcat(buf2, get_uname(), sizeof(buf2)); strlcat(buf2, "\n" - "opt protocols Link 1 2 Circuit 1\n" + "protocols Link 1 2 Circuit 1\n" "published 1970-01-01 00:00:00\n" - "opt fingerprint ", sizeof(buf2)); + "fingerprint ", sizeof(buf2)); test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1)); strlcat(buf2, fingerprint, sizeof(buf2)); strlcat(buf2, "\nuptime 0\n" @@ -161,14 +172,18 @@ test_dir_formats(void) 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, "hidden-service-dir\n", sizeof(buf2)); + strlcat(buf2, "contact Magri White <magri@elsewhere.example.com>\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); + tor_free(buf); - test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0); + buf = router_dump_router_to_string(r1, pk2); + test_assert(buf); cp = buf; rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); test_assert(rp1); @@ -182,35 +197,67 @@ test_dir_formats(void) 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)); + strlcpy(buf2, + "router Fred 1.1.1.1 9005 0 0\n" + "platform Tor "VERSION" on ", sizeof(buf2)); + strlcat(buf2, get_uname(), sizeof(buf2)); + strlcat(buf2, "\n" + "protocols Link 1 2 Circuit 1\n" + "published 1970-01-01 00:00:05\n" + "fingerprint ", sizeof(buf2)); + test_assert(!crypto_pk_get_fingerprint(pk1, fingerprint, 1)); + strlcat(buf2, fingerprint, sizeof(buf2)); + strlcat(buf2, "\nuptime 0\n" + "bandwidth 3000 3000 3000\n", sizeof(buf2)); + strlcat(buf2, "onion-key\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); + strlcat(buf2, "hidden-service-dir\n", sizeof(buf2)); + strlcat(buf2, "ntor-onion-key " + "skyinAnvardNostarsNomoonNowindormistsorsnow=\n", sizeof(buf2)); + strlcat(buf2, "accept *:80\nreject 18.0.0.0/8:24\n", sizeof(buf2)); + strlcat(buf2, "router-signature\n", sizeof(buf2)); + + buf = router_dump_router_to_string(r2, pk1); + buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same + * twice */ test_streq(buf, buf2); + tor_free(buf); + buf = router_dump_router_to_string(r2, pk1); cp = buf; - rp2 = router_parse_entry_from_string(&cp,1); + rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL); 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_streq(rp2->address, r2->address); + test_eq(rp2->or_port, r2->or_port); + test_eq(rp2->dir_port, r2->dir_port); + test_eq(rp2->bandwidthrate, r2->bandwidthrate); + test_eq(rp2->bandwidthburst, r2->bandwidthburst); + test_eq(rp2->bandwidthcapacity, r2->bandwidthcapacity); + test_memeq(rp2->onion_curve25519_pkey->public_key, + r2->onion_curve25519_pkey->public_key, + CURVE25519_PUBKEY_LEN); 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); + test_eq(smartlist_len(rp2->exit_policy), 2); + + p = smartlist_get(rp2->exit_policy, 0); + test_eq(p->policy_type, ADDR_POLICY_ACCEPT); + test_assert(tor_addr_is_null(&p->addr)); + test_eq(p->maskbits, 0); + test_eq(p->prt_min, 80); + test_eq(p->prt_max, 80); + + p = smartlist_get(rp2->exit_policy, 1); + test_eq(p->policy_type, ADDR_POLICY_REJECT); + test_assert(tor_addr_eq(&p->addr, &ex2->addr)); + test_eq(p->maskbits, 8); + test_eq(p->prt_min, 24); + test_eq(p->prt_max, 24); + +#if 0 /* Okay, now for the directories. */ { fingerprint_list = smartlist_new(); @@ -220,24 +267,6 @@ test_dir_formats(void) 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(); @@ -247,12 +276,11 @@ test_dir_formats(void) if (r2) routerinfo_free(r2); + tor_free(buf); tor_free(pk1_str); tor_free(pk2_str); - tor_free(pk3_str); if (pk1) crypto_pk_free(pk1); if (pk2) crypto_pk_free(pk2); - if (pk3) crypto_pk_free(pk3); if (rp1) routerinfo_free(rp1); tor_free(dir1); /* XXXX And more !*/ tor_free(dir2); /* And more !*/ @@ -422,10 +450,8 @@ test_dir_split_fps(void *testdata) "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); @@ -525,7 +551,7 @@ test_dir_split_fps(void *testdata) } static void -test_dir_measured_bw(void) +test_dir_measured_bw_kb(void) { measured_bw_line_t mbwl; int i; @@ -581,7 +607,7 @@ test_dir_measured_bw(void) 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(mbwl.bw_kb == 1024); test_assert(strcmp(mbwl.node_hex, "557365204145532d32353620696e73746561642e") == 0); } @@ -590,6 +616,83 @@ test_dir_measured_bw(void) return; } +#define MBWC_INIT_TIME 1000 + +/** Do the measured bandwidth cache unit test */ +static void +test_dir_measured_bw_kb_cache(void) +{ + /* Initial fake time_t for testing */ + time_t curr = MBWC_INIT_TIME; + /* Some measured_bw_line_ts */ + measured_bw_line_t mbwl[3]; + /* For receiving output on cache queries */ + long bw; + time_t as_of; + + /* First, clear the cache and assert that it's empty */ + dirserv_clear_measured_bw_cache(); + test_eq(dirserv_get_measured_bw_cache_size(), 0); + /* + * Set up test mbwls; none of the dirserv_cache_*() functions care about + * the node_hex field. + */ + memset(mbwl[0].node_id, 0x01, DIGEST_LEN); + mbwl[0].bw_kb = 20; + memset(mbwl[1].node_id, 0x02, DIGEST_LEN); + mbwl[1].bw_kb = 40; + memset(mbwl[2].node_id, 0x03, DIGEST_LEN); + mbwl[2].bw_kb = 80; + /* Try caching something */ + dirserv_cache_measured_bw(&(mbwl[0]), curr); + test_eq(dirserv_get_measured_bw_cache_size(), 1); + /* Okay, let's see if we can retrieve it */ + test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, &as_of)); + test_eq(bw, 20); + test_eq(as_of, MBWC_INIT_TIME); + /* Try retrieving it without some outputs */ + test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL, NULL)); + test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, NULL)); + test_eq(bw, 20); + test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL,&as_of)); + test_eq(as_of, MBWC_INIT_TIME); + /* Now expire it */ + curr += MAX_MEASUREMENT_AGE + 1; + dirserv_expire_measured_bw_cache(curr); + /* Check that the cache is empty */ + test_eq(dirserv_get_measured_bw_cache_size(), 0); + /* Check that we can't retrieve it */ + test_assert(!dirserv_query_measured_bw_cache_kb(mbwl[0].node_id, NULL,NULL)); + /* Try caching a few things now */ + dirserv_cache_measured_bw(&(mbwl[0]), curr); + test_eq(dirserv_get_measured_bw_cache_size(), 1); + curr += MAX_MEASUREMENT_AGE / 4; + dirserv_cache_measured_bw(&(mbwl[1]), curr); + test_eq(dirserv_get_measured_bw_cache_size(), 2); + curr += MAX_MEASUREMENT_AGE / 4; + dirserv_cache_measured_bw(&(mbwl[2]), curr); + test_eq(dirserv_get_measured_bw_cache_size(), 3); + curr += MAX_MEASUREMENT_AGE / 4 + 1; + /* Do an expire that's too soon to get any of them */ + dirserv_expire_measured_bw_cache(curr); + test_eq(dirserv_get_measured_bw_cache_size(), 3); + /* Push the oldest one off the cliff */ + curr += MAX_MEASUREMENT_AGE / 4; + dirserv_expire_measured_bw_cache(curr); + test_eq(dirserv_get_measured_bw_cache_size(), 2); + /* And another... */ + curr += MAX_MEASUREMENT_AGE / 4; + dirserv_expire_measured_bw_cache(curr); + test_eq(dirserv_get_measured_bw_cache_size(), 1); + /* This should empty it out again */ + curr += MAX_MEASUREMENT_AGE / 4; + dirserv_expire_measured_bw_cache(curr); + test_eq(dirserv_get_measured_bw_cache_size(), 0); + + done: + return; +} + static void test_dir_param_voting(void) { @@ -761,6 +864,17 @@ generate_ri_from_rs(const vote_routerstatus_t *vrs) strlen(r->cache_info.signed_descriptor_body); r->exit_policy = smartlist_new(); r->cache_info.published_on = ++published + time(NULL); + if (rs->has_bandwidth) { + /* + * Multiply by 1000 because the routerinfo_t and the routerstatus_t + * seem to use different units (*sigh*) and because we seem stuck on + * icky and perverse decimal kilobytes (*double sigh*) - see + * router_get_advertised_bandwidth_capped() of routerlist.c and + * routerstatus_format_entry() of dirserv.c. + */ + r->bandwidthrate = rs->bandwidth_kb * 1000; + r->bandwidthcapacity = rs->bandwidth_kb * 1000; + } return r; } @@ -781,15 +895,328 @@ get_detached_sigs(networkstatus_t *ns, networkstatus_t *ns2) return r; } -/** Run unit tests for generating and parsing V3 consensus networkstatus - * documents. */ +/** + * Generate a routerstatus for v3_networkstatus test + */ +static vote_routerstatus_t * +gen_routerstatus_for_v3ns(int idx, time_t now) +{ + vote_routerstatus_t *vrs=NULL; + routerstatus_t *rs; + tor_addr_t addr_ipv6; + + switch (idx) { + case 0: + /* Generate 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_flagged_running = 1; + break; + case 1: + /* Generate 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; + tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); + tor_addr_copy(&rs->ipv6_addr, &addr_ipv6); + rs->ipv6_orport = 4711; + rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running = + rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1; + break; + case 2: + /* Generate 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_flagged_running = rs->is_valid = rs->is_v2_dir = + rs->is_possible_guard = 1; + break; + case 3: + /* Generate 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 */ + break; + case 4: + /* No more for this test; return NULL */ + vrs = NULL; + break; + default: + /* Shouldn't happen */ + test_assert(0); + } + if (vrs) { + vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); + tor_asprintf(&vrs->microdesc->microdesc_hash_line, + "m 9,10,11,12,13,14,15,16,17 " + "sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n", + idx); + } + + done: + return vrs; +} + +/** Apply tweaks to the vote list for each voter */ +static int +vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now) +{ + vote_routerstatus_t *vrs; + const char *msg = NULL; + + test_assert(v); + (void)now; + + if (voter == 1) { + measured_bw_line_t mbw; + memset(mbw.node_id, 33, sizeof(mbw.node_id)); + mbw.bw_kb = 1024; + test_assert(measured_bw_line_apply(&mbw, + v->routerstatus_list) == 1); + } else if (voter == 2 || voter == 3) { + /* Monkey around with the list a bit */ + vrs = smartlist_get(v->routerstatus_list, 2); + smartlist_del_keeporder(v->routerstatus_list, 2); + tor_free(vrs->version); + tor_free(vrs); + vrs = smartlist_get(v->routerstatus_list, 0); + vrs->status.is_fast = 1; + + if (voter == 3) { + vrs = smartlist_get(v->routerstatus_list, 0); + smartlist_del_keeporder(v->routerstatus_list, 0); + tor_free(vrs->version); + tor_free(vrs); + vrs = smartlist_get(v->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); + } + } + + done: + return 0; +} + +/** + * Test a parsed vote_routerstatus_t for v3_networkstatus test + */ static void -test_dir_v3_networkstatus(void) +test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now) +{ + routerstatus_t *rs; + tor_addr_t addr_ipv6; + + test_assert(vrs); + rs = &(vrs->status); + test_assert(rs); + + /* Split out by digests to test */ + if (tor_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) && + (voter == 1)) { + /* Check the first routerstatus. */ + 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" + } else if (tor_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) && + (voter == 1 || voter == 2)) { + 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); + + if (voter == 1) { + /* Check the second routerstatus. */ + test_streq(vrs->version, "0.2.0.5"); + test_eq(rs->published_on, now-1000); + test_streq(rs->nickname, "router1"); + } + 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); + tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); + test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + test_eq(rs->ipv6_orport, 4711); + if (voter == 1) { + test_eq(vrs->flags, U64_LITERAL(254)); // all flags except "authority." + } else { + /* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) */ + test_eq(vrs->flags, U64_LITERAL(974)); + } + } else if (tor_memeq(rs->identity_digest, + "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33" + "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33", + DIGEST_LEN) && + (voter == 1 || voter == 2)) { + /* Check the measured bandwidth bits */ + test_assert(vrs->has_measured_bw && + vrs->measured_bw_kb == 1024); + } else { + /* + * Didn't expect this, but the old unit test only checked some of them, + * so don't assert. + */ + /* test_assert(0); */ + } + + done: + return; +} + +/** + * Test a consensus for v3_networkstatus_test + */ +static void +test_consensus_for_v3ns(networkstatus_t *con, time_t now) +{ + (void)now; + + test_assert(con); + 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. */ + + done: + return; +} + +/** + * Test a router list entry for v3_networkstatus test + */ +static void +test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now) +{ + tor_addr_t addr_ipv6; + + test_assert(rs); + + /* There should be two listed routers: one with identity 3, one with + * identity 5. */ + /* This one showed up in 2 digests. */ + if (tor_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->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); + /* (If it wasn't running it wouldn't be here) */ + test_assert(rs->is_flagged_running); + test_assert(!rs->is_v2_dir); + test_assert(!rs->is_valid); + test_assert(!rs->is_named); + /* XXXX check version */ + } else if (tor_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)) { + /* 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); + tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); + test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + test_eq(rs->ipv6_orport, 4711); + 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_flagged_running); + test_assert(rs->is_v2_dir); + test_assert(rs->is_valid); + test_assert(!rs->is_named); + /* XXXX check version */ + } else { + /* Weren't expecting this... */ + test_assert(0); + } + + done: + return; +} + +/** Run a unit tests for generating and parsing networkstatuses, with + * the supply test fns. */ +static void +test_a_networkstatus( + vote_routerstatus_t * (*vrs_gen)(int idx, time_t now), + int (*vote_tweaks)(networkstatus_t *v, int voter, time_t now), + void (*vrs_test)(vote_routerstatus_t *vrs, int voter, time_t now), + void (*consensus_test)(networkstatus_t *con, time_t now), + void (*rs_test)(routerstatus_t *rs, time_t now)) { authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL; crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL; crypto_pk_t *sign_skey_leg1=NULL; const char *msg=NULL; + /* + * Sum the non-zero returns from vote_tweaks() we've seen; if vote_tweaks() + * returns non-zero, it changed net_params and we should skip the tests for + * that later as they will fail. + */ + int params_tweaked = 0; time_t now = time(NULL); networkstatus_voter_info_t *voter; @@ -798,6 +1225,7 @@ test_dir_v3_networkstatus(void) *con_md=NULL; vote_routerstatus_t *vrs; routerstatus_t *rs; + int idx, n_rs, n_vrs; char *v1_text=NULL, *v2_text=NULL, *v3_text=NULL, *consensus_text=NULL, *cp; smartlist_t *votes = smartlist_new(); @@ -809,6 +1237,10 @@ test_dir_v3_networkstatus(void) networkstatus_t *con2=NULL, *con_md2=NULL, *con3=NULL, *con_md3=NULL; ns_detached_signatures_t *dsig1=NULL, *dsig2=NULL; + test_assert(vrs_gen); + test_assert(rs_test); + test_assert(vrs_test); + /* Parse certificates and keys. */ cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL); test_assert(cert1); @@ -866,69 +1298,18 @@ test_dir_v3_networkstatus(void) smartlist_split_string(vote->net_params, "circuitwindow=101 foo=990", NULL, 0, 0); vote->routerstatus_list = smartlist_new(); - /* 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_flagged_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_flagged_running = - rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1; - smartlist_add(vote->routerstatus_list, vrs); - test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); - - /* 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_flagged_running = rs->is_valid = rs->is_v2_dir = - rs->is_possible_guard = 1; - smartlist_add(vote->routerstatus_list, vrs); - test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0); - - /* 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); + /* add routerstatuses */ + idx = 0; + do { + vrs = vrs_gen(idx, now); + if (vrs) { + smartlist_add(vote->routerstatus_list, vrs); + test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), + &msg,0,0)>=0); + ++idx; + } + } while (vrs); + n_vrs = idx; /* dump the vote and try to parse it. */ v1_text = format_networkstatus_vote(sign_skey_1, vote); @@ -959,45 +1340,15 @@ test_dir_v3_networkstatus(void) 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." + test_eq(smartlist_len(v1->routerstatus_list), n_vrs); - { - 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); + if (vote_tweaks) params_tweaked += vote_tweaks(v1, 1, now); + + /* Check the routerstatuses. */ + for (idx = 0; idx < n_vrs; ++idx) { + vrs = smartlist_get(v1->routerstatus_list, idx); + test_assert(vrs); + vrs_test(vrs, 1, now); } /* Generate second vote. It disagrees on some of the times, @@ -1022,25 +1373,28 @@ test_dir_v3_networkstatus(void) 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. */ + + /* generate and parse v2. */ 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); + + if (vote_tweaks) params_tweaked += vote_tweaks(v2, 2, now); + /* 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)); + + /* Check the routerstatuses. */ + n_vrs = smartlist_len(v2->routerstatus_list); + for (idx = 0; idx < n_vrs; ++idx) { + vrs = smartlist_get(v2->routerstatus_list, idx); + test_assert(vrs); + vrs_test(vrs, 2, now); + } /* Generate the third vote. */ vote->published = now; @@ -1063,13 +1417,6 @@ test_dir_v3_networkstatus(void) 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); @@ -1077,6 +1424,8 @@ test_dir_v3_networkstatus(void) v3 = networkstatus_parse_vote_from_string(v3_text, NULL, NS_TYPE_VOTE); test_assert(v3); + if (vote_tweaks) params_tweaked += vote_tweaks(v3, 3, now); + /* Compute a consensus as voter 3. */ smartlist_add(votes, v3); smartlist_add(votes, v1); @@ -1119,9 +1468,12 @@ test_dir_v3_networkstatus(void) 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, "circuitwindow=80:foo=660"); - tor_free(cp); + if (!params_tweaked) { + /* Skip this one if vote_tweaks() messed with the param lists */ + cp = smartlist_join_strings(con->net_params, ":", 0, NULL); + test_streq(cp, "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. */ @@ -1136,49 +1488,15 @@ test_dir_v3_networkstatus(void) 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); - /* (If it wasn't running it wouldn't be here) */ - test_assert(rs->is_flagged_running); - test_assert(!rs->is_v2_dir); - test_assert(!rs->is_valid); - test_assert(!rs->is_named); - /* 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_flagged_running); - test_assert(rs->is_v2_dir); - test_assert(rs->is_valid); - test_assert(!rs->is_named); - /* XXXX check version */ + consensus_test(con, now); + + /* Check the routerstatuses. */ + n_rs = smartlist_len(con->routerstatus_list); + for (idx = 0; idx < n_rs; ++idx) { + rs = smartlist_get(con->routerstatus_list, idx); + test_assert(rs); + rs_test(rs, now); + } /* 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. */ @@ -1381,21 +1699,693 @@ test_dir_v3_networkstatus(void) ns_detached_signatures_free(dsig2); } +/** Run unit tests for generating and parsing V3 consensus networkstatus + * documents. */ +static void +test_dir_v3_networkstatus(void) +{ + test_a_networkstatus(gen_routerstatus_for_v3ns, + vote_tweaks_for_v3ns, + test_vrs_for_v3ns, + test_consensus_for_v3ns, + test_routerstatus_for_v3ns); +} + +static void +test_dir_scale_bw(void *testdata) +{ + double v[8] = { 2.0/3, + 7.0, + 1.0, + 3.0, + 1.0/5, + 1.0/7, + 12.0, + 24.0 }; + u64_dbl_t vals[8]; + uint64_t total; + int i; + + (void) testdata; + + for (i=0; i<8; ++i) + vals[i].dbl = v[i]; + + scale_array_elements_to_u64(vals, 8, &total); + + tt_int_op((int)total, ==, 48); + total = 0; + for (i=0; i<8; ++i) { + total += vals[i].u64; + } + tt_assert(total >= (U64_LITERAL(1)<<60)); + tt_assert(total <= (U64_LITERAL(1)<<62)); + + for (i=0; i<8; ++i) { + double ratio = ((double)vals[i].u64) / vals[2].u64; + tt_double_op(fabs(ratio - v[i]), <, .00001); + } + + done: + ; +} + +static void +test_dir_random_weighted(void *testdata) +{ + int histogram[10]; + uint64_t vals[10] = {3,1,2,4,6,0,7,5,8,9}, total=0; + u64_dbl_t inp[10]; + int i, choice; + const int n = 50000; + double max_sq_error; + (void) testdata; + + /* Try a ten-element array with values from 0 through 10. The values are + * in a scrambled order to make sure we don't depend on order. */ + memset(histogram,0,sizeof(histogram)); + for (i=0; i<10; ++i) { + inp[i].u64 = vals[i]; + total += vals[i]; + } + tt_int_op(total, ==, 45); + for (i=0; i<n; ++i) { + choice = choose_array_element_by_weight(inp, 10); + tt_int_op(choice, >=, 0); + tt_int_op(choice, <, 10); + histogram[choice]++; + } + + /* Now see if we chose things about frequently enough. */ + max_sq_error = 0; + for (i=0; i<10; ++i) { + int expected = (int)(n*vals[i]/total); + double frac_diff = 0, sq; + TT_BLATHER((" %d : %5d vs %5d\n", (int)vals[i], histogram[i], expected)); + if (expected) + frac_diff = (histogram[i] - expected) / ((double)expected); + else + tt_int_op(histogram[i], ==, 0); + + sq = frac_diff * frac_diff; + if (sq > max_sq_error) + max_sq_error = sq; + } + /* It should almost always be much much less than this. If you want to + * figure out the odds, please feel free. */ + tt_double_op(max_sq_error, <, .05); + + /* Now try a singleton; do we choose it? */ + for (i = 0; i < 100; ++i) { + choice = choose_array_element_by_weight(inp, 1); + tt_int_op(choice, ==, 0); + } + + /* Now try an array of zeros. We should choose randomly. */ + memset(histogram,0,sizeof(histogram)); + for (i = 0; i < 5; ++i) + inp[i].u64 = 0; + for (i = 0; i < n; ++i) { + choice = choose_array_element_by_weight(inp, 5); + tt_int_op(choice, >=, 0); + tt_int_op(choice, <, 5); + histogram[choice]++; + } + /* Now see if we chose things about frequently enough. */ + max_sq_error = 0; + for (i=0; i<5; ++i) { + int expected = n/5; + double frac_diff = 0, sq; + TT_BLATHER((" %d : %5d vs %5d\n", (int)vals[i], histogram[i], expected)); + frac_diff = (histogram[i] - expected) / ((double)expected); + sq = frac_diff * frac_diff; + if (sq > max_sq_error) + max_sq_error = sq; + } + /* It should almost always be much much less than this. If you want to + * figure out the odds, please feel free. */ + tt_double_op(max_sq_error, <, .05); + done: + ; +} + +/* Function pointers for test_dir_clip_unmeasured_bw_kb() */ + +static uint32_t alternate_clip_bw = 0; + +/** + * Generate a routerstatus for clip_unmeasured_bw_kb test; based on the + * v3_networkstatus ones. + */ +static vote_routerstatus_t * +gen_routerstatus_for_umbw(int idx, time_t now) +{ + vote_routerstatus_t *vrs = NULL; + routerstatus_t *rs; + tor_addr_t addr_ipv6; + uint32_t max_unmeasured_bw_kb = (alternate_clip_bw > 0) ? + alternate_clip_bw : DEFAULT_MAX_UNMEASURED_BW_KB; + + switch (idx) { + case 0: + /* Generate 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_flagged_running = 1; + /* + * This one has measured bandwidth below the clip cutoff, and + * so shouldn't be clipped; we'll have to test that it isn't + * later. + */ + vrs->has_measured_bw = 1; + rs->has_bandwidth = 1; + vrs->measured_bw_kb = rs->bandwidth_kb = max_unmeasured_bw_kb / 2; + break; + case 1: + /* Generate 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; + tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); + tor_addr_copy(&rs->ipv6_addr, &addr_ipv6); + rs->ipv6_orport = 4711; + rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running = + rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1; + /* + * This one has measured bandwidth above the clip cutoff, and + * so shouldn't be clipped; we'll have to test that it isn't + * later. + */ + vrs->has_measured_bw = 1; + rs->has_bandwidth = 1; + vrs->measured_bw_kb = rs->bandwidth_kb = 2 * max_unmeasured_bw_kb; + break; + case 2: + /* Generate 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, 0x33, 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_flagged_running = rs->is_valid = rs->is_v2_dir = + rs->is_possible_guard = 1; + /* + * This one has unmeasured bandwidth above the clip cutoff, and + * so should be clipped; we'll have to test that it isn't + * later. + */ + vrs->has_measured_bw = 0; + rs->has_bandwidth = 1; + vrs->measured_bw_kb = 0; + rs->bandwidth_kb = 2 * max_unmeasured_bw_kb; + break; + case 3: + /* Generate 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, 0x34, DIGEST_LEN); + memset(rs->descriptor_digest, 47, DIGEST_LEN); + rs->addr = 0xC0000203; + rs->or_port = 500; + rs->dir_port = 1999; + /* all flags but running cleared */ + rs->is_flagged_running = 1; + /* + * This one has unmeasured bandwidth below the clip cutoff, and + * so shouldn't be clipped; we'll have to test that it isn't + * later. + */ + vrs->has_measured_bw = 0; + rs->has_bandwidth = 1; + vrs->measured_bw_kb = 0; + rs->bandwidth_kb = max_unmeasured_bw_kb / 2; + break; + case 4: + /* No more for this test; return NULL */ + vrs = NULL; + break; + default: + /* Shouldn't happen */ + test_assert(0); + } + if (vrs) { + vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); + tor_asprintf(&vrs->microdesc->microdesc_hash_line, + "m 9,10,11,12,13,14,15,16,17 " + "sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n", + idx); + } + + done: + return vrs; +} + +/** Apply tweaks to the vote list for each voter; for the umbw test this is + * just adding the right consensus methods to let clipping happen */ +static int +vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now) +{ + char *maxbw_param = NULL; + int rv = 0; + + test_assert(v); + (void)voter; + (void)now; + + test_assert(v->supported_methods); + smartlist_clear(v->supported_methods); + /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */ + smartlist_split_string(v->supported_methods, + "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17", + NULL, 0, -1); + /* If we're using a non-default clip bandwidth, add it to net_params */ + if (alternate_clip_bw > 0) { + tor_asprintf(&maxbw_param, "maxunmeasuredbw=%u", alternate_clip_bw); + test_assert(maxbw_param); + if (maxbw_param) { + smartlist_add(v->net_params, maxbw_param); + rv = 1; + } + } + + done: + return rv; +} + +/** + * Test a parsed vote_routerstatus_t for umbw test. + */ +static void +test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now) +{ + routerstatus_t *rs; + tor_addr_t addr_ipv6; + uint32_t max_unmeasured_bw_kb = (alternate_clip_bw > 0) ? + alternate_clip_bw : DEFAULT_MAX_UNMEASURED_BW_KB; + + (void)voter; + test_assert(vrs); + rs = &(vrs->status); + test_assert(rs); + + /* Split out by digests to test */ + if (tor_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)) { + /* + * Check the first routerstatus - measured bandwidth below the clip + * cutoff. + */ + 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_assert(rs->has_bandwidth); + test_assert(vrs->has_measured_bw); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); + test_eq(vrs->measured_bw_kb, max_unmeasured_bw_kb / 2); + } else if (tor_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)) { + + /* + * Check the second routerstatus - measured bandwidth above the clip + * cutoff. + */ + 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); + tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); + test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + test_eq(rs->ipv6_orport, 4711); + test_assert(rs->has_bandwidth); + test_assert(vrs->has_measured_bw); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2); + test_eq(vrs->measured_bw_kb, max_unmeasured_bw_kb * 2); + } else if (tor_memeq(rs->identity_digest, + "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33" + "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33", + DIGEST_LEN)) { + /* + * Check the third routerstatus - unmeasured bandwidth above the clip + * cutoff; this one should be clipped later on in the consensus, but + * appears unclipped in the vote. + */ + test_assert(rs->has_bandwidth); + test_assert(!(vrs->has_measured_bw)); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2); + test_eq(vrs->measured_bw_kb, 0); + } else if (tor_memeq(rs->identity_digest, + "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34" + "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34", + DIGEST_LEN)) { + /* + * Check the fourth routerstatus - unmeasured bandwidth below the clip + * cutoff; this one should not be clipped. + */ + test_assert(rs->has_bandwidth); + test_assert(!(vrs->has_measured_bw)); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); + test_eq(vrs->measured_bw_kb, 0); + } else { + test_assert(0); + } + + done: + return; +} + +/** + * Test a consensus for v3_networkstatus_test + */ +static void +test_consensus_for_umbw(networkstatus_t *con, time_t now) +{ + (void)now; + + test_assert(con); + test_assert(!con->cert); + // test_assert(con->consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB); + test_assert(con->consensus_method >= 16); + test_eq(4, smartlist_len(con->routerstatus_list)); + /* There should be four listed routers; all voters saw the same in this */ + + done: + return; +} + +/** + * Test a router list entry for umbw test + */ +static void +test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) +{ + tor_addr_t addr_ipv6; + uint32_t max_unmeasured_bw_kb = (alternate_clip_bw > 0) ? + alternate_clip_bw : DEFAULT_MAX_UNMEASURED_BW_KB; + + test_assert(rs); + + /* There should be four listed routers, as constructed above */ + if (tor_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->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); + /* (If it wasn't running it wouldn't be here) */ + test_assert(rs->is_flagged_running); + test_assert(!rs->is_v2_dir); + test_assert(!rs->is_valid); + test_assert(!rs->is_named); + /* This one should have measured bandwidth below the clip cutoff */ + test_assert(rs->has_bandwidth); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); + test_assert(!(rs->bw_is_unmeasured)); + } else if (tor_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)) { + /* 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); + tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); + test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6)); + test_eq(rs->ipv6_orport, 4711); + 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_flagged_running); + test_assert(rs->is_v2_dir); + test_assert(rs->is_valid); + test_assert(!rs->is_named); + /* This one should have measured bandwidth above the clip cutoff */ + test_assert(rs->has_bandwidth); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2); + test_assert(!(rs->bw_is_unmeasured)); + } else if (tor_memeq(rs->identity_digest, + "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33" + "\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33", + DIGEST_LEN)) { + /* + * This one should have unmeasured bandwidth above the clip cutoff, + * and so should be clipped + */ + test_assert(rs->has_bandwidth); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb); + test_assert(rs->bw_is_unmeasured); + } else if (tor_memeq(rs->identity_digest, + "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34" + "\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34", + DIGEST_LEN)) { + /* + * This one should have unmeasured bandwidth below the clip cutoff, + * and so should not be clipped + */ + test_assert(rs->has_bandwidth); + test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2); + test_assert(rs->bw_is_unmeasured); + } else { + /* Weren't expecting this... */ + test_assert(0); + } + + done: + return; +} + +/** + * Compute a consensus involving clipping unmeasured bandwidth with consensus + * method 17; this uses the same test_a_networkstatus() function that the + * v3_networkstatus test uses. + */ + +static void +test_dir_clip_unmeasured_bw_kb(void) +{ + /* Run the test with the default clip bandwidth */ + alternate_clip_bw = 0; + test_a_networkstatus(gen_routerstatus_for_umbw, + vote_tweaks_for_umbw, + test_vrs_for_umbw, + test_consensus_for_umbw, + test_routerstatus_for_umbw); +} + +/** + * This version of test_dir_clip_unmeasured_bw_kb() uses a non-default choice + * of clip bandwidth. + */ + +static void +test_dir_clip_unmeasured_bw_kb_alt(void) +{ + /* + * Try a different one; this value is chosen so that the below-the-cutoff + * unmeasured nodes the test uses, at alternate_clip_bw / 2, will be above + * DEFAULT_MAX_UNMEASURED_BW_KB and if the consensus incorrectly uses that + * cutoff it will fail the test. + */ + alternate_clip_bw = 3 * DEFAULT_MAX_UNMEASURED_BW_KB; + test_a_networkstatus(gen_routerstatus_for_umbw, + vote_tweaks_for_umbw, + test_vrs_for_umbw, + test_consensus_for_umbw, + test_routerstatus_for_umbw); +} + +extern time_t time_of_process_start; /* from main.c */ + +static void +test_dir_v2_dir(void *arg) +{ + /* Runs in a forked process: acts like a v2 directory just enough to make and + * sign a v2 networkstatus opinion */ + + cached_dir_t *v2 = NULL; + or_options_t *options = get_options_mutable(); + crypto_pk_t *id_key = pk_generate(4); + (void) arg; + + options->ORPort_set = 1; /* So we believe we're a server. */ + options->DirPort_set = 1; + options->Address = tor_strdup("99.99.99.99"); + options->Nickname = tor_strdup("TestV2Auth"); + options->ContactInfo = tor_strdup("TestV2Auth <testv2auth@example.com>"); + { + /* Give it a DirPort */ + smartlist_t *ports = (smartlist_t *)get_configured_ports(); + port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t)); + port->type = CONN_TYPE_DIR_LISTENER; + port->port = 9999; + smartlist_add(ports, port); + } + set_server_identity_key(id_key); + set_client_identity_key(id_key); + + /* Add a router. */ + { + was_router_added_t wra; + const char *msg = NULL; + routerinfo_t *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 = time(NULL)-60; + r1->or_port = 9000; + r1->dir_port = 9003; + tor_addr_parse(&r1->ipv6_addr, "1:2:3:4::"); + r1->ipv6_orport = 9999; + r1->onion_pkey = pk_generate(1); + r1->identity_pkey = pk_generate(2); + r1->bandwidthrate = 1000; + r1->bandwidthburst = 5000; + r1->bandwidthcapacity = 10000; + r1->exit_policy = NULL; + r1->nickname = tor_strdup("Magri"); + r1->platform = tor_strdup("Tor 0.2.7.7-gamma"); + r1->cache_info.routerlist_index = -1; + r1->cache_info.signed_descriptor_body = + router_dump_router_to_string(r1, r1->identity_pkey); + r1->cache_info.signed_descriptor_len = + strlen(r1->cache_info.signed_descriptor_body); + wra = router_add_to_routerlist(r1, &msg, 0, 0); + tt_int_op(wra, ==, ROUTER_ADDED_SUCCESSFULLY); + } + + /* Prevent call of rep_hist_note_router_unreachable(). */ + time_of_process_start = time(NULL); + + /* Make a directory so there's somewhere to store the thing */ +#ifdef _WIN32 + mkdir(get_fname("cached-status")); +#else + mkdir(get_fname("cached-status"), 0700); +#endif + + v2 = generate_v2_networkstatus_opinion(); + tt_assert(v2); + + done: + crypto_pk_free(id_key); + cached_dir_decref(v2); +} + +static void +test_dir_fmt_control_ns(void *arg) +{ + char *s = NULL; + routerstatus_t rs; + (void)arg; + + memset(&rs, 0, sizeof(rs)); + rs.published_on = 1364925198; + strlcpy(rs.nickname, "TetsuoMilk", sizeof(rs.nickname)); + memcpy(rs.identity_digest, "Stately, plump Buck ", DIGEST_LEN); + memcpy(rs.descriptor_digest, "Mulligan came up fro", DIGEST_LEN); + rs.addr = 0x20304050; + rs.or_port = 9001; + rs.dir_port = 9002; + rs.is_exit = 1; + rs.is_fast = 1; + rs.is_flagged_running = 1; + rs.has_bandwidth = 1; + rs.bandwidth_kb = 1000; + + s = networkstatus_getinfo_helper_single(&rs); + tt_assert(s); + tt_str_op(s, ==, + "r TetsuoMilk U3RhdGVseSwgcGx1bXAgQnVjayA " + "TXVsbGlnYW4gY2FtZSB1cCBmcm8 2013-04-02 17:53:18 " + "32.48.64.80 9001 9002\n" + "s Exit Fast Running\n" + "w Bandwidth=1000\n"); + + done: + tor_free(s); +} + #define DIR_LEGACY(name) \ { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_dir_ ## name } -#define DIR(name) \ - { #name, test_dir_##name, 0, NULL, NULL } +#define DIR(name,flags) \ + { #name, test_dir_##name, (flags), 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(split_fps, 0), + DIR_LEGACY(measured_bw_kb), + DIR_LEGACY(measured_bw_kb_cache), DIR_LEGACY(param_voting), DIR_LEGACY(v3_networkstatus), + DIR(random_weighted, 0), + DIR(scale_bw, 0), + DIR_LEGACY(clip_unmeasured_bw_kb), + DIR_LEGACY(clip_unmeasured_bw_kb_alt), + DIR(v2_dir, TT_FORK), + DIR(fmt_control_ns, 0), END_OF_TESTCASES }; diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c new file mode 100644 index 0000000000..69c1152229 --- /dev/null +++ b/src/test/test_introduce.c @@ -0,0 +1,528 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "crypto.h" +#include "or.h" +#include "test.h" + +#define RENDSERVICE_PRIVATE +#include "rendservice.h" + +extern const char AUTHORITY_SIGNKEY_1[]; + +static uint8_t v0_test_plaintext[] = + /* 20 bytes of rendezvous point nickname */ + { 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* 20 bytes dummy rendezvous cookie */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 128 bytes dummy DH handshake data */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + +static uint8_t v1_test_plaintext[] = + /* Version byte */ + { 0x01, + /* 42 bytes of dummy rendezvous point hex digest */ + 0x24, 0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, + 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, + 0x37, 0x30, 0x38, 0x30, 0x39, 0x30, 0x41, 0x30, + 0x42, 0x30, 0x43, 0x30, 0x44, 0x30, 0x45, 0x30, + 0x46, 0x31, 0x30, 0x31, 0x31, 0x31, 0x32, 0x31, + 0x33, 0x00, + /* 20 bytes dummy rendezvous cookie */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 128 bytes dummy DH handshake data */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + +static uint8_t v2_test_plaintext[] = + /* Version byte */ + { 0x02, + /* 4 bytes rendezvous point's IP address */ + 0xc0, 0xa8, 0x00, 0x01, + /* 2 bytes rendezvous point's OR port */ + 0x23, 0x5a, + /* 20 bytes dummy rendezvous point's identity digest */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 2 bytes length of onion key */ + 0x00, 0x8c, + /* Onion key (140 bytes taken from live test) */ + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb1, + 0xcd, 0x46, 0xa9, 0x18, 0xd2, 0x0f, 0x01, 0xf8, + 0xb2, 0xad, 0xa4, 0x79, 0xb4, 0xbb, 0x4b, 0xf4, + 0x54, 0x1e, 0x3f, 0x03, 0x54, 0xcf, 0x7c, 0xb6, + 0xb5, 0xf0, 0xfe, 0xed, 0x4b, 0x7d, 0xd7, 0x61, + 0xdb, 0x6d, 0xd9, 0x19, 0xe2, 0x72, 0x04, 0xaa, + 0x3e, 0x89, 0x26, 0x14, 0x62, 0x9a, 0x6c, 0x11, + 0x0b, 0x35, 0x99, 0x2c, 0x9f, 0x2c, 0x64, 0xa1, + 0xd9, 0xe2, 0x88, 0xce, 0xf6, 0x54, 0xfe, 0x1d, + 0x37, 0x5e, 0x6d, 0x73, 0x95, 0x54, 0x90, 0xf0, + 0x7b, 0xfa, 0xd4, 0x44, 0xac, 0xb2, 0x23, 0x9f, + 0x75, 0x36, 0xe2, 0x78, 0x62, 0x82, 0x80, 0xa4, + 0x23, 0x22, 0xc9, 0xbf, 0xc4, 0x36, 0xd1, 0x31, + 0x33, 0x8e, 0x64, 0xb4, 0xa9, 0x74, 0xa1, 0xcb, + 0x42, 0x8d, 0x60, 0xc7, 0xbb, 0x8e, 0x6e, 0x0f, + 0x36, 0x74, 0x8e, 0xf4, 0x08, 0x99, 0x06, 0x92, + 0xb1, 0x3f, 0xb3, 0xdd, 0xed, 0xf7, 0xc9, 0x02, + 0x03, 0x01, 0x00, 0x01, + /* 20 bytes dummy rendezvous cookie */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 128 bytes dummy DH handshake data */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + +static uint8_t v3_no_auth_test_plaintext[] = + /* Version byte */ + { 0x03, + /* Auth type (0 for no auth len/auth data) */ + 0x00, + /* Timestamp */ + 0x50, 0x0b, 0xb5, 0xaa, + /* 4 bytes rendezvous point's IP address */ + 0xc0, 0xa8, 0x00, 0x01, + /* 2 bytes rendezvous point's OR port */ + 0x23, 0x5a, + /* 20 bytes dummy rendezvous point's identity digest */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 2 bytes length of onion key */ + 0x00, 0x8c, + /* Onion key (140 bytes taken from live test) */ + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb1, + 0xcd, 0x46, 0xa9, 0x18, 0xd2, 0x0f, 0x01, 0xf8, + 0xb2, 0xad, 0xa4, 0x79, 0xb4, 0xbb, 0x4b, 0xf4, + 0x54, 0x1e, 0x3f, 0x03, 0x54, 0xcf, 0x7c, 0xb6, + 0xb5, 0xf0, 0xfe, 0xed, 0x4b, 0x7d, 0xd7, 0x61, + 0xdb, 0x6d, 0xd9, 0x19, 0xe2, 0x72, 0x04, 0xaa, + 0x3e, 0x89, 0x26, 0x14, 0x62, 0x9a, 0x6c, 0x11, + 0x0b, 0x35, 0x99, 0x2c, 0x9f, 0x2c, 0x64, 0xa1, + 0xd9, 0xe2, 0x88, 0xce, 0xf6, 0x54, 0xfe, 0x1d, + 0x37, 0x5e, 0x6d, 0x73, 0x95, 0x54, 0x90, 0xf0, + 0x7b, 0xfa, 0xd4, 0x44, 0xac, 0xb2, 0x23, 0x9f, + 0x75, 0x36, 0xe2, 0x78, 0x62, 0x82, 0x80, 0xa4, + 0x23, 0x22, 0xc9, 0xbf, 0xc4, 0x36, 0xd1, 0x31, + 0x33, 0x8e, 0x64, 0xb4, 0xa9, 0x74, 0xa1, 0xcb, + 0x42, 0x8d, 0x60, 0xc7, 0xbb, 0x8e, 0x6e, 0x0f, + 0x36, 0x74, 0x8e, 0xf4, 0x08, 0x99, 0x06, 0x92, + 0xb1, 0x3f, 0xb3, 0xdd, 0xed, 0xf7, 0xc9, 0x02, + 0x03, 0x01, 0x00, 0x01, + /* 20 bytes dummy rendezvous cookie */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 128 bytes dummy DH handshake data */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + +static uint8_t v3_basic_auth_test_plaintext[] = + /* Version byte */ + { 0x03, + /* Auth type (1 for REND_BASIC_AUTH) */ + 0x01, + /* Auth len (must be 16 bytes for REND_BASIC_AUTH) */ + 0x00, 0x10, + /* Auth data (a 16-byte dummy descriptor cookie) */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* Timestamp */ + 0x50, 0x0b, 0xb5, 0xaa, + /* 4 bytes rendezvous point's IP address */ + 0xc0, 0xa8, 0x00, 0x01, + /* 2 bytes rendezvous point's OR port */ + 0x23, 0x5a, + /* 20 bytes dummy rendezvous point's identity digest */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 2 bytes length of onion key */ + 0x00, 0x8c, + /* Onion key (140 bytes taken from live test) */ + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb1, + 0xcd, 0x46, 0xa9, 0x18, 0xd2, 0x0f, 0x01, 0xf8, + 0xb2, 0xad, 0xa4, 0x79, 0xb4, 0xbb, 0x4b, 0xf4, + 0x54, 0x1e, 0x3f, 0x03, 0x54, 0xcf, 0x7c, 0xb6, + 0xb5, 0xf0, 0xfe, 0xed, 0x4b, 0x7d, 0xd7, 0x61, + 0xdb, 0x6d, 0xd9, 0x19, 0xe2, 0x72, 0x04, 0xaa, + 0x3e, 0x89, 0x26, 0x14, 0x62, 0x9a, 0x6c, 0x11, + 0x0b, 0x35, 0x99, 0x2c, 0x9f, 0x2c, 0x64, 0xa1, + 0xd9, 0xe2, 0x88, 0xce, 0xf6, 0x54, 0xfe, 0x1d, + 0x37, 0x5e, 0x6d, 0x73, 0x95, 0x54, 0x90, 0xf0, + 0x7b, 0xfa, 0xd4, 0x44, 0xac, 0xb2, 0x23, 0x9f, + 0x75, 0x36, 0xe2, 0x78, 0x62, 0x82, 0x80, 0xa4, + 0x23, 0x22, 0xc9, 0xbf, 0xc4, 0x36, 0xd1, 0x31, + 0x33, 0x8e, 0x64, 0xb4, 0xa9, 0x74, 0xa1, 0xcb, + 0x42, 0x8d, 0x60, 0xc7, 0xbb, 0x8e, 0x6e, 0x0f, + 0x36, 0x74, 0x8e, 0xf4, 0x08, 0x99, 0x06, 0x92, + 0xb1, 0x3f, 0xb3, 0xdd, 0xed, 0xf7, 0xc9, 0x02, + 0x03, 0x01, 0x00, 0x01, + /* 20 bytes dummy rendezvous cookie */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + /* 128 bytes dummy DH handshake data */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + +static void do_decrypt_test(uint8_t *plaintext, size_t plaintext_len); +static void do_early_parse_test(uint8_t *plaintext, size_t plaintext_len); +static void do_late_parse_test(uint8_t *plaintext, size_t plaintext_len); +static void do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase); +static ssize_t make_intro_from_plaintext( + void *buf, size_t len, crypto_pk_t *key, void **cell_out); + +#define EARLY_PARSE_ONLY 1 +#define DECRYPT_ONLY 2 +#define ALL_PARSING 3 + +static void +do_early_parse_test(uint8_t *plaintext, size_t plaintext_len) +{ + do_parse_test(plaintext, plaintext_len, EARLY_PARSE_ONLY); +} + +static void +do_decrypt_test(uint8_t *plaintext, size_t plaintext_len) +{ + do_parse_test(plaintext, plaintext_len, DECRYPT_ONLY); +} + +static void +do_late_parse_test(uint8_t *plaintext, size_t plaintext_len) +{ + do_parse_test(plaintext, plaintext_len, ALL_PARSING); +} + +/** Test utility function: checks that the <b>plaintext_len</b>-byte string at + * <b>plaintext</b> is at least superficially parseable. + */ +static void +do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase) +{ + crypto_pk_t *k = NULL; + ssize_t r; + uint8_t *cell = NULL; + size_t cell_len; + rend_intro_cell_t *parsed_req = NULL; + char *err_msg = NULL; + char digest[DIGEST_LEN]; + + /* Get a key */ + k = crypto_pk_new(); + test_assert(k); + r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_1, -1); + test_assert(!r); + + /* Get digest for future comparison */ + r = crypto_pk_get_digest(k, digest); + test_assert(r >= 0); + + /* Make a cell out of it */ + r = make_intro_from_plaintext( + plaintext, plaintext_len, + k, (void **)(&cell)); + test_assert(r > 0); + test_assert(cell); + cell_len = r; + + /* Do early parsing */ + parsed_req = rend_service_begin_parse_intro(cell, cell_len, 2, &err_msg); + test_assert(parsed_req); + test_assert(!err_msg); + test_memeq(parsed_req->pk, digest, DIGEST_LEN); + test_assert(parsed_req->ciphertext); + test_assert(parsed_req->ciphertext_len > 0); + + if (phase == EARLY_PARSE_ONLY) + goto done; + + /* Do decryption */ + r = rend_service_decrypt_intro(parsed_req, k, &err_msg); + test_assert(!r); + test_assert(!err_msg); + test_assert(parsed_req->plaintext); + test_assert(parsed_req->plaintext_len > 0); + + if (phase == DECRYPT_ONLY) + goto done; + + /* Do late parsing */ + r = rend_service_parse_intro_plaintext(parsed_req, &err_msg); + test_assert(!r); + test_assert(!err_msg); + test_assert(parsed_req->parsed); + + done: + tor_free(cell); + crypto_pk_free(k); + rend_service_free_intro(parsed_req); + tor_free(err_msg); +} + +/** Given the plaintext of the encrypted part of an INTRODUCE1/2 and a key, + * construct the encrypted cell for testing. + */ + +static ssize_t +make_intro_from_plaintext( + void *buf, size_t len, crypto_pk_t *key, void **cell_out) +{ + char *cell = NULL; + ssize_t cell_len = -1, r; + /* Assemble key digest and ciphertext, then construct the cell */ + ssize_t ciphertext_size; + + if (!(buf && key && len > 0 && cell_out)) goto done; + + /* + * Figure out an upper bound on how big the ciphertext will be + * (see crypto_pk_public_hybrid_encrypt()) + */ + ciphertext_size = PKCS1_OAEP_PADDING_OVERHEAD; + ciphertext_size += crypto_pk_keysize(key); + ciphertext_size += CIPHER_KEY_LEN; + ciphertext_size += len; + + /* + * Allocate space for the cell + */ + cell = tor_malloc(DIGEST_LEN + ciphertext_size); + + /* Compute key digest (will be first DIGEST_LEN octets of cell) */ + r = crypto_pk_get_digest(key, cell); + test_assert(r >= 0); + + /* Do encryption */ + r = crypto_pk_public_hybrid_encrypt( + key, cell + DIGEST_LEN, ciphertext_size, + buf, len, + PK_PKCS1_OAEP_PADDING, 0); + test_assert(r >= 0); + + /* Figure out cell length */ + cell_len = DIGEST_LEN + r; + + /* Output the cell */ + *cell_out = cell; + + done: + return cell_len; +} + +/** Test v0 INTRODUCE2 parsing through decryption only + */ + +static void +test_introduce_decrypt_v0(void) +{ + do_decrypt_test(v0_test_plaintext, sizeof(v0_test_plaintext)); +} + +/** Test v1 INTRODUCE2 parsing through decryption only + */ + +static void +test_introduce_decrypt_v1(void) +{ + do_decrypt_test(v1_test_plaintext, sizeof(v1_test_plaintext)); +} + +/** Test v2 INTRODUCE2 parsing through decryption only + */ + +static void +test_introduce_decrypt_v2(void) +{ + do_decrypt_test(v2_test_plaintext, sizeof(v2_test_plaintext)); +} + +/** Test v3 INTRODUCE2 parsing through decryption only + */ + +static void +test_introduce_decrypt_v3(void) +{ + do_decrypt_test( + v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext)); + do_decrypt_test( + v3_basic_auth_test_plaintext, sizeof(v3_basic_auth_test_plaintext)); +} + +/** Test v0 INTRODUCE2 parsing through early parsing only + */ + +static void +test_introduce_early_parse_v0(void) +{ + do_early_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext)); +} + +/** Test v1 INTRODUCE2 parsing through early parsing only + */ + +static void +test_introduce_early_parse_v1(void) +{ + do_early_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext)); +} + +/** Test v2 INTRODUCE2 parsing through early parsing only + */ + +static void +test_introduce_early_parse_v2(void) +{ + do_early_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext)); +} + +/** Test v3 INTRODUCE2 parsing through early parsing only + */ + +static void +test_introduce_early_parse_v3(void) +{ + do_early_parse_test( + v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext)); + do_early_parse_test( + v3_basic_auth_test_plaintext, sizeof(v3_basic_auth_test_plaintext)); +} + +/** Test v0 INTRODUCE2 parsing + */ + +static void +test_introduce_late_parse_v0(void) +{ + do_late_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext)); +} + +/** Test v1 INTRODUCE2 parsing + */ + +static void +test_introduce_late_parse_v1(void) +{ + do_late_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext)); +} + +/** Test v2 INTRODUCE2 parsing + */ + +static void +test_introduce_late_parse_v2(void) +{ + do_late_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext)); +} + +/** Test v3 INTRODUCE2 parsing + */ + +static void +test_introduce_late_parse_v3(void) +{ + do_late_parse_test( + v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext)); + do_late_parse_test( + v3_basic_auth_test_plaintext, sizeof(v3_basic_auth_test_plaintext)); +} + +#define INTRODUCE_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_introduce_ ## name } + +struct testcase_t introduce_tests[] = { + INTRODUCE_LEGACY(early_parse_v0), + INTRODUCE_LEGACY(early_parse_v1), + INTRODUCE_LEGACY(early_parse_v2), + INTRODUCE_LEGACY(early_parse_v3), + INTRODUCE_LEGACY(decrypt_v0), + INTRODUCE_LEGACY(decrypt_v1), + INTRODUCE_LEGACY(decrypt_v2), + INTRODUCE_LEGACY(decrypt_v3), + INTRODUCE_LEGACY(late_parse_v0), + INTRODUCE_LEGACY(late_parse_v1), + INTRODUCE_LEGACY(late_parse_v2), + INTRODUCE_LEGACY(late_parse_v3), + END_OF_TESTCASES +}; + diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 89c578f4a7..53a03a48ad 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Tor Project, Inc. */ +/* Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -208,11 +208,25 @@ test_md_cache(void *data) md3 = NULL; /* it's history now! */ /* rebuild again, make sure it stays gone. */ - microdesc_cache_rebuild(mc, 1); + tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0); tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1)); tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2)); tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3)); + /* Re-add md3, and make sure we can rebuild the cache. */ + added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL, + SAVED_NOWHERE, 0, time3, NULL); + tt_int_op(1, ==, smartlist_len(added)); + md3 = smartlist_get(added, 0); + smartlist_free(added); + added = NULL; + tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE); + tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE); + tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL); + + tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0); + tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE); + done: if (options) tor_free(options->DataDirectory); @@ -226,8 +240,53 @@ test_md_cache(void *data) tor_free(fn); } +static const char truncated_md[] = + "@last-listed 2013-08-08 19:02:59\n" + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAM91vLFNaM+gGhnRIdz2Cm/Kl7Xz0cOobIdVzhS3cKUJfk867hCuTipS\n" + "NveLBzNopvgXKruAAzEj3cACxk6Q8lv5UWOGCD1UolkgsWSE62RBjap44g+oc9J1\n" + "RI9968xOTZw0VaBQg9giEILNXl0djoikQ+5tQRUvLDDa67gpa5Q1AgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "family @\n"; + +static void +test_md_cache_broken(void *data) +{ + or_options_t *options; + char *fn=NULL; + microdesc_cache_t *mc = NULL; + + (void)data; + + options = get_options_mutable(); + tt_assert(options); + options->DataDirectory = tor_strdup(get_fname("md_datadir_test2")); + +#ifdef _WIN32 + tt_int_op(0, ==, mkdir(options->DataDirectory)); +#else + tt_int_op(0, ==, mkdir(options->DataDirectory, 0700)); +#endif + + tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs", + options->DataDirectory); + + write_str_to_file(fn, truncated_md, 1); + + mc = get_microdesc_cache(); + tt_assert(mc); + + done: + if (options) + tor_free(options->DataDirectory); + tor_free(fn); + microdesc_free_all(); +} + struct testcase_t microdesc_tests[] = { { "cache", test_md_cache, TT_FORK, NULL, NULL }, + { "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_ntor_cl.c b/src/test/test_ntor_cl.c new file mode 100644 index 0000000000..f2b7a72ad5 --- /dev/null +++ b/src/test/test_ntor_cl.c @@ -0,0 +1,170 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include <stdio.h> +#include <stdlib.h> + +#define ONION_NTOR_PRIVATE +#include "or.h" +#include "util.h" +#include "compat.h" +#include "crypto.h" +#include "crypto_curve25519.h" +#include "onion_ntor.h" + +#ifndef CURVE25519_ENABLED +#error "This isn't going to work without curve25519." +#endif + +#define N_ARGS(n) STMT_BEGIN { \ + if (argc < (n)) { \ + fprintf(stderr, "%s needs %d arguments.\n",argv[1],n); \ + return 1; \ + } \ + } STMT_END +#define BASE16(idx, var, n) STMT_BEGIN { \ + const char *s = argv[(idx)]; \ + if (base16_decode((char*)var, n, s, strlen(s)) < 0 ) { \ + fprintf(stderr, "couldn't decode argument %d (%s)\n",idx,s); \ + return 1; \ + } \ + } STMT_END +#define INT(idx, var) STMT_BEGIN { \ + var = atoi(argv[(idx)]); \ + if (var <= 0) { \ + fprintf(stderr, "bad integer argument %d (%s)\n",idx,argv[(idx)]); \ + } \ + } STMT_END + +static int +client1(int argc, char **argv) +{ + /* client1 nodeID B -> msg state */ + curve25519_public_key_t B; + uint8_t node_id[DIGEST_LEN]; + ntor_handshake_state_t *state = NULL; + uint8_t msg[NTOR_ONIONSKIN_LEN]; + + char buf[1024]; + + N_ARGS(4); + BASE16(2, node_id, DIGEST_LEN); + BASE16(3, B.public_key, CURVE25519_PUBKEY_LEN); + + if (onion_skin_ntor_create(node_id, &B, &state, msg)<0) { + fprintf(stderr, "handshake failed"); + return 2; + } + + base16_encode(buf, sizeof(buf), (const char*)msg, sizeof(msg)); + printf("%s\n", buf); + base16_encode(buf, sizeof(buf), (void*)state, sizeof(*state)); + printf("%s\n", buf); + + ntor_handshake_state_free(state); + return 0; +} + +static int +server1(int argc, char **argv) +{ + uint8_t msg_in[NTOR_ONIONSKIN_LEN]; + curve25519_keypair_t kp; + di_digest256_map_t *keymap=NULL; + uint8_t node_id[DIGEST_LEN]; + int keybytes; + + uint8_t msg_out[NTOR_REPLY_LEN]; + uint8_t *keys = NULL; + char *hexkeys = NULL; + int result = 0; + + char buf[256]; + + /* server1: b nodeID msg N -> msg keys */ + N_ARGS(6); + BASE16(2, kp.seckey.secret_key, CURVE25519_SECKEY_LEN); + BASE16(3, node_id, DIGEST_LEN); + BASE16(4, msg_in, NTOR_ONIONSKIN_LEN); + INT(5, keybytes); + + curve25519_public_key_generate(&kp.pubkey, &kp.seckey); + dimap_add_entry(&keymap, kp.pubkey.public_key, &kp); + + keys = tor_malloc(keybytes); + hexkeys = tor_malloc(keybytes*2+1); + if (onion_skin_ntor_server_handshake( + msg_in, keymap, NULL, node_id, msg_out, keys, + (size_t)keybytes)<0) { + fprintf(stderr, "handshake failed"); + result = 2; + goto done; + } + + base16_encode(buf, sizeof(buf), (const char*)msg_out, sizeof(msg_out)); + printf("%s\n", buf); + base16_encode(hexkeys, keybytes*2+1, (const char*)keys, keybytes); + printf("%s\n", hexkeys); + + done: + tor_free(keys); + tor_free(hexkeys); + return result; +} + +static int +client2(int argc, char **argv) +{ + struct ntor_handshake_state_t state; + uint8_t msg[NTOR_REPLY_LEN]; + int keybytes; + uint8_t *keys; + char *hexkeys; + int result = 0; + + N_ARGS(5); + BASE16(2, (&state), sizeof(state)); + BASE16(3, msg, sizeof(msg)); + INT(4, keybytes); + + keys = tor_malloc(keybytes); + hexkeys = tor_malloc(keybytes*2+1); + if (onion_skin_ntor_client_handshake(&state, msg, keys, keybytes)<0) { + fprintf(stderr, "handshake failed"); + result = 2; + goto done; + } + + base16_encode(hexkeys, keybytes*2+1, (const char*)keys, keybytes); + printf("%s\n", hexkeys); + + done: + tor_free(keys); + tor_free(hexkeys); + return result; +} + +int +main(int argc, char **argv) +{ + /* + client1: nodeID B -> msg state + server1: b nodeID msg N -> msg keys + client2: state msg N -> keys + */ + if (argc < 2) { + fprintf(stderr, "I need arguments. Read source for more info.\n"); + return 1; + } else if (!strcmp(argv[1], "client1")) { + return client1(argc, argv); + } else if (!strcmp(argv[1], "server1")) { + return server1(argc, argv); + } else if (!strcmp(argv[1], "client2")) { + return client2(argc, argv); + } else { + fprintf(stderr, "What's a %s?\n", argv[1]); + return 1; + } +} + diff --git a/src/test/test_pt.c b/src/test/test_pt.c index d3dadb9bfa..80707f4379 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" diff --git a/src/test/test_replay.c b/src/test/test_replay.c new file mode 100644 index 0000000000..de841ad594 --- /dev/null +++ b/src/test/test_replay.c @@ -0,0 +1,178 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define REPLAYCACHE_PRIVATE + +#include "orconfig.h" +#include "or.h" +#include "replaycache.h" +#include "test.h" + +static const char *test_buffer = + "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed do eiusmod" + " tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim" + " veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea" + " commodo consequat. Duis aute irure dolor in reprehenderit in voluptate" + " velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint" + " occaecat cupidatat non proident, sunt in culpa qui officia deserunt" + " mollit anim id est laborum."; + +static void +test_replaycache_alloc(void) +{ + replaycache_t *r = NULL; + + r = replaycache_new(600, 300); + test_assert(r != NULL); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_miss(void) +{ + replaycache_t *r = NULL; + int result; + + r = replaycache_new(600, 300); + test_assert(r != NULL); + + result = + replaycache_add_and_test_internal(1200, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_hit(void) +{ + replaycache_t *r = NULL; + int result; + + r = replaycache_new(600, 300); + test_assert(r != NULL); + + result = + replaycache_add_and_test_internal(1200, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + + result = + replaycache_add_and_test_internal(1300, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 1); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_age(void) +{ + replaycache_t *r = NULL; + int result; + + r = replaycache_new(600, 300); + test_assert(r != NULL); + + result = + replaycache_add_and_test_internal(1200, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + + result = + replaycache_add_and_test_internal(1300, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 1); + + result = + replaycache_add_and_test_internal(3000, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_elapsed(void) +{ + replaycache_t *r = NULL; + int result; + time_t elapsed; + + r = replaycache_new(600, 300); + test_assert(r != NULL); + + result = + replaycache_add_and_test_internal(1200, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + + result = + replaycache_add_and_test_internal(1300, r, test_buffer, + (int)strlen(test_buffer), &elapsed); + test_eq(result, 1); + test_eq(elapsed, 100); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_noexpire(void) +{ + replaycache_t *r = NULL; + int result; + + r = replaycache_new(0, 0); + test_assert(r != NULL); + + result = + replaycache_add_and_test_internal(1200, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + + result = + replaycache_add_and_test_internal(1300, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 1); + + result = + replaycache_add_and_test_internal(3000, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 1); + + done: + if (r) replaycache_free(r); + + return; +} + +#define REPLAYCACHE_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_replaycache_ ## name } + +struct testcase_t replaycache_tests[] = { + REPLAYCACHE_LEGACY(alloc), + REPLAYCACHE_LEGACY(miss), + REPLAYCACHE_LEGACY(hit), + REPLAYCACHE_LEGACY(age), + REPLAYCACHE_LEGACY(elapsed), + REPLAYCACHE_LEGACY(noexpire), + END_OF_TESTCASES +}; + diff --git a/src/test/test_util.c b/src/test/test_util.c index 6c72247e9c..65d9d2f878 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2012, The Tor Project, Inc. */ + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -17,6 +17,7 @@ #ifdef _WIN32 #include <tchar.h> #endif +#include <math.h> /* XXXX this is a minimal wrapper to make the unit tests compile with the * changed tor_timegm interface. */ @@ -32,6 +33,75 @@ tor_timegm_wrapper(const struct tm *tm) #define tor_timegm tor_timegm_wrapper static void +test_util_read_until_eof_impl(const char *fname, size_t file_len, + size_t read_limit) +{ + char *fifo_name = NULL; + char *test_str = NULL; + char *str = NULL; + size_t sz = 9999999; + int fd = -1; + int r; + + fifo_name = tor_strdup(get_fname(fname)); + test_str = tor_malloc(file_len); + crypto_rand(test_str, file_len); + + r = write_bytes_to_file(fifo_name, test_str, file_len, 1); + tt_int_op(r, ==, 0); + + fd = open(fifo_name, O_RDONLY|O_BINARY); + tt_int_op(fd, >=, 0); + str = read_file_to_str_until_eof(fd, read_limit, &sz); + tt_assert(str != NULL); + + if (read_limit < file_len) + tt_int_op(sz, ==, read_limit); + else + tt_int_op(sz, ==, file_len); + + test_mem_op(test_str, ==, str, sz); + test_assert(str[sz] == '\0'); + + done: + unlink(fifo_name); + tor_free(fifo_name); + tor_free(test_str); + tor_free(str); + if (fd >= 0) + close(fd); +} + +static void +test_util_read_file_eof_tiny_limit(void *arg) +{ + (void)arg; + // purposely set limit shorter than what we wrote to the FIFO to + // test the maximum, and that it puts the NUL in the right spot + + test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4); +} + +static void +test_util_read_file_eof_two_loops(void *arg) +{ + (void)arg; + // write more than 1024 bytes to the FIFO to test two passes through + // the loop in the method; if the re-alloc size is changed this + // should be updated as well. + + test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000); +} + +static void +test_util_read_file_eof_zero_bytes(void *arg) +{ + (void)arg; + // zero-byte fifo + test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000); +} + +static void test_util_time(void) { struct timeval start, end; @@ -152,6 +222,7 @@ test_util_time(void) test_eq(-1, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res)); test_eq(-1, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res)); test_eq(-1, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res)); + test_eq(-1, parse_iso_time("2147483647-08-29 14:00:00", &t_res)); test_eq(-1, parse_iso_time("2011-03-30 23:59", &t_res)); /* Test tor_gettimeofday */ @@ -731,7 +802,7 @@ test_util_strmisc(void) { char buf[1024]; int i; - char *cp; + char *cp, *cp_tmp = NULL; /* Test strl operations */ test_eq(5, strlcpy(buf, "Hello", 0)); @@ -934,20 +1005,20 @@ test_util_strmisc(void) /* 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_tmp = tor_strndup(s, 30); + test_streq(cp_tmp, s); /* same string, */ + test_neq_ptr(cp_tmp, s); /* but different pointers. */ + tor_free(cp_tmp); - cp = tor_strndup(s, 5); - test_streq(cp, "abcde"); - tor_free(cp); + cp_tmp = tor_strndup(s, 5); + test_streq(cp_tmp, "abcde"); + tor_free(cp_tmp); 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); + cp_tmp = tor_memdup(s,10); + test_memeq(cp_tmp, s, 10); /* same ram, */ + test_neq_ptr(cp_tmp, s); /* but different pointers. */ + tor_free(cp_tmp); } /* Test str-foo functions */ @@ -983,79 +1054,6 @@ test_util_strmisc(void) test_assert(!tor_memstr(haystack, 7, "ababcade")); } - /* Test wrap_string */ - { - smartlist_t *sl = smartlist_new(); - wrap_string(sl, - "This is a test of string wrapping functionality: woot. " - "a functionality? w00t w00t...!", - 10, "", ""); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, - "This is a\ntest of\nstring\nwrapping\nfunctional\nity: woot.\n" - "a\nfunctional\nity? w00t\nw00t...!\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_clear(sl); - - wrap_string(sl, "A test of string wrapping...", 6, "### ", "# "); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, - "### A\n# test\n# of\n# stri\n# ng\n# wrap\n# ping\n# ...\n"); - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - wrap_string(sl, "Wrapping test", 6, "#### ", "# "); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, "#### W\n# rapp\n# ing\n# test\n"); - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - wrap_string(sl, "Small test", 6, "### ", "#### "); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, "### Sm\n#### a\n#### l\n#### l\n#### t\n#### e" - "\n#### s\n#### t\n"); - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - wrap_string(sl, "First null", 6, NULL, "> "); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, "First\n> null\n"); - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - wrap_string(sl, "Second null", 6, "> ", NULL); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, "> Seco\nnd\nnull\n"); - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_clear(sl); - - wrap_string(sl, "Both null", 6, NULL, NULL); - cp = smartlist_join_strings(sl, "", 0, NULL); - test_streq(cp, "Both\nnull\n"); - tor_free(cp); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_free(sl); - - /* Can't test prefixes that have the same length as the line width, because - the function has an assert */ - } - /* Test hex_str */ { char binary_data[68]; @@ -1099,7 +1097,7 @@ test_util_strmisc(void) tt_int_op(strcmp_len("blah", "", 0), ==, 0); done: - ; + tor_free(cp_tmp); } static void @@ -1109,6 +1107,7 @@ test_util_pow2(void) test_eq(tor_log2(64), 6); test_eq(tor_log2(65), 6); test_eq(tor_log2(63), 5); + test_eq(tor_log2(0), 0); /* incorrect mathematically, but as specified */ test_eq(tor_log2(1), 0); test_eq(tor_log2(2), 1); test_eq(tor_log2(3), 1); @@ -1123,26 +1122,35 @@ test_util_pow2(void) 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); + test_eq(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)), + U64_LITERAL(1)<<63); + test_eq(round_to_power_of_2(0), 1); + test_eq(round_to_power_of_2(1), 1); + test_eq(round_to_power_of_2(2), 2); + test_eq(round_to_power_of_2(3), 2); + test_eq(round_to_power_of_2(4), 4); + test_eq(round_to_power_of_2(5), 4); + test_eq(round_to_power_of_2(6), 4); + test_eq(round_to_power_of_2(7), 8); done: ; } /** mutex for thread test to stop the threads hitting data at the same time. */ -static tor_mutex_t *_thread_test_mutex = NULL; +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; +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; +static strmap_t *thread_test_strmap_ = NULL; /** The name of thread1 for the thread test */ -static char *_thread1_name = NULL; +static char *thread1_name_ = NULL; /** The name of thread2 for the thread test */ -static char *_thread2_name = NULL; +static char *thread2_name_ = NULL; -static void _thread_test_func(void* _s) ATTR_NORETURN; +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; @@ -1150,9 +1158,9 @@ 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. */ + * thread_test_mutex_. */ static void -_thread_test_func(void* _s) +thread_test_func_(void* _s) { char *s = _s; int i, *count; @@ -1160,12 +1168,12 @@ _thread_test_func(void* _s) char buf[64]; char **cp; if (!strcmp(s, "thread 1")) { - m = _thread_test_start1; - cp = &_thread1_name; + m = thread_test_start1_; + cp = &thread1_name_; count = &t1_count; } else { - m = _thread_test_start2; - cp = &_thread2_name; + m = thread_test_start2_; + cp = &thread2_name_; count = &t2_count; } @@ -1175,14 +1183,14 @@ _thread_test_func(void* _s) 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); + tor_mutex_acquire(thread_test_mutex_); + strmap_set(thread_test_strmap_, "last to run", *cp); ++*count; - tor_mutex_release(_thread_test_mutex); + 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_acquire(thread_test_mutex_); + strmap_set(thread_test_strmap_, s, *cp); + tor_mutex_release(thread_test_mutex_); tor_mutex_release(m); @@ -1207,67 +1215,67 @@ test_util_threads(void) 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(); + 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); + 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")) { + 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 + 150) { timedout = done = 1; } - tor_mutex_release(_thread_test_mutex); + tor_mutex_release(thread_test_mutex_); #ifndef _WIN32 /* 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_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); + 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(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"))); + 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); + 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 */ @@ -1416,7 +1424,7 @@ test_util_mmap(void) /* Now a zero-length file. */ write_str_to_file(fname1, "", 1); mapping = tor_mmap_file(fname1); - test_eq(mapping, NULL); + test_eq_ptr(mapping, NULL); test_eq(ERANGE, errno); unlink(fname1); @@ -1474,12 +1482,28 @@ test_util_control_formats(void) tor_free(out); } +#define test_feq(value1,value2) do { \ + double v1 = (value1), v2=(value2); \ + double tf_diff = v1-v2; \ + double tf_tolerance = ((v1+v2)/2.0)/1e8; \ + if (tf_diff<0) tf_diff=-tf_diff; \ + if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \ + if (tf_diff<tf_tolerance) { \ + TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \ + } else { \ + TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \ + } \ + } while (0) + static void test_util_sscanf(void) { unsigned u1, u2, u3; char s1[20], s2[10], s3[10], ch; int r; + long lng1,lng2; + int int1, int2; + double d1,d2,d3,d4; /* Simple tests (malformed patterns, literal matching, ...) */ test_eq(-1, tor_sscanf("123", "%i", &r)); /* %i is not supported */ @@ -1608,6 +1632,65 @@ test_util_sscanf(void) test_eq(4, tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch)); test_eq(' ', ch); + r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2); + test_eq(r,3); + test_eq(int1, 12345); + test_eq(lng1, -67890); + test_eq(int2, -1); + +#if SIZEOF_INT == 4 + r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2); + test_eq(r,2); + test_eq(int1, -2147483647-1); + test_eq(int2, 2147483647); + + r = tor_sscanf("-2147483679.", "%d.", &int1); + test_eq(r,0); + + r = tor_sscanf("2147483678.", "%d.", &int1); + test_eq(r,0); +#elif SIZEOF_INT == 8 + r = tor_sscanf("-9223372036854775808. 9223372036854775807.", + "%d. %d.", &int1, &int2); + test_eq(r,2); + test_eq(int1, -9223372036854775807-1); + test_eq(int2, 9223372036854775807); + + r = tor_sscanf("-9223372036854775809.", "%d.", &int1); + test_eq(r,0); + + r = tor_sscanf("9223372036854775808.", "%d.", &int1); + test_eq(r,0); +#endif + +#if SIZEOF_LONG == 4 + r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2); + test_eq(r,2); + test_eq(lng1, -2147483647 - 1); + test_eq(lng2, 2147483647); +#elif SIZEOF_LONG == 8 + r = tor_sscanf("-9223372036854775808. 9223372036854775807.", + "%ld. %ld.", &lng1, &lng2); + test_eq(r,2); + test_eq(lng1, -9223372036854775807L - 1); + test_eq(lng2, 9223372036854775807L); + + r = tor_sscanf("-9223372036854775808. 9223372036854775808.", + "%ld. %ld.", &lng1, &lng2); + test_eq(r,1); + r = tor_sscanf("-9223372036854775809. 9223372036854775808.", + "%ld. %ld.", &lng1, &lng2); + test_eq(r,0); +#endif + + r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2", + "%lf %lf %lf %lf", &d1,&d2,&d3,&d4); + test_eq(r,4); + test_feq(d1, 123.456); + test_feq(d2, .000007); + test_feq(d3, -900123123.2000787); + test_feq(d4, 3.2); + done: ; } @@ -1735,7 +1818,7 @@ test_util_memarea(void) /* Make sure we don't overalign. */ p1 = memarea_alloc(area, 1); p2 = memarea_alloc(area, 1); - test_eq(p1+sizeof(void*), p2); + test_eq_ptr(p1+sizeof(void*), p2); { malloced_ptr = tor_malloc(64); test_assert(!memarea_owns_ptr(area, malloced_ptr)); @@ -1780,7 +1863,7 @@ test_util_memarea(void) memarea_clear(area); p1 = memarea_alloc(area, 1); - test_eq(p1, p1_orig); + test_eq_ptr(p1, p1_orig); memarea_clear(area); /* Check for running over an area's size. */ @@ -2061,13 +2144,13 @@ test_util_listdir(void *ptr) dir_contents = tor_listdir(dirname); test_assert(dir_contents); /* make sure that each filename is listed. */ - test_assert(smartlist_string_isin_case(dir_contents, "hopscotch")); - test_assert(smartlist_string_isin_case(dir_contents, "mumblety-peg")); - test_assert(smartlist_string_isin_case(dir_contents, ".hidden-file")); - test_assert(smartlist_string_isin_case(dir_contents, "some-directory")); + test_assert(smartlist_contains_string_case(dir_contents, "hopscotch")); + test_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg")); + test_assert(smartlist_contains_string_case(dir_contents, ".hidden-file")); + test_assert(smartlist_contains_string_case(dir_contents, "some-directory")); - test_assert(!smartlist_string_isin(dir_contents, ".")); - test_assert(!smartlist_string_isin(dir_contents, "..")); + test_assert(!smartlist_contains_string(dir_contents, ".")); + test_assert(!smartlist_contains_string(dir_contents, "..")); done: tor_free(fname1); @@ -2136,7 +2219,7 @@ test_util_load_win_lib(void *ptr) tt_assert(h); done: if (h) - CloseHandle(h); + FreeLibrary(h); } #endif @@ -2558,7 +2641,7 @@ test_util_join_win_cmdline(void *ptr) }; int i; - char *joined_argv; + char *joined_argv = NULL; (void)ptr; @@ -2570,7 +2653,7 @@ test_util_join_win_cmdline(void *ptr) } done: - ; + tor_free(joined_argv); } #define MAX_SPLIT_LINE_COUNT 4 @@ -2690,6 +2773,16 @@ test_util_di_ops(void) test_eq(neq1, !eq1); } + tt_int_op(1, ==, safe_mem_is_zero("", 0)); + tt_int_op(1, ==, safe_mem_is_zero("", 1)); + tt_int_op(0, ==, safe_mem_is_zero("a", 1)); + tt_int_op(0, ==, safe_mem_is_zero("a", 2)); + tt_int_op(0, ==, safe_mem_is_zero("\0a", 2)); + tt_int_op(1, ==, safe_mem_is_zero("\0\0a", 2)); + tt_int_op(1, ==, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8)); + tt_int_op(1, ==, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8)); + tt_int_op(0, ==, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9)); + done: ; } @@ -3045,7 +3138,7 @@ test_util_set_env_var_in_sl(void *ptr) SMARTLIST_FOREACH(new_env_vars, char *, env_var, set_environment_variable_in_smartlist(merged_env_vars, env_var, - _tor_free, + tor_free_, 1)); smartlist_sort_strings(merged_env_vars); @@ -3077,6 +3170,48 @@ test_util_set_env_var_in_sl(void *ptr) smartlist_free(expected_resulting_env_vars); } +static void +test_util_weak_random(void *arg) +{ + int i, j, n[16]; + tor_weak_rng_t rng; + (void) arg; + + tor_init_weak_random(&rng, (unsigned)time(NULL)); + + for (i = 1; i <= 256; ++i) { + for (j=0;j<100;++j) { + int r = tor_weak_random_range(&rng, i); + tt_int_op(0, <=, r); + tt_int_op(r, <, i); + } + } + + memset(n,0,sizeof(n)); + for (j=0;j<8192;++j) { + n[tor_weak_random_range(&rng, 16)]++; + } + + for (i=0;i<16;++i) + tt_int_op(n[i], >, 0); + done: + ; +} + +static void +test_util_mathlog(void *arg) +{ + double d; + (void) arg; + + d = tor_mathlog(2.718281828); + tt_double_op(fabs(d - 1.0), <, .000001); + d = tor_mathlog(10); + tt_double_op(fabs(d - 2.30258509), <, .000001); + done: + ; +} + #define UTIL_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name } @@ -3130,6 +3265,11 @@ struct testcase_t util_tests[] = { UTIL_TEST(envnames, 0), UTIL_TEST(make_environment, 0), UTIL_TEST(set_env_var_in_sl, 0), + UTIL_TEST(read_file_eof_tiny_limit, 0), + UTIL_TEST(read_file_eof_two_loops, 0), + UTIL_TEST(read_file_eof_zero_bytes, 0), + UTIL_TEST(mathlog, 0), + UTIL_TEST(weak_random, 0), END_OF_TESTCASES }; diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am deleted file mode 100644 index 35b0a41f53..0000000000 --- a/src/tools/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -bin_PROGRAMS = tor-resolve tor-gencert -noinst_PROGRAMS = tor-checkkey - -tor_resolve_SOURCES = tor-resolve.c -tor_resolve_LDFLAGS = -tor_resolve_LDADD = ../common/libor.a @TOR_LIB_MATH@ @TOR_LIB_WS32@ - -tor_gencert_SOURCES = tor-gencert.c -tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ -tor_gencert_LDADD = ../common/libor.a ../common/libor-crypto.a \ - @TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ - -tor_checkkey_SOURCES = tor-checkkey.c -tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ -tor_checkkey_LDADD = ../common/libor.a ../common/libor-crypto.a \ - @TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ - -SUBDIRS = tor-fw-helper -DIST_SUBDIRS = tor-fw-helper - diff --git a/src/tools/Makefile.nmake b/src/tools/Makefile.nmake index a30a28b2e1..fda1990e0b 100644 --- a/src/tools/Makefile.nmake +++ b/src/tools/Makefile.nmake @@ -6,8 +6,8 @@ LIBS = ..\..\..\build-alpha\lib\libevent.lib \ ..\..\..\build-alpha\lib\libcrypto.lib \ ..\..\..\build-alpha\lib\libssl.lib \ ..\..\..\build-alpha\lib\libz.lib \ - ws2_32.lib advapi32.lib shell32.lib - + ws2_32.lib advapi32.lib shell32.lib \ + crypt32.lib gdi32.lib user32.lib tor-gencert.exe: tor-gencert.obj $(CC) $(CFLAGS) $(LIBS) ..\common\*.lib tor-gencert.obj diff --git a/src/tools/include.am b/src/tools/include.am new file mode 100644 index 0000000000..54b150a80c --- /dev/null +++ b/src/tools/include.am @@ -0,0 +1,24 @@ +bin_PROGRAMS+= src/tools/tor-resolve src/tools/tor-gencert +noinst_PROGRAMS+= src/tools/tor-checkkey + +src_tools_tor_resolve_SOURCES = src/tools/tor-resolve.c +src_tools_tor_resolve_LDFLAGS = +src_tools_tor_resolve_LDADD = src/common/libor.a @TOR_LIB_MATH@ @TOR_LIB_WS32@ + +src_tools_tor_gencert_SOURCES = src/tools/tor-gencert.c +src_tools_tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ +src_tools_tor_gencert_LDADD = src/common/libor.a src/common/libor-crypto.a \ + $(LIBDONNA) \ + @TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + +src_tools_tor_checkkey_SOURCES = src/tools/tor-checkkey.c +src_tools_tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ +src_tools_tor_checkkey_LDADD = src/common/libor.a src/common/libor-crypto.a \ + $(LIBDONNA) \ + @TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + +include src/tools/tor-fw-helper/include.am + + diff --git a/src/tools/tor-checkkey.c b/src/tools/tor-checkkey.c index 10d13d8371..a3860ca4b7 100644 --- a/src/tools/tor-checkkey.c +++ b/src/tools/tor-checkkey.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2012, The Tor Project, Inc. */ +/* Copyright (c) 2008-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CRYPTO_PRIVATE @@ -71,7 +71,7 @@ main(int c, char **v) return 1; printf("%s\n",digest); } else { - rsa = _crypto_pk_get_rsa(env); + rsa = crypto_pk_get_rsa_(env); str = BN_bn2hex(rsa->n); printf("%s\n", str); diff --git a/src/tools/tor-fw-helper/Makefile.am b/src/tools/tor-fw-helper/Makefile.am deleted file mode 100644 index 393562db03..0000000000 --- a/src/tools/tor-fw-helper/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -if USE_FW_HELPER -bin_PROGRAMS = tor-fw-helper -else -bin_PROGRAMS = -endif - -tor_fw_helper_SOURCES = \ - tor-fw-helper.c \ - tor-fw-helper-natpmp.c \ - tor-fw-helper-upnp.c -noinst_HEADERS = \ - tor-fw-helper.h \ - tor-fw-helper-natpmp.h \ - tor-fw-helper-upnp.h - -if NAT_PMP -nat_pmp_ldflags = @TOR_LDFLAGS_libnatpmp@ -nat_pmp_ldadd = -lnatpmp @TOR_LIB_IPHLPAPI@ -nat_pmp_cppflags = @TOR_CPPFLAGS_libnatpmp@ -else -nat_pmp_ldflags = -nat_pmp_ldadd = -nat_pmp_cppflags = -endif - -if MINIUPNPC -miniupnpc_ldflags = @TOR_LDFLAGS_libminiupnpc@ -miniupnpc_ldadd = -lminiupnpc -lm @TOR_LIB_IPHLPAPI@ -miniupnpc_cppflags = @TOR_CPPFLAGS_libminiupnpc@ -else -miniupnpc_ldflags = -miniupnpc_ldadd = -miniupnpc_cppflags = -endif - -tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags) -tor_fw_helper_LDADD = ../../common/libor.a $(nat_pmp_ldadd) $(miniupnpc_ldadd) @TOR_LIB_WS32@ -tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags) diff --git a/src/tools/tor-fw-helper/include.am b/src/tools/tor-fw-helper/include.am new file mode 100644 index 0000000000..275a0e237c --- /dev/null +++ b/src/tools/tor-fw-helper/include.am @@ -0,0 +1,36 @@ +if USE_FW_HELPER +bin_PROGRAMS+= src/tools/tor-fw-helper/tor-fw-helper +endif + +src_tools_tor_fw_helper_tor_fw_helper_SOURCES = \ + src/tools/tor-fw-helper/tor-fw-helper.c \ + src/tools/tor-fw-helper/tor-fw-helper-natpmp.c \ + src/tools/tor-fw-helper/tor-fw-helper-upnp.c +noinst_HEADERS+= \ + src/tools/tor-fw-helper/tor-fw-helper.h \ + src/tools/tor-fw-helper/tor-fw-helper-natpmp.h \ + src/tools/tor-fw-helper/tor-fw-helper-upnp.h + +if NAT_PMP +nat_pmp_ldflags = @TOR_LDFLAGS_libnatpmp@ +nat_pmp_ldadd = -lnatpmp @TOR_LIB_IPHLPAPI@ +nat_pmp_cppflags = @TOR_CPPFLAGS_libnatpmp@ +else +nat_pmp_ldflags = +nat_pmp_ldadd = +nat_pmp_cppflags = +endif + +if MINIUPNPC +miniupnpc_ldflags = @TOR_LDFLAGS_libminiupnpc@ +miniupnpc_ldadd = -lminiupnpc @TOR_LIB_IPHLPAPI@ +miniupnpc_cppflags = @TOR_CPPFLAGS_libminiupnpc@ +else +miniupnpc_ldflags = +miniupnpc_ldadd = +miniupnpc_cppflags = +endif + +src_tools_tor_fw_helper_tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags) +src_tools_tor_fw_helper_tor_fw_helper_LDADD = src/common/libor.a $(nat_pmp_ldadd) $(miniupnpc_ldadd) -lm @TOR_LIB_WS32@ +src_tools_tor_fw_helper_tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags) diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c index 0e0b385f9b..41eb9dcb76 100644 --- a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c +++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c @@ -1,5 +1,5 @@ /* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2012, The Tor Project, Inc. */ + * Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -60,15 +60,15 @@ tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state) state->lease = NATPMP_DEFAULT_LEASE; if (tor_fw_options->verbose) - fprintf(stdout, "V: natpmp init...\n"); + fprintf(stderr, "V: natpmp init...\n"); r = initnatpmp(&(state->natpmp), 0, 0); if (r == 0) { state->init = 1; - fprintf(stdout, "tor-fw-helper: natpmp initialized...\n"); + fprintf(stderr, "V: natpmp initialized...\n"); return r; } else { - fprintf(stderr, "tor-fw-helper: natpmp failed to initialize...\n"); + fprintf(stderr, "V: natpmp failed to initialize...\n"); return r; } } @@ -80,10 +80,10 @@ tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state) natpmp_state_t *state = (natpmp_state_t *) backend_state; int r = 0; if (tor_fw_options->verbose) - fprintf(stdout, "V: natpmp cleanup...\n"); + fprintf(stderr, "V: natpmp cleanup...\n"); r = closenatpmp(&(state->natpmp)); if (tor_fw_options->verbose) - fprintf(stdout, "V: closing natpmp socket: %d\n", r); + fprintf(stderr, "V: closing natpmp socket: %d\n", r); return r; } @@ -93,16 +93,20 @@ wait_until_fd_readable(tor_socket_t fd, struct timeval *timeout) { int r; fd_set fds; + +#ifndef WIN32 if (fd >= FD_SETSIZE) { fprintf(stderr, "E: NAT-PMP FD_SETSIZE error %d\n", fd); return -1; } +#endif + FD_ZERO(&fds); FD_SET(fd, &fds); r = select(fd+1, &fds, NULL, NULL, timeout); if (r == -1) { - fprintf(stdout, "V: select failed in wait_until_fd_readable: %s\n", - strerror(errno)); + fprintf(stderr, "V: select failed in wait_until_fd_readable: %s\n", + tor_socket_strerror(tor_socket_errno(fd))); return -1; } /* XXXX we should really check to see whether fd was readable, or we timed @@ -110,27 +114,25 @@ wait_until_fd_readable(tor_socket_t fd, struct timeval *timeout) return 0; } -/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b> - * using the <b>natpmp_t</b> stored in <b>backend_state</b>. */ int -tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options, - void *backend_state) +tor_natpmp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, + int is_verbose, void *backend_state) { - natpmp_state_t *state = (natpmp_state_t *) backend_state; int r = 0; int x = 0; int sav_errno; + natpmp_state_t *state = (natpmp_state_t *) backend_state; struct timeval timeout; - if (tor_fw_options->verbose) - fprintf(stdout, "V: sending natpmp portmapping request...\n"); + if (is_verbose) + fprintf(stderr, "V: sending natpmp portmapping request...\n"); r = sendnewportmappingrequest(&(state->natpmp), state->protocol, - tor_fw_options->internal_port, - tor_fw_options->external_port, + internal_port, + external_port, state->lease); - if (tor_fw_options->verbose) - fprintf(stdout, "tor-fw-helper: NAT-PMP sendnewportmappingrequest " + if (is_verbose) + fprintf(stderr, "tor-fw-helper: NAT-PMP sendnewportmappingrequest " "returned %d (%s)\n", r, r==12?"SUCCESS":"FAILED"); do { @@ -139,15 +141,15 @@ tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options, if (x == -1) return -1; - if (tor_fw_options->verbose) - fprintf(stdout, "V: attempting to readnatpmpreponseorretry...\n"); + if (is_verbose) + fprintf(stderr, "V: attempting to readnatpmpreponseorretry...\n"); r = readnatpmpresponseorretry(&(state->natpmp), &(state->response)); - sav_errno = errno; + sav_errno = tor_socket_errno(state->natpmp.s); if (r<0 && r!=NATPMP_TRYAGAIN) { fprintf(stderr, "E: readnatpmpresponseorretry failed %d\n", r); fprintf(stderr, "E: errno=%d '%s'\n", sav_errno, - strerror(sav_errno)); + tor_socket_strerror(sav_errno)); } } while (r == NATPMP_TRYAGAIN); @@ -163,16 +165,14 @@ tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options, } if (r == NATPMP_SUCCESS) { - fprintf(stdout, "tor-fw-helper: NAT-PMP mapped public port %hu to" + fprintf(stderr, "tor-fw-helper: NAT-PMP mapped public port %hu to" " localport %hu liftime %u\n", (state->response).pnu.newportmapping.mappedpublicport, (state->response).pnu.newportmapping.privateport, (state->response).pnu.newportmapping.lifetime); } - tor_fw_options->nat_pmp_status = 1; - - return r; + return (r == NATPMP_SUCCESS) ? 0 : -1; } /** Fetch our likely public IP from our upstream NAT-PMP enabled NAT device. @@ -189,7 +189,7 @@ tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options, struct timeval timeout; r = sendpublicaddressrequest(&(state->natpmp)); - fprintf(stdout, "tor-fw-helper: NAT-PMP sendpublicaddressrequest returned" + fprintf(stderr, "tor-fw-helper: NAT-PMP sendpublicaddressrequest returned" " %d (%s)\n", r, r==2?"SUCCESS":"FAILED"); do { @@ -200,19 +200,19 @@ tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options, return -1; if (tor_fw_options->verbose) - fprintf(stdout, "V: NAT-PMP attempting to read reponse...\n"); + fprintf(stderr, "V: NAT-PMP attempting to read reponse...\n"); r = readnatpmpresponseorretry(&(state->natpmp), &(state->response)); - sav_errno = errno; + sav_errno = tor_socket_errno(state->natpmp.s); if (tor_fw_options->verbose) - fprintf(stdout, "V: NAT-PMP readnatpmpresponseorretry returned" + fprintf(stderr, "V: NAT-PMP readnatpmpresponseorretry returned" " %d\n", r); if ( r < 0 && r != NATPMP_TRYAGAIN) { fprintf(stderr, "E: NAT-PMP readnatpmpresponseorretry failed %d\n", r); fprintf(stderr, "E: NAT-PMP errno=%d '%s'\n", sav_errno, - strerror(sav_errno)); + tor_socket_strerror(sav_errno)); } } while (r == NATPMP_TRYAGAIN ); @@ -223,15 +223,15 @@ tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options, return r; } - fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n", + fprintf(stderr, "tor-fw-helper: ExternalIPAddress = %s\n", inet_ntoa((state->response).pnu.publicaddress.addr)); tor_fw_options->public_ip_status = 1; if (tor_fw_options->verbose) { - fprintf(stdout, "V: result = %u\n", r); - fprintf(stdout, "V: type = %u\n", (state->response).type); - fprintf(stdout, "V: resultcode = %u\n", (state->response).resultcode); - fprintf(stdout, "V: epoch = %u\n", (state->response).epoch); + fprintf(stderr, "V: result = %u\n", r); + fprintf(stderr, "V: type = %u\n", (state->response).type); + fprintf(stderr, "V: resultcode = %u\n", (state->response).resultcode); + fprintf(stderr, "V: epoch = %u\n", (state->response).epoch); } return r; diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h index 54f541bcf4..2d924ce750 100644 --- a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h +++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h @@ -1,5 +1,5 @@ /* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2012, The Tor Project, Inc. */ + * Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -7,8 +7,8 @@ **/ #ifdef NAT_PMP -#ifndef _TOR_FW_HELPER_NATPMP_H -#define _TOR_FW_HELPER_NATPMP_H +#ifndef TOR_TOR_FW_HELPER_NATPMP_H +#define TOR_TOR_FW_HELPER_NATPMP_H #include <natpmp.h> @@ -36,8 +36,8 @@ int tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state); int tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state); -int tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options, - void *backend_state); +int tor_natpmp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, + int is_verbose, void *backend_state); int tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options, void *backend_state); diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.c b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c index 7c104f11cd..692186d372 100644 --- a/src/tools/tor-fw-helper/tor-fw-helper-upnp.c +++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c @@ -1,5 +1,5 @@ /* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2012, The Tor Project, Inc. */ + * Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -91,7 +91,7 @@ tor_upnp_init(tor_fw_options_t *options, void *backend_state) assert(options); r = UPNP_GetValidIGD(devlist, &(state->urls), &(state->data), state->lanaddr, UPNP_LANADDR_SZ); - fprintf(stdout, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r, + fprintf(stderr, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r, r==UPNP_SUCCESS?"SUCCESS":"FAILED"); freeUPNPDevlist(devlist); @@ -141,7 +141,7 @@ tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state) goto err; if (externalIPAddress[0]) { - fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n", + fprintf(stderr, "tor-fw-helper: ExternalIPAddress = %s\n", externalIPAddress); tor_upnp_cleanup(options, state); options->public_ip_status = 1; return UPNP_ERR_SUCCESS; @@ -154,44 +154,40 @@ tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state) return UPNP_ERR_GETEXTERNALIP; } -/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b> - * and store the results in <b>backend_state</b>. */ int -tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state) +tor_upnp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, + int is_verbose, void *backend_state) { - miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; - int r; + int retval; char internal_port_str[6]; char external_port_str[6]; + miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; if (!state->init) { - r = tor_upnp_init(options, state); - if (r != UPNP_ERR_SUCCESS) - return r; + fprintf(stderr, "E: %s but state is not initialized.\n", __func__); + return -1; } - if (options->verbose) - fprintf(stdout, "V: internal port: %d, external port: %d\n", - (int)options->internal_port, (int)options->external_port); + if (is_verbose) + fprintf(stderr, "V: UPnP: internal port: %u, external port: %u\n", + internal_port, external_port); tor_snprintf(internal_port_str, sizeof(internal_port_str), - "%d", (int)options->internal_port); + "%u", internal_port); tor_snprintf(external_port_str, sizeof(external_port_str), - "%d", (int)options->external_port); + "%u", external_port); - r = UPNP_AddPortMapping(state->urls.controlURL, - state->data.first.servicetype, - external_port_str, internal_port_str, + retval = UPNP_AddPortMapping(state->urls.controlURL, + state->data.first.servicetype, + external_port_str, internal_port_str, #ifdef MINIUPNPC15 - state->lanaddr, UPNP_DESC, "TCP", 0); + state->lanaddr, UPNP_DESC, "TCP", 0); #else - state->lanaddr, UPNP_DESC, "TCP", 0, 0); + state->lanaddr, UPNP_DESC, "TCP", 0, 0); #endif - if (r != UPNPCOMMAND_SUCCESS) - return UPNP_ERR_ADDPORTMAPPING; - options->upnp_status = 1; - return UPNP_ERR_SUCCESS; + return (retval == UPNP_ERR_SUCCESS) ? 0 : -1; } + #endif diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h index f037c75bab..b6c7ed8643 100644 --- a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h +++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h @@ -1,5 +1,5 @@ /* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2012, The Tor Project, Inc. */ + * Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -8,8 +8,8 @@ **/ #ifdef MINIUPNPC -#ifndef _TOR_FW_HELPER_UPNP_H -#define _TOR_FW_HELPER_UPNP_H +#ifndef TOR_TOR_FW_HELPER_UPNP_H +#define TOR_TOR_FW_HELPER_UPNP_H #include <miniupnpc/miniwget.h> #include <miniupnpc/miniupnpc.h> @@ -36,7 +36,8 @@ int tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state); int tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state); -int tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state); +int tor_upnp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, + int is_verbose, void *backend_state); #endif #endif diff --git a/src/tools/tor-fw-helper/tor-fw-helper.c b/src/tools/tor-fw-helper/tor-fw-helper.c index 0510e65d11..bb6e70aaa3 100644 --- a/src/tools/tor-fw-helper/tor-fw-helper.c +++ b/src/tools/tor-fw-helper/tor-fw-helper.c @@ -1,5 +1,5 @@ /* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2012, The Tor Project, Inc. */ + * Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -20,6 +20,9 @@ #include <getopt.h> #include <time.h> #include <string.h> +#include <assert.h> + +#include "container.h" #ifdef _WIN32 #include <winsock2.h> @@ -45,7 +48,7 @@ typedef struct backends_t { void *backend_state[MAX_BACKENDS]; } backends_t; -/** Initalize each backend helper with the user input stored in <b>options</b> +/** Initialize each backend helper with the user input stored in <b>options</b> * and put the results in the <b>backends</b> struct. */ static int init_backends(tor_fw_options_t *options, backends_t *backends) @@ -94,13 +97,10 @@ usage(void) { fprintf(stderr, "tor-fw-helper usage:\n" " [-h|--help]\n" - " [-T|--Test]\n" + " [-T|--test-commandline]\n" " [-v|--verbose]\n" " [-g|--fetch-public-ip]\n" - " -i|--internal-or-port [TCP port]\n" - " [-e|--external-or-port [TCP port]]\n" - " [-d|--internal-dir-port [TCP port]\n" - " [-p|--external-dir-port [TCP port]]]\n"); + " [-p|--forward-port ([<external port>]:<internal port>)]\n"); } /** Log commandline options to a hardcoded file <b>tor-fw-helper.log</b> in the @@ -125,7 +125,7 @@ log_commandline_options(int argc, char **argv) if (retval < 0) goto error; - retval = fprintf(stdout, "ARG: %d: %s\n", i, argv[i]); + retval = fprintf(stderr, "ARG: %d: %s\n", i, argv[i]); if (retval < 0) goto error; } @@ -152,82 +152,141 @@ tor_fw_fetch_public_ip(tor_fw_options_t *tor_fw_options, int r = 0; if (tor_fw_options->verbose) - fprintf(stdout, "V: tor_fw_fetch_public_ip\n"); + fprintf(stderr, "V: tor_fw_fetch_public_ip\n"); for (i=0; i<backends->n_backends; ++i) { if (tor_fw_options->verbose) { - fprintf(stdout, "V: running backend_state now: %i\n", i); - fprintf(stdout, "V: size of backend state: %u\n", + fprintf(stderr, "V: running backend_state now: %i\n", i); + fprintf(stderr, "V: size of backend state: %u\n", (int)(backends->backend_ops)[i].state_len); - fprintf(stdout, "V: backend state name: %s\n", + fprintf(stderr, "V: backend state name: %s\n", (char *)(backends->backend_ops)[i].name); } r = backends->backend_ops[i].fetch_public_ip(tor_fw_options, backends->backend_state[i]); - fprintf(stdout, "tor-fw-helper: tor_fw_fetch_public_ip backend %s " + fprintf(stderr, "tor-fw-helper: tor_fw_fetch_public_ip backend %s " " returned: %i\n", (char *)(backends->backend_ops)[i].name, r); } } -/** Iterate over each of the supported <b>backends</b> and attempt to add a - * port forward for the OR port stored in <b>tor_fw_options</b>. */ +/** Print a spec-conformant string to stdout describing the results of + * the TCP port forwarding operation from <b>external_port</b> to + * <b>internal_port</b>. */ static void -tor_fw_add_or_port(tor_fw_options_t *tor_fw_options, - backends_t *backends) +tor_fw_helper_report_port_fw_results(uint16_t internal_port, + uint16_t external_port, + int succeded, + const char *message) +{ + char *report_string = NULL; + + tor_asprintf(&report_string, "%s %s %u %u %s %s\n", + "tor-fw-helper", + "tcp-forward", + external_port, internal_port, + succeded ? "SUCCESS" : "FAIL", + message); + fprintf(stdout, "%s", report_string); + fflush(stdout); + tor_free(report_string); +} + +#define tor_fw_helper_report_port_fw_fail(i, e, m) \ + tor_fw_helper_report_port_fw_results((i), (e), 0, (m)) + +#define tor_fw_helper_report_port_fw_success(i, e, m) \ + tor_fw_helper_report_port_fw_results((i), (e), 1, (m)) + +/** Return a heap-allocated string containing the list of our + * backends. It can be used in log messages. Be sure to free it + * afterwards! */ +static char * +get_list_of_backends_string(backends_t *backends) { + char *backend_names = NULL; int i; - int r = 0; + smartlist_t *backend_names_sl = smartlist_new(); - if (tor_fw_options->verbose) - fprintf(stdout, "V: tor_fw_add_or_port\n"); + assert(backends->n_backends); - for (i=0; i<backends->n_backends; ++i) { - if (tor_fw_options->verbose) { - fprintf(stdout, "V: running backend_state now: %i\n", i); - fprintf(stdout, "V: size of backend state: %u\n", - (int)(backends->backend_ops)[i].state_len); - fprintf(stdout, "V: backend state name: %s\n", - (const char *) backends->backend_ops[i].name); - } - r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options, - backends->backend_state[i]); - fprintf(stdout, "tor-fw-helper: tor_fw_add_or_port backend %s " - "returned: %i\n", (const char *) backends->backend_ops[i].name, r); - } + for (i=0; i<backends->n_backends; ++i) + smartlist_add(backend_names_sl, (char *) backends->backend_ops[i].name); + + backend_names = smartlist_join_strings(backend_names_sl, ", ", 0, NULL); + smartlist_free(backend_names_sl); + + return backend_names; } /** Iterate over each of the supported <b>backends</b> and attempt to add a - * port forward for the Dir port stored in <b>tor_fw_options</b>. */ + * port forward for the port stored in <b>tor_fw_options</b>. */ static void -tor_fw_add_dir_port(tor_fw_options_t *tor_fw_options, - backends_t *backends) +tor_fw_add_ports(tor_fw_options_t *tor_fw_options, + backends_t *backends) { int i; int r = 0; + int succeeded = 0; if (tor_fw_options->verbose) - fprintf(stdout, "V: tor_fw_add_dir_port\n"); + fprintf(stderr, "V: %s\n", __func__); - for (i=0; i<backends->n_backends; ++i) { - if (tor_fw_options->verbose) { - fprintf(stdout, "V: running backend_state now: %i\n", i); - fprintf(stdout, "V: size of backend state: %u\n", - (int)(backends->backend_ops)[i].state_len); - fprintf(stdout, "V: backend state name: %s\n", - (char *)(backends->backend_ops)[i].name); + /** Loop all ports that need to be forwarded, and try to use our + * backends for each port. If a backend succeeds, break the loop, + * report success and get to the next port. If all backends fail, + * report failure for that port. */ + SMARTLIST_FOREACH_BEGIN(tor_fw_options->ports_to_forward, + port_to_forward_t *, port_to_forward) { + + succeeded = 0; + + for (i=0; i<backends->n_backends; ++i) { + if (tor_fw_options->verbose) { + fprintf(stderr, "V: running backend_state now: %i\n", i); + fprintf(stderr, "V: size of backend state: %u\n", + (int)(backends->backend_ops)[i].state_len); + fprintf(stderr, "V: backend state name: %s\n", + (const char *) backends->backend_ops[i].name); + } + + r = + backends->backend_ops[i].add_tcp_mapping(port_to_forward->internal_port, + port_to_forward->external_port, + tor_fw_options->verbose, + backends->backend_state[i]); + if (r == 0) { /* backend success */ + tor_fw_helper_report_port_fw_success(port_to_forward->internal_port, + port_to_forward->external_port, + backends->backend_ops[i].name); + succeeded = 1; + break; + } + + fprintf(stderr, "tor-fw-helper: tor_fw_add_port backend %s " + "returned: %i\n", + (const char *) backends->backend_ops[i].name, r); } - r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options, - backends->backend_state[i]); - fprintf(stdout, "tor-fw-helper: tor_fw_add_dir_port backend %s " - "returned: %i\n", (const char *)backends->backend_ops[i].name, r); - } + + if (!succeeded) { /* all backends failed */ + char *list_of_backends_str = get_list_of_backends_string(backends); + char *fail_msg = NULL; + tor_asprintf(&fail_msg, "All port forwarding backends (%s) failed.", + list_of_backends_str); + tor_fw_helper_report_port_fw_fail(port_to_forward->internal_port, + port_to_forward->external_port, + fail_msg); + tor_free(list_of_backends_str); + tor_free(fail_msg); + } + + } SMARTLIST_FOREACH_END(port_to_forward); } /** Called before we make any calls to network-related functions. * (Some operating systems require their network libraries to be * initialized.) (from common/compat.c) */ static int -network_init(void) +tor_fw_helper_network_init(void) { #ifdef _WIN32 /* This silly exercise is necessary before windows will allow @@ -247,6 +306,67 @@ network_init(void) return 0; } +/** Parse the '-p' argument of tor-fw-helper. Its format is + * [<external port>]:<internal port>, and <external port> is optional. + * Return NULL if <b>arg</b> was c0rrupted. */ +static port_to_forward_t * +parse_port(const char *arg) +{ + smartlist_t *sl = smartlist_new(); + port_to_forward_t *port_to_forward = NULL; + char *port_str = NULL; + int ok; + int port; + + smartlist_split_string(sl, arg, ":", 0, 0); + if (smartlist_len(sl) != 2) + goto err; + + port_to_forward = tor_malloc(sizeof(port_to_forward_t)); + if (!port_to_forward) + goto err; + + port_str = smartlist_get(sl, 0); /* macroify ? */ + port = (int)tor_parse_long(port_str, 10, 1, 65535, &ok, NULL); + if (!ok && strlen(port_str)) /* ":1555" is valid */ + goto err; + port_to_forward->external_port = port; + + port_str = smartlist_get(sl, 1); + port = (int)tor_parse_long(port_str, 10, 1, 65535, &ok, NULL); + if (!ok) + goto err; + port_to_forward->internal_port = port; + + goto done; + + err: + tor_free(port_to_forward); + + done: + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + smartlist_free(sl); + + return port_to_forward; +} + +/** Report a failure of epic proportions: We didn't manage to + * initialize any port forwarding backends. */ +static void +report_full_fail(const smartlist_t *ports_to_forward) +{ + if (!ports_to_forward) + return; + + SMARTLIST_FOREACH_BEGIN(ports_to_forward, + const port_to_forward_t *, port_to_forward) { + tor_fw_helper_report_port_fw_fail(port_to_forward->internal_port, + port_to_forward->external_port, + "All backends (NAT-PMP, UPnP) failed " + "to initialize!"); /* XXX hardcoded */ + } SMARTLIST_FOREACH_END(port_to_forward); +} + int main(int argc, char **argv) { @@ -259,22 +379,20 @@ main(int argc, char **argv) memset(&tor_fw_options, 0, sizeof(tor_fw_options)); memset(&backend_state, 0, sizeof(backend_state)); + // Parse CLI arguments. while (1) { int option_index = 0; static struct option long_options[] = { {"verbose", 0, 0, 'v'}, {"help", 0, 0, 'h'}, - {"internal-or-port", 1, 0, 'i'}, - {"external-or-port", 1, 0, 'e'}, - {"internal-dir-port", 1, 0, 'd'}, - {"external-dir-port", 1, 0, 'p'}, + {"port", 1, 0, 'p'}, {"fetch-public-ip", 0, 0, 'g'}, {"test-commandline", 0, 0, 'T'}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "vhi:e:d:p:gT", + c = getopt_long(argc, argv, "vhp:gT", long_options, &option_index); if (c == -1) break; @@ -282,14 +400,31 @@ main(int argc, char **argv) switch (c) { case 'v': tor_fw_options.verbose = 1; break; case 'h': tor_fw_options.help = 1; usage(); exit(1); break; - case 'i': sscanf(optarg, "%hu", &tor_fw_options.private_or_port); - break; - case 'e': sscanf(optarg, "%hu", &tor_fw_options.public_or_port); - break; - case 'd': sscanf(optarg, "%hu", &tor_fw_options.private_dir_port); - break; - case 'p': sscanf(optarg, "%hu", &tor_fw_options.public_dir_port); + case 'p': { + port_to_forward_t *port_to_forward = parse_port(optarg); + if (!port_to_forward) { + fprintf(stderr, "E: Failed to parse '%s'.\n", optarg); + usage(); + exit(1); + } + + /* If no external port was given (it's optional), set it to be + * equal with the internal port. */ + if (!port_to_forward->external_port) { + assert(port_to_forward->internal_port); + if (tor_fw_options.verbose) + fprintf(stderr, "V: No external port was given. Setting to %u.\n", + port_to_forward->internal_port); + port_to_forward->external_port = port_to_forward->internal_port; + } + + if (!tor_fw_options.ports_to_forward) + tor_fw_options.ports_to_forward = smartlist_new(); + + smartlist_add(tor_fw_options.ports_to_forward, port_to_forward); + break; + } case 'g': tor_fw_options.fetch_public_ip = 1; break; case 'T': tor_fw_options.test_commandline = 1; break; case '?': break; @@ -297,98 +432,68 @@ main(int argc, char **argv) } } - if (tor_fw_options.verbose) { - fprintf(stderr, "V: tor-fw-helper version %s\n" - "V: We were called with the following arguments:\n" - "V: verbose = %d, help = %d, pub or port = %u, " - "priv or port = %u\n" - "V: pub dir port = %u, priv dir port = %u\n" - "V: fetch_public_ip = %u\n", - tor_fw_version, tor_fw_options.verbose, tor_fw_options.help, - tor_fw_options.private_or_port, tor_fw_options.public_or_port, - tor_fw_options.private_dir_port, tor_fw_options.public_dir_port, - tor_fw_options.fetch_public_ip); + { // Verbose output + + if (tor_fw_options.verbose) + fprintf(stderr, "V: tor-fw-helper version %s\n" + "V: We were called with the following arguments:\n" + "V: verbose = %d, help = %d, fetch_public_ip = %u\n", + tor_fw_version, tor_fw_options.verbose, tor_fw_options.help, + tor_fw_options.fetch_public_ip); + + if (tor_fw_options.verbose && tor_fw_options.ports_to_forward) { + fprintf(stderr, "V: TCP forwarding:\n"); + SMARTLIST_FOREACH(tor_fw_options.ports_to_forward, + const port_to_forward_t *, port_to_forward, + fprintf(stderr, "V: External: %u, Internal: %u\n", + port_to_forward->external_port, + port_to_forward->internal_port)); + } } if (tor_fw_options.test_commandline) { return log_commandline_options(argc, argv); } - /* At the very least, we require an ORPort; - Given a private ORPort, we can ask for a mapping that matches the port - externally. - */ - if (!tor_fw_options.private_or_port && !tor_fw_options.fetch_public_ip) { - fprintf(stderr, "E: We require an ORPort or fetch_public_ip" - " request!\n"); + // See if the user actually wants us to do something. + if (!tor_fw_options.fetch_public_ip && !tor_fw_options.ports_to_forward) { + fprintf(stderr, "E: We require a port to be forwarded or " + "fetch_public_ip request!\n"); usage(); exit(1); - } else { - /* When we only have one ORPort, internal/external are - set to be the same.*/ - if (!tor_fw_options.public_or_port && tor_fw_options.private_or_port) { - if (tor_fw_options.verbose) - fprintf(stdout, "V: We're setting public_or_port = " - "private_or_port.\n"); - tor_fw_options.public_or_port = tor_fw_options.private_or_port; - } - } - if (!tor_fw_options.private_dir_port) { - if (tor_fw_options.verbose) - fprintf(stdout, "V: We have no DirPort; no hole punching for " - "DirPorts\n"); - - } else { - /* When we only have one DirPort, internal/external are - set to be the same.*/ - if (!tor_fw_options.public_dir_port && tor_fw_options.private_dir_port) { - if (tor_fw_options.verbose) - fprintf(stdout, "V: We're setting public_or_port = " - "private_or_port.\n"); - - tor_fw_options.public_dir_port = tor_fw_options.private_dir_port; - } - } - - if (tor_fw_options.verbose) { - fprintf(stdout, "V: pub or port = %u, priv or port = %u\n" - "V: pub dir port = %u, priv dir port = %u\n", - tor_fw_options.private_or_port, tor_fw_options.public_or_port, - tor_fw_options.private_dir_port, - tor_fw_options.public_dir_port); } // Initialize networking - if (network_init()) + if (tor_fw_helper_network_init()) exit(1); // Initalize the various fw-helper backend helpers r = init_backends(&tor_fw_options, &backend_state); - if (r) - printf("tor-fw-helper: %i NAT traversal helper(s) loaded\n", r); - - if (tor_fw_options.fetch_public_ip) { - tor_fw_fetch_public_ip(&tor_fw_options, &backend_state); + if (!r) { // all backends failed: + // report our failure + report_full_fail(tor_fw_options.ports_to_forward); + fprintf(stderr, "tor-fw-helper: All backends failed.\n"); + exit(1); + } else { // some backends succeeded: + fprintf(stderr, "tor-fw-helper: %i NAT traversal helper(s) loaded\n", r); } - if (tor_fw_options.private_or_port) { - tor_fw_options.internal_port = tor_fw_options.private_or_port; - tor_fw_options.external_port = tor_fw_options.private_or_port; - tor_fw_add_or_port(&tor_fw_options, &backend_state); + // Forward TCP ports. + if (tor_fw_options.ports_to_forward) { + tor_fw_add_ports(&tor_fw_options, &backend_state); } - if (tor_fw_options.private_dir_port) { - tor_fw_options.internal_port = tor_fw_options.private_dir_port; - tor_fw_options.external_port = tor_fw_options.private_dir_port; - tor_fw_add_dir_port(&tor_fw_options, &backend_state); + // Fetch our public IP. + if (tor_fw_options.fetch_public_ip) { + tor_fw_fetch_public_ip(&tor_fw_options, &backend_state); } - r = (((tor_fw_options.nat_pmp_status | tor_fw_options.upnp_status) - |tor_fw_options.public_ip_status)); - if (r > 0) { - fprintf(stdout, "tor-fw-helper: SUCCESS\n"); - } else { - fprintf(stderr, "tor-fw-helper: FAILURE\n"); + // Cleanup and exit. + if (tor_fw_options.ports_to_forward) { + SMARTLIST_FOREACH(tor_fw_options.ports_to_forward, + port_to_forward_t *, port, + tor_free(port)); + smartlist_free(tor_fw_options.ports_to_forward); } exit(r); diff --git a/src/tools/tor-fw-helper/tor-fw-helper.h b/src/tools/tor-fw-helper/tor-fw-helper.h index 058afc4e09..0b0d179935 100644 --- a/src/tools/tor-fw-helper/tor-fw-helper.h +++ b/src/tools/tor-fw-helper/tor-fw-helper.h @@ -1,5 +1,5 @@ /* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2012, The Tor Project, Inc. */ + * Copyright (c) 2010-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -7,8 +7,8 @@ * \brief The main header for our firewall helper. **/ -#ifndef _TOR_FW_HELPER_H -#define _TOR_FW_HELPER_H +#ifndef TOR_TOR_FW_HELPER_H +#define TOR_TOR_FW_HELPER_H #include <stdint.h> #include <stdio.h> @@ -17,24 +17,26 @@ #include <time.h> /** The current version of tor-fw-helper. */ -#define tor_fw_version "0.1" +#define tor_fw_version "0.2" /** This is an arbitrary hard limit - We currently have two (NAT-PMP and UPnP). We're likely going to add the Intel UPnP library but nothing else comes to mind at the moment. */ #define MAX_BACKENDS 23 +/** Forward traffic received in port <b>external_port</b> in the + * external side of our NAT to <b>internal_port</b> in this host. */ +typedef struct { + uint16_t external_port; + uint16_t internal_port; +} port_to_forward_t; + /** This is where we store parsed commandline options. */ typedef struct { int verbose; int help; int test_commandline; - uint16_t private_dir_port; - uint16_t private_or_port; - uint16_t public_dir_port; - uint16_t public_or_port; - uint16_t internal_port; - uint16_t external_port; + struct smartlist_t *ports_to_forward; int fetch_public_ip; int nat_pmp_status; int upnp_status; @@ -50,8 +52,8 @@ typedef struct tor_fw_backend_t { int (*init)(tor_fw_options_t *options, void *backend_state); int (*cleanup)(tor_fw_options_t *options, void *backend_state); int (*fetch_public_ip)(tor_fw_options_t *options, void *backend_state); - int (*add_tcp_mapping)(tor_fw_options_t *options, void *backend_state); + int (*add_tcp_mapping)(uint16_t internal_port, uint16_t external_port, + int is_verbose, void *backend_state); } tor_fw_backend_t; - #endif diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c index c7ab8dc615..3809b22d43 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2012, The Tor Project, Inc. */ +/* Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" @@ -82,10 +82,11 @@ crypto_log_errors(int severity, const char *doing) if (!lib) lib = "(null)"; if (!func) func = "(null)"; if (doing) { - log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)", - doing, msg, lib, func); + tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)", + doing, msg, lib, func); } else { - log(severity, LD_CRYPTO, "crypto error: %s (in %s:%s)", msg, lib, func); + tor_log(severity, LD_CRYPTO, "crypto error: %s (in %s:%s)", + msg, lib, func); } } } @@ -227,7 +228,7 @@ generate_key(int bits) crypto_pk_t *env = crypto_pk_new(); if (crypto_pk_generate_key_with_bits(env,bits)<0) goto done; - rsa = _crypto_pk_get_rsa(env); + rsa = crypto_pk_get_rsa_(env); rsa = RSAPrivateKey_dup(rsa); done: crypto_pk_free(env); @@ -401,7 +402,7 @@ static int get_fingerprint(EVP_PKEY *pkey, char *out) { int r = 1; - crypto_pk_t *pk = _crypto_new_pk_from_rsa(EVP_PKEY_get1_RSA(pkey)); + crypto_pk_t *pk = crypto_new_pk_from_rsa_(EVP_PKEY_get1_RSA(pkey)); if (pk) { r = crypto_pk_get_fingerprint(pk, out, 0); crypto_pk_free(pk); @@ -414,7 +415,7 @@ static int get_digest(EVP_PKEY *pkey, char *out) { int r = 1; - crypto_pk_t *pk = _crypto_new_pk_from_rsa(EVP_PKEY_get1_RSA(pkey)); + crypto_pk_t *pk = crypto_new_pk_from_rsa_(EVP_PKEY_get1_RSA(pkey)); if (pk) { r = crypto_pk_get_digest(pk, out); crypto_pk_free(pk); diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c index 4ef84f491c..306f6c66ab 100644 --- a/src/tools/tor-resolve.c +++ b/src/tools/tor-resolve.c @@ -1,10 +1,9 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson - * Copyright (c) 2007-2012, The Tor Project, Inc. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" - #include "compat.h" #include "../common/util.h" #include "address.h" @@ -74,23 +73,29 @@ build_socks_resolve_request(char **out, memcpy((*out)+8+strlen(username)+1, hostname, strlen(hostname)+1); } else if (version == 5) { int is_ip_address; - struct in_addr in; + tor_addr_t addr; size_t addrlen; - is_ip_address = tor_inet_aton(hostname, &in); + int ipv6; + is_ip_address = tor_addr_parse(&addr, hostname) != -1; if (!is_ip_address && reverse) { log_err(LD_GENERAL, "Tried to do a reverse lookup on a non-IP!"); return -1; } - addrlen = reverse ? 4 : 1 + strlen(hostname); + ipv6 = reverse && tor_addr_family(&addr) == AF_INET6; + addrlen = reverse ? (ipv6 ? 16 : 4) : 1 + strlen(hostname); len = 6 + addrlen; *out = tor_malloc(len); (*out)[0] = 5; /* SOCKS version 5 */ (*out)[1] = reverse ? '\xF1' : '\xF0'; /* RESOLVE_PTR or RESOLVE */ (*out)[2] = 0; /* reserved. */ - (*out)[3] = reverse ? 1 : 3; if (reverse) { - set_uint32((*out)+4, in.s_addr); + (*out)[3] = ipv6 ? 4 : 1; + if (ipv6) + memcpy((*out)+4, tor_addr_to_in6_addr8(&addr), 16); + else + set_uint32((*out)+4, tor_addr_to_ipv4n(&addr)); } else { + (*out)[3] = 3; (*out)[4] = (char)(uint8_t)(addrlen - 1); memcpy((*out)+5, hostname, addrlen - 1); } @@ -109,7 +114,7 @@ build_socks_resolve_request(char **out, static int parse_socks4a_resolve_response(const char *hostname, const char *response, size_t len, - uint32_t *addr_out) + tor_addr_t *addr_out) { uint8_t status; tor_assert(response); @@ -140,7 +145,7 @@ parse_socks4a_resolve_response(const char *hostname, return -1; } - *addr_out = ntohl(get_uint32(response+4)); + tor_addr_from_ipv4n(addr_out, get_uint32(response+4)); return 0; } @@ -179,9 +184,9 @@ socks5_reason_to_string(char reason) static int do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, int reverse, int version, - uint32_t *result_addr, char **result_hostname) + tor_addr_t *result_addr, char **result_hostname) { - int s; + int s = -1; struct sockaddr_in socksaddr; char *req = NULL; ssize_t len = 0; @@ -190,7 +195,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, tor_assert(result_addr); tor_assert(version == 4 || version == 5); - *result_addr = 0; + tor_addr_make_unspec(result_addr); *result_hostname = NULL; s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); @@ -205,28 +210,28 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, socksaddr.sin_addr.s_addr = htonl(sockshost); if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) { log_sock_error("connecting to SOCKS host", s); - return -1; + goto err; } if (version == 5) { char method_buf[2]; if (write_all(s, "\x05\x01\x00", 3, 1) != 3) { log_err(LD_NET, "Error sending SOCKS5 method list."); - return -1; + goto err; } if (read_all(s, method_buf, 2, 1) != 2) { log_err(LD_NET, "Error reading SOCKS5 methods."); - return -1; + goto err; } if (method_buf[0] != '\x05') { log_err(LD_NET, "Unrecognized socks version: %u", (unsigned)method_buf[0]); - return -1; + goto err; } if (method_buf[1] != '\x00') { log_err(LD_NET, "Unrecognized socks authentication method: %u", (unsigned)method_buf[1]); - return -1; + goto err; } } @@ -234,12 +239,12 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, version))<0) { log_err(LD_BUG,"Error generating SOCKS request"); tor_assert(!req); - return -1; + goto err; } if (write_all(s, req, len, 1) != len) { log_sock_error("sending SOCKS request", s); tor_free(req); - return -1; + goto err; } tor_free(req); @@ -247,22 +252,22 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, char reply_buf[RESPONSE_LEN_4]; if (read_all(s, reply_buf, RESPONSE_LEN_4, 1) != RESPONSE_LEN_4) { log_err(LD_NET, "Error reading SOCKS4 response."); - return -1; + goto err; } if (parse_socks4a_resolve_response(hostname, reply_buf, RESPONSE_LEN_4, result_addr)<0) { - return -1; + goto err; } } else { - char reply_buf[4]; + char reply_buf[16]; if (read_all(s, reply_buf, 4, 1) != 4) { log_err(LD_NET, "Error reading SOCKS5 response."); - return -1; + goto err; } if (reply_buf[0] != 5) { log_err(LD_NET, "Bad SOCKS5 reply version."); - return -1; + goto err; } /* Give a user some useful feedback about SOCKS5 errors */ if (reply_buf[1] != 0) { @@ -276,32 +281,44 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, "to Tor; we suggest an application that uses SOCKS 4a.", hostname); } - return -1; + goto err; } if (reply_buf[3] == 1) { /* IPv4 address */ if (read_all(s, reply_buf, 4, 1) != 4) { log_err(LD_NET, "Error reading address in socks5 response."); - return -1; + goto err; + } + tor_addr_from_ipv4n(result_addr, get_uint32(reply_buf)); + } else if (reply_buf[3] == 4) { + /* IPv6 address */ + if (read_all(s, reply_buf, 16, 1) != 16) { + log_err(LD_NET, "Error reading address in socks5 response."); + goto err; } - *result_addr = ntohl(get_uint32(reply_buf)); + tor_addr_from_ipv6_bytes(result_addr, reply_buf); } else if (reply_buf[3] == 3) { + /* Domain name */ size_t result_len; if (read_all(s, reply_buf, 1, 1) != 1) { log_err(LD_NET, "Error reading address_length in socks5 response."); - return -1; + goto err; } result_len = *(uint8_t*)(reply_buf); *result_hostname = tor_malloc(result_len+1); if (read_all(s, *result_hostname, result_len, 1) != (int) result_len) { log_err(LD_NET, "Error reading hostname in socks5 response."); - return -1; + goto err; } (*result_hostname)[result_len] = '\0'; } } + tor_close_socket(s); return 0; + err: + tor_close_socket(s); + return -1; } /** Print a usage message and exit. */ @@ -322,10 +339,8 @@ main(int argc, char **argv) int isSocks4 = 0, isVerbose = 0, isReverse = 0; char **arg; int n_args; - struct in_addr a; - uint32_t result = 0; + tor_addr_t result; char *result_hostname = NULL; - char buf[INET_NTOA_BUF_LEN]; log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t)); init_logging(); @@ -423,9 +438,7 @@ main(int argc, char **argv) if (result_hostname) { printf("%s\n", result_hostname); } else { - a.s_addr = htonl(result); - tor_inet_ntoa(&a, buf, sizeof(buf)); - printf("%s\n", buf); + printf("%s\n", fmt_addr(&result)); } return 0; } diff --git a/src/win32/Makefile.am b/src/win32/Makefile.am deleted file mode 100644 index 7f5d742481..0000000000 --- a/src/win32/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ - -EXTRA_DIST = orconfig.h - diff --git a/src/win32/include.am b/src/win32/include.am new file mode 100644 index 0000000000..dad59af3ae --- /dev/null +++ b/src/win32/include.am @@ -0,0 +1,3 @@ + +EXTRA_DIST+= src/win32/orconfig.h + diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index d780d5d73d..9e0a41a47d 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -145,9 +145,15 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `_vscprintf' function. */ +#define HAVE__VSCPRINTF 1 + /* Define to 1 iff NULL is represented by a 0 in memory. */ #define NULL_REP_IS_ZERO_BYTES 1 +/* Define to 1 iff memset(0) sets doubles to 0.0 */ +#define DOUBLE_0_REP_IS_ZERO_BYTES 1 + /* Name of package */ #define PACKAGE "tor" @@ -190,6 +196,9 @@ /* The size of a `long long', as computed by sizeof. */ #undef SIZEOF_LONG_LONG +/* The size of `pid_t', as computed by sizeof. */ +#define SIZEOF_PID_T 0 + /* The size of a `short', as computed by sizeof. */ #define SIZEOF_SHORT 2 @@ -232,7 +241,7 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.3.18-rc-dev" +#define VERSION "0.2.4.22-dev" @@ -242,3 +251,9 @@ #define FLEXIBLE_ARRAY_MEMBER 0 #define HAVE_EVENT2_EVENT_H #define SHARE_DATADIR "" +#define HAVE_EVENT2_DNS_H +#define HAVE_EVENT_BASE_LOOPEXIT +#define CURVE25519_ENABLED +#define USE_CURVE25519_DONNA + +#define ENUM_VALS_ARE_SIGNED 1 |